加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – ActiveRecord如何检测链中的最后一个方法调用?

发布时间:2020-12-17 03:28:19 所属栏目:百科 来源:网络整理
导读:让我为你想象一下. class Product ActiveRecord::BaseendProduct.first.title#= "My sample product" 这里没什么特别的.只是一个简单的方法调用.现在看一下下面的例子. class Product ActiveRecord::Base def method_missing endendProduct.first.title#= ni
让我为你想象一下.

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"

这怎么可能?在某种程度上,他们确定方法链的结束并采取行动?至少这就是我的理论.

谁能解释这种行为?

解决方法

你看到一个使用irb调查事物的工件.

当你这样说:

> 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并不真正知道链的末端在哪里,它只是不会从数据库中加载任何东西,直到它必须通过说出去并检索我一些数据来告诉它链在哪里结束.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读