轨。无需新查询即可获取垂直关联数据

时间:2016-01-26 11:32:15

标签: mysql ruby-on-rails has-many

我有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

我了解includesjoins方法,但在调用date_for_state时始终运行新查询。即使我删除wherepluck查询也会执行。 我只有一个想法就是为此创建服务对象。

1 个答案:

答案 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调用的参数需要与您随后在对象上进行的关联调用完全匹配。