-
Notifications
You must be signed in to change notification settings - Fork 21.3k
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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixing an edge case when using objects as constraints #34004
Conversation
This PR fixes an issue when the following situation occurs. If you define a class like this class MyConstraint def call(*args) # for some reason this is defined end def matches?(*args) # checking the args end end and try to use it as a constraint get "/", to: "home#show", constraints: MyConstraint.new if its `matches?` method returns `false` there will be an error for the mapper will ask for the constraint arity, thinking it is a proc, lambda or method. This PR checks for the presence of the `arity` method on the constraint calling it only if present, preventing the error while keeping the basic behavior.
Isn't the problem going to be the same if the Maybe it would be be better to check if the object is a proc instead of looking if it responds to |
end | ||
end | ||
private :constraint_args |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you changed the way the private method is defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rafaelfranca I changed it because it was like that in other places of the same file 馃槉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 187 and 192 for instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to leave as it is. Line 255 is using the previous code.
@Edouard-chin I thought about it but didn't want to make too big of a change. I suppose I could simply ask for the arity of the Something like def constraint_args(constraint, request)
arity =
if constraint.respond_to?(:arity)
constraint.arity
else
constraint.method(:call).arity
end
return [] if arity < 1
return [request] if arity == 1
[request.path_parameters, request]
end I guess this doesn't cover the case where the |
If the |
@rafaelfranca alright, I'll update the code to the one in my previous comment. Any convention regarding the edit: Ok apparently the convention is the following so I will do that arity = if constraint.respond_to?(:arity)
constraint.arity
else
constraint.method(:call).arity
end |
Merged in 6a73faa |
Fixing an edge case when using objects as constraints
Hello 馃槉
Summary
This PR fixes an issue when the following situation occurs.
If you define a class like this:
and try to use it as a constraint:
if its
matches?
method returnsfalse
there will be an error because the mapper will ask for the constraint arity, thinking it is a proc, lambda or method.The new code checks for the presence of the
arity
method on the constraint, calling it only if present, preventing the error while keeping the basic behavior.