在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_name
,find_all_by_name_and_colour
?
由于
答案 0 :(得分:3)
根据documentation,delegate
:
提供委托类方法 容易暴露包含的对象' 方法作为你自己的。通过一个或多个 方法(指定为符号或 字符串)和目标的名称 对象通过: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
的开销