-
-
Notifications
You must be signed in to change notification settings - Fork 395
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keyword args support causes expected values to coerce to Hash #1241
Comments
I can't look at this much right now, but could you provide a code example of unexpected behavior? |
@marcandre The snippit provided simulates what happens inside rspec-expectations... in context, the expected value gets coerced before it gets to e.q an I will create a small rspec example as well. |
It may be possible to revisit this, the |
@headius can you furnish us with a spec that will break with this on |
This is one of the reasons we separated keyword args in Ruby 3, because if an object responds to to_hash, it could be treated as keywords even if not passed as keywords in Ruby 2. The approach here (https://github.com/rspec/rspec-expectations/pull/1187/files#diff-4bff1e98c288b9ed0d824e9ac97c878795f2b67718dcf28cb47082620a442a09R184) looks wrong. You should use |
@jeremyevans We have tried to use |
The solution we have where it is was a last resort, we don't want string eval'd code if possible |
This fails on rspec-expectations 3.9.3 and later. I think it should pass. describe "A non-Hash value with to_hash defined" do
it "does not coerce when passed through an equal? expectation" do
cls = Class.new { def to_hash; {a:1}; end }
obj = cls.new
expect(obj).to be_equal(obj)
end
end |
If If |
|
Does the RSpec team plans to work on this? I think we should replace all I tried to clarify that in a tweet, since it seems many people got confused about "what's the correct way to do delegation for Ruby 2.7, compatible with <=2.6 and Ruby 3?". The only answer is |
@eregon Yes, we definitely plan to work on this. In the new few days we're focused on pushing I keep a bookmark to this comment of yours that explains that What concerns me is that klass = class << self
# See `Macros#define_user_override` above, for an explanation.
include(@user_method_defs = Module.new)
self
end
RSpec::Support::WithKeywordsWhenNeeded.class_exec(klass, *expected, &declarations) What is the correct approach for the above case? Also, I haven't checked Jeremy's note above in detail, but it sounds like in some cases we're might be cornered with clean support of both recent major Ruby versions. It's not that I'm trying to push the responsibility to you, but an informed advise would help to move this forward a bit quicker. |
Assuming you want to pass keywords through the ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true) The approach of using |
This comment has been minimized.
This comment has been minimized.
It's worth noting that we don't do The RSpec team are fully aware of |
@headius Your supplied spec passes for me on 3.10 which is our current supported version, can you give that a try? (edit I can confirm it doesn't work on 3.9.3, but 3.9.4 and 3.10 it passes, which I believe when I replaced the use of **kwargs in the helper and used ruby2_keywords) |
It's actually easiest to use Ruby 3 to find the places you need to add |
@jeremyevans We have passing builds for Ruby 3, part of the problem we've had is that people have use keyword argument support in ways we haven't anticipated (like in blocks supplied to things for example) and thus don't have specs for. It's always worked because we just delegate everything. |
The proactive approach in this case is to look at every method in RSpec that accepts |
@JonRowe Indeed it does! That is sufficient for me. jruby/jruby#6505 |
Closing this since the issue has apparently been resolved. |
In jruby/jruby#6452 we discovered that a recent update to rspec-expectations (#1187) started causing Java HashMap to coerce to Hash, triggering a failure in our tests of HashMap integration.
The coercion behavior appears to match CRuby, and we are debating whether Java HashMap should even support
to_hash
, but the behavior in rspec may be problematic. Any expected value object passed through the same logic will end up coercing to Hash if it defines an appropriateto_hash
, which seems...unexpected.I do not have a solution to offer, but wanted to bring it up here since it seems peculiar that an RSpec expectation would cause a value to coerce... as in our case I would expect it to pass through without modification or conversion.
Note that the behavior of coercing the last argument to a Hash will go away in Ruby 3.0, which will avoid this behavior... but it affects 2.7 (with a warning) and lower.
Isolated example not using JRuby Java integration (this simulates passing through the code from #1187):
CC @eregon @jeremyevans @marcandre since I believe they have been part of debates on kwargs behavior going forward.
The text was updated successfully, but these errors were encountered: