未验证 提交 d043920e 编写于 作者: S Simon Courtois 提交者: Rafael Mendonça França

Fixing an edge case when using objects as constraints

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.
上级 d0d1cd3d
......@@ -50,7 +50,19 @@ def serve(req)
private
def constraint_args(constraint, request)
constraint.arity == 1 ? [request] : [request.path_parameters, request]
arity = if constraint.respond_to?(:arity)
constraint.arity
else
constraint.method(:call).arity
end
if arity < 1
[]
elsif arity == 1
[request]
else
[request.path_parameters, request]
end
end
end
......
......@@ -115,6 +115,21 @@ def test_redirect_with_passing_constraint
assert_equal 301, status
end
def test_accepts_a_constraint_object_responding_to_call
constraint = Class.new do
def call(*); true; end
def matches?(*); false; end
end
draw do
get "/", to: "home#show", constraints: constraint.new
end
assert_nothing_raised do
get "/"
end
end
def test_namespace_with_controller_segment
assert_raise(ArgumentError) do
draw do
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册