gpt4 book ai didi

ruby-on-rails - 将一种方法链接到另一种方法如何改变原始方法

转载 作者:数据小太阳 更新时间:2023-10-29 09:00:30 26 4
gpt4 key购买 nike

解释这个难题的最简单方法是举个例子:

假设我有两个 Mongoid 模型,它们通过 has_many 关系相关:博客文章

class Post
include Mongoid::Document
field :body, type: String

has_many :comments
end

还有评论

class Comment
include Mongoid::Document
field :text, type: String

belongs_to :post
end

现在我在 IRB 中创建了一个有两条评论的帖子,我尝试通过关系加载它们。我启用了一些数据库日志记录,所以我可以看到何时进行查询:

post.comments #=>
2016-04-27 13:51:52.144 [DEBUG MONGODB | localhost:27017 | test.find | STARTED | {"find"=>"comments", "filter"=>{"post_id"=>BSON::ObjectId('571f315e5a4e491a6be39e02')}}]
2016-04-27 13:51:52.150 [DEBUG MONGODB | localhost:27017 | test.find | SUCCEEDED | 0.000492643s]
=> [#<Comment _id: 571f315e5a4e491a6be39e03, text: 'great post' >, #<Comment _id: 571f315e5a4e491a6be39e12, text: 'this!' >]

因此评论从数据库加载并作为 Mongoid::Relations::Targets::Enumerable 类返回,它看起来像一个数组,它包含两个评论。

现在,当我打开一个新的 IRB 控制台,并使用 Mongoid::Relations::Targets::Enumerable 的 criteria 属性查看用于加载这些评论的标准 类实例 post.comments,我得到这个输出:

post.comments.criteria #=>
=> #<Mongoid::Criteria
selector: {"post_id"=>BSON::ObjectId('571f315e5a4e491a6be39e02')}
options: {}
class: Comment
embedded: false>

为什么在这个例子中没有发出数据库请求?这不是缓存问题,因为我打开了一个新的 IRB 控制台。

如何将 criteria 链接到 post.comments 来改变 .comments 方法的作用?我查看了 Mongoid 对 Mongoid::Relations::Targets::Enumerable 类 (source on Github) 的实现,但找不到任何有关其工作原理的线索。


编辑

澄清问题:

这段代码,不查询数据库:

post.comments.criteria

但这段代码确实:

foo = post.comments
post.comments.criteria

怎么会?

最佳答案

将评论转化为答案:

执行时 Mongoid::Relations::Targets::Enumerable#inspect , inspect 方法在所有条目上执行:

Inspection will just inspect the entries for nice array-style printing.

如果不使用查询方法,这是无法完成的。

OP 实际上遇到的问题与 IRB 控制台更相关。 IRB 控制台以触发 #inspect 的方式处理此响应对象,进而触发查询方法。对于 Mongoid(和 ActiveRecord)类,#inspect 方法执行查询以产生预期结果。

例如,如果在 IRB 控制台中运行,这将触发对数据库的查询:

>> foo = posts.comments
>> post.comments.criteria

foo 的响应将在 IRB 控制台尝试输出对象作为响应时触发查询方法。可以(至少)通过以下两种方式之一在 IRB 控制台中抑制对数据库的查询:

方法一:和nil

本质上,您可以为单个命令添加后缀 and nil;0 或类似的东西,以防止第一个命令被 IRB 的响应输出处理。这是因为 IRB 控制台只查看最后一个对象(就像 ruby​​ 方法的返回)。

>> foo = posts.comments and nil
>> post.comments.criteria

上面不会查询数据库,因为第一行IRB处理的输出是nil,而不是foo变量。

方法二:conf.echo = false

来源:https://stackoverflow.com/a/13284331/1483788

此方法可防止 IRB 控制台自动处理响应对象。

>> conf.echo = false    
>> foo = posts.comments
>> post.comments.criteria

这不会从控制台查询数据库。但是,您也不会从最后一行得到响应。您将需要使用 putspp( pretty-print )来输出对象。相比之下,如果您在使用此方法时运行命令 foo.inspect,您会注意到执行了对数据库的查询以产生所需的结果。

关于ruby-on-rails - 将一种方法链接到另一种方法如何改变原始方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36891026/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com