关联块只被调用一次

时间:2015-02-25 11:53:11

标签: 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, :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)

是错误还是功能?或者我做错了什么?

谢谢

3 个答案:

答案 0 :(得分:2)

在这种情况下,会热切地评估该块,并缓存生成的数据集。要延迟评估当前区域设置,您需要使用延迟评估:

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的文档以反映这一点。

答案 1 :(得分:0)

假设您正在说&#34;阻止&#34;你意味着A class的身体或者身体内的某些东西,这是完全合理的。类只加载一次(通常,除非猴子修补,但即便如此,#34;加载&#34;是一个值得商榷的术语)。

在这种情况下,A的正文设置了您正在执行的查询的声明性逻辑。如果您正在与传递给one_to_one的块进行对话,那么可能Sequel::Model正在计算其结果并在加载类时将其缓存。

我在这里错过了这个问题吗?

答案 2 :(得分:0)

这是一个特色:

只有在加载类时才会对块进行求值。这就是为什么在ActiveRecord中使用lambdas来定义范围或关联中的变量部分的原因。我不知道Sequel是否也支持查询或关联定义中的lambda。

数据库未被调用两次,因为关联在被检索后被缓存。见Caching in the docs for Sequel::Model