理解Rails中的委托和作用域方法

时间:2011-02-17 23:45:41

标签: ruby-on-rails ruby delegates

在active_record / base.rb中,module ActiveRecord您可以看到以下代码:

delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, 
             :delete_all, :update, :update_all, :to => :scoped

我们采用first方法,因此我假设first方法委托给scoped方法,然后scoped应该从数据库返回第一条记录。但scoped只是匿名的scope,当前的建设是如何发挥作用的呢?

与此同时,动态方法如何运作,例如find_by_namefind_all_by_name_and_colour

由于

3 个答案:

答案 0 :(得分:3)

根据documentationdelegate

  

提供委托类方法   容易暴露包含的对象'   方法作为你自己的。通过一个或多个   方法(指定为符号或   字符串)和目标的名称   对象通过:to选项(也是一个   符号或字符串)

因此,这会将列表中的方法委托给scoped方法,该方法在ActiveRecord :: NamedScoped :: ClassMethods中定义,并且returns an anonymous scope

至于为什么ActiveRecord这样做,我们可以继续使用熟悉的方法,例如find,而幕后AR实际上是在调用新的Arel方法。例如,当你做

Post.find(37)

实际执行的是:

Post.where(primary_key.eq(37))

答案 1 :(得分:1)

我会回答你的第二个问题。 find_by_name和find_all_by_what_you_want依赖于ruby的宝贵方法_missing。只要方法不存在,对象就会调用method_missing,您可以覆盖它。例如,我可能想覆盖method_missing,捕获所有不存在的方法调用,检查一些正则表达式是否开始/结束/包含一些关键字等。

在你的例子中,我将覆盖method_missing,检查它是否以find开头,如果是,则拆分''关键字以获取我想要的属性数组做我的发现。

这是一个很好的例子:http://technicalpickles.com/posts/using-method_missing-and-respond_to-to-create-dynamic-methods/

答案 2 :(得分:1)

首先:“委托”委托给一个对象,而不是一个方法 - 所以“范围”必须是某个对象。

在没有检查源来验证和继续我对ActiveRecord的工作知识的情况下,我将假设“范围”将是当前的AR实例,除非它在关联代理上被调用。

因此:

User.first # "scope" will be User

User.posts.first # "scope" will be the Post collection proxy

@christianblais在问题#2上是正确的,method_missing正在处理这些调用。此外,Rails实际上在第一次调用时定义了丢失的方法,因此后续调用它不会产生method_missing的开销