Rails 4 中作用域的元数

5

我知道如何检查lambda的arity(函数参数个数),但我不知道如何从作用域中提取它。

这个问题是4年前提出的:

https://groups.google.com/forum/#!topic/rubyonrails-core/7Cs0T34mj8c

All, In the course of working on a change for the meta-search gem I've run into an issue with the way that scopes are implemented in ActiveRecord. In order to include a scope in a search we pass the name of the scope to a search method like so: {:name_of_my_scope => 1}. Meta-search automatically passes the "1" as an argument to the scope. This causes an ArgumentError with lambda scopes that don't take an argument.

My intention was to check the arity of the scope before calling and dropping the "1" in the event the scope didn't take an argument. My issue is that the implementation of scope wraps scope_options up in a lambda that passes *args to the block (active_record/named_scope.rb: 106). This results in the call to arity always returning -1 regardless of the actual number of arguments required by the scope definition.

Is there a different way to implement scopes that would allow exposing the arity from the scope definition?

Ex.

class Post < ActiveRecord::Base  
     scope :today, lambda {where(:created_at => (Time.new.beginning_of_day...(Time.new.end_of_day)) }  
  end 

irb> Post.today.arity # => -1

在调用作用域之前,它要求帮助查找其数量。

已经找到解决方案了吗?

1个回答

2
下面展示的scope方法没有明确的参数。
irb(main):070:0> User.method(:active_users).parameters
=> [[:rest, :args]]
:rest 表示参数被收集成一个数组。这允许没有参数或任意数量的参数。
对于接受参数的作用域,如果您使用错误数量的参数调用,则会收到 ArgumentError - 就像下面这样:
ArgumentError: wrong number of arguments (1 for 2)

我们可以利用这个ArgumentError来确定arity,因为arity在错误信息中存在。
让我提醒一下,这有点像黑客技巧,如果你迫切需要确定基于lambda的作用域的arity,它可能会有用。
我们可以在Model中定义一个方法,尝试使用非常大数量的参数调用scope,比如100个参数,从而强制抛出ArgumentError,然后我们可以捕获消息并从中提取arity。
下面是这种方法的一种可能实现:
def self.scope_arity scope_symbol
    begin
        send(scope_symbol, (1..100).to_a) 
    rescue ArgumentError => e
        f = e.message.scan(/for\s+(\d+)/).flatten.first
        f.to_i.nonzero? || 0
    end
end

可能的用法如下所示:

irb(main):074:0> User.scope_arity(:active_users)
=> 2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接