我有Order
模型,has_many :order_operations
。订单状态更改时,OrderOperation始终创建。我想在不创建新查询的情况下显示订单的所有OrderOperations.created_at。我使用MySQL。
class Order < ActiveRecord::Base
has_many :order_operations
def change_state new_state
order_operations.create to_state: new_state
end
def date_for_state state_name
order_operations.where(state: state_name).pluck(:created_at).last
end
end
我了解includes
和joins
方法,但在调用date_for_state
时始终运行新查询。即使我删除where
,pluck
查询也会执行。
我只有一个想法就是为此创建服务对象。
答案 0 :(得分:0)
当您执行加入/包含时,它会缓存执行特定查询的结果:具体而言,是一个查询,以获取与order_operations
关联的所有order
。
如果您已加载@order,急切加载关联的order_operations并执行@order.order_operations
,则Rails已将关联的order_operations缓存为包含的一部分,并且不需要再次加载它们。
但是,如果你执行@order.order_operations.where(state: state_name).pluck(:created_at).last
,这是一个不同的查询,而不是包含中使用的查询,所以rails说&#34;他要求一些不同的我缓存的东西,所以我不能使用缓存的东西,我需要进行另一个查询&#34;。你可能会说&#34; aha,但这只是你缓存的东西的一部分,所以你不能弄清楚这适用于哪些缓存记录?&#34;,但Rails isn&这很聪明。
如果你要做
@order.order_operations.select{|oo| oo.state == state_name}.map(:created_at).last
然后您只是进行一些数组操作,而.order_operations
将使用缓存的记录,因为它与您使用{{缓存的记录相同的查询1}},即直接连接到所有相关记录。但是,如果你在一个实例var @order上调用它并没有真正加载相关记录,那么它将效率低得多,因为它会做更大的查询而不是你原来的那个。
换句话说:如果您希望使用includes
来提高效率,那么includes
调用的参数需要与您随后在对象上进行的关联调用完全匹配。