ruby-on-rails - Rails 4 中的作用域数量

标签 ruby-on-rails ruby ruby-on-rails-4 rails-activerecord

我知道如何检查 lambda 的元数,但我不知道如何从作用域中提取它。

这个问题是 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

它会在调用之前寻求帮助以找到作用域的元数。

找到解决方案了吗?

最佳答案

scope 方法没有显式参数,如下所示

irb(main):070:0> User.method(:active_users).parameters
=> [[:rest, :args]]

:rest 表示参数被收集为一个数组。这允许一个人对任意数量的参数没有参数。

对于接受参数的范围,如果您使用错误数量的参数调用,您将收到一个 ArgumentError - 有点像下面这样:

ArgumentError: wrong number of arguments (1 for 2)

我们可以利用这个 ArgumentError 来计算元数,因为错误消息中存在元数。

让我提醒你,这是一种hack,如果你迫切需要弄清楚,它可能会有用大量基于 lambda 的作用域。

我们可以在 Model 中定义一个方法,该方法将尝试使用异常多的参数(比如 100 个参数)调用 scope - 从而强制 ArgumentError - 然后我们可以捕获消息并从中提取元数。

这种方法的可能实现如下所示:

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

关于ruby-on-rails - Rails 4 中的作用域数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34297956/

相关文章:

ruby-on-rails - Rails 删除development.log 行(不是文件本身)

ruby-on-rails - 如何在 Rails 应用程序中使用 form_for 发布销毁操作?

ruby-on-rails - Ruby/Rails 解析电子邮件

Ruby IO#read 单次读取的最大长度

ruby - 为什么 'Date.parse' 不引发无效日期字符串的异常?

ruby-on-rails - Geocoder Gem - 获取 request.location.country 的 "Reserved"(即使在本地!)

ruby-on-rails - 如何在Rails中过滤资源?

ruby-on-rails - 无法弄清楚是什么导致我的测试失败

ruby-on-rails - 使用 rails 应用程序 : Error with build stream, 轮询结果的 heroku 错误

ruby-on-rails - ActionController::估值中的UrlGenerationError#new