Ruby 关联块只调用一次
我正在使用Sequel,我的模型定义如下:Ruby 关联块只调用一次,ruby,sequel,Ruby,Sequel,我正在使用Sequel,我的模型定义如下: class A < Sequel::Model one_to_one :lang, class: ALang, key: :a_id, graph_join_type: :inner do |ds| ds.where(ALang__lang: I18n.locale.to_s) end delegate :title, :titleSanitized, :d
class A < Sequel::Model
one_to_one :lang, class: ALang, key: :a_id,
graph_join_type: :inner do |ds|
ds.where(ALang__lang: I18n.locale.to_s)
end
delegate :title, :titleSanitized, :description, to: :lang
# ...
end
I18n.lang = :de
A.eager(:lang).all
# block is called ("ds.where(ALang__lang: I18n.locale.to_s)" code)
# database was queried (I can see the query in logs)
I18n.lang = :en
A.eager(:lang).all
# block is not called
# database was queried (I can see the query in logs)
A类
它是bug还是特性?还是我做错了什么
谢谢你假设你说的“block”是指
A
类
的主体或所述主体内的某个东西,这是非常有意义的。类只加载一次(通常情况下,除非使用monkey补丁,但即使这样,“加载”也是一个有争议的术语)
在本例中,A
的主体设置所执行查询的声明性逻辑。如果您正在谈论传递给one-to-one
的块,则很可能Sequel::Model
正在计算其结果并在加载类时缓存它
我是否遗漏了这个问题?这是一个功能:
加载类时,该块仅计算一次。这就是为什么在ActiveRecord中使用lambdas来定义作用域或关联中的变量部分。我不知道Sequel在查询或关联定义中是否也支持lambda
数据库不会被调用两次,因为关联在检索后会被缓存。请参见在本例中,将急切地评估块,并缓存结果数据集。要延迟对当前区域设置的评估,需要使用延迟评估:
one_to_one :lang, class: ALang, key: :a_id,
graph_join_type: :inner do |ds|
ds.where(ALang__lang: Sequel.delay{I18n.locale.to_s})
end
我已经更新了Sequel的文档以反映这一点。抱歉,我不清楚,我删除了包含
ds.where(ALang\u lang:I18n.locale.to_s)
code.Gotcha,从@spickermann的回答中可以看出我的直觉是正确的。请参阅结尾“如果您谈论的是传递给one-to-one的块,那么很可能Sequel::Model正在计算其结果,并在加载类时缓存它。“好吧,这是可以理解的。但是,如果块定义不能反映动态状态,那么我就看不到在关联中使用块定义的意义。你明白我的意思吗?我相信我做错了什么,但我不知道是什么:(.好的,但为什么在两次调用中都查询数据库?请查看编辑后的问题。非常感谢。您是否在Rails日志或数据库日志中看到查询?Rails日志只告诉您Rails请求了该数据,但不告诉您缓存层是否能够提供该数据。在缓存层中提供查询结果时,您可以将在Rails日志中看到查询,但不会在数据库的日志中看到查询,因为它实际上没有两次为数据库提供工具包。问题不在于缓存数据,而在于缓存数据集以进行关联。现在所有问题都已解决。感谢您抽出时间。