class Product < ActiveRecord::Base end Product.first.title #=> "My sample product"
这里没什么特别的.只是一个简单的方法调用.现在看一下下面的例子.
class Product < ActiveRecord::Base def method_missing end end Product.first.title #=> nil Product.first Product.first.title #=> "My sample product"
这怎么可能?在某种程度上,他们确定方法链的结束并采取行动?至少这就是我的理论.
谁能解释这种行为?
解决方法
当你这样说:
> Product.first.title #=> nil
您的method_missing将被调用为延迟加载标题方法,您将获得零.
当你这样说:
> Product.first
你实际上是这样做的:
> p = Product.first; puts p.inspect
将加载第一个Product实例,然后irb将在其上调用inspect,AR将在此过程中添加访问器方法.结果是Product现在有一个title方法.因此,这样做:
> Product.first > Product.first.title
不会调用你的method_missing,因为Product.first.title会有一个真正的title方法来调用.
如果你再试这样:
> Product.first; nil > Product.first.title
你会看到两个零.
就链接而言,ActiveRecord并没有真正检测到结束,只是某些方法调用自然需要来自数据库的真实数据而有些则不需要.
如果您调用where,order或任何其他查询方法,则会返回ActiveRecord::Relation实例,并且可以在该关系对象上链接更多查询方法和范围.例如,where
(ActiveRecord :: Relation通过包括ActiveRecord::QueryMethods得到)看起来像这样:
def where(opts,*rest) return self if opts.blank? relation = clone relation.where_values += build_where(opts,rest) relation end
所以它只是制作当前查询的副本,为副本添加一些内容,并为您提供副本.
如果你先调用first,last,to_a,all,任何Enumerable方法(即你调用每个方法),那么你就会询问特定的实例,而ActiveRecord必须执行查询来实现模型实例.有问题.例如,ActiveRecord::Relation#to_a
看起来像这样:
def to_a logging_query_plan do exec_queries end end
和all
只是to_a的包装.
ActiveRecord并不真正知道链的末端在哪里,它只是不会从数据库中加载任何东西,直到它必须通过说出去并检索我一些数据来告诉它链在哪里结束.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。