我在 Rails 模型中遇到了一些前所未见的行为。给定一个发货模型,
class Shipment < ApplicationRecord
has_many :items
def can_add_all_items_to_work_order?
return false if items.empty?
items.all? { |i| i.assignable_to_work_order? }
end
end
当我在控制器操作中从数据库加载货物时:
shipment = Shipment.find(params[:shipment_id])
我调用方法
can_add_all_items_to_work_order?
,
shipment.can_add_all_items_to_work_order?
该方法返回
false
,因为它认为 items
为空。
但是数据库中确实存在与 Shipment 关联的持久化 Item 对象,并且此方法应该返回
true
。
如果我在加载对象后显式访问
items
,
shipment = Shipment.find(params[:shipment_id])
shipment.items
我再次调用该方法
can_add_all_items_to_work_order?
,
shipment.can_add_all_items_to_work_order?
现在该方法神奇地返回
true
,正如它应该的那样。
我以前从未遇到过这种情况。为什么方法
can_add_all_items_to_work_order?
相信items
是空的?为什么我必须显式加载或访问 items
?方法的第一个语句中不应该引用 items
吗?
return false if items.empty?
从数据库中获取 items
,就像我执行以下语句一样:
shipment.items
来自物体外部?此外,我无法在 Rails 控制台中复制此操作 - 该方法的行为应如此,当我在 Rails 控制台中调用
can_add_all_items_to_work_order?
时,我会看到
Item Load... SELECT *...
的日志输出。为什么我在控制台中看到数据库命中,但在我的控制器操作中却看不到完全相同的语句?最后,如果我使用一些急切加载,
includes
,
shipment = Shipment.includes(:items).find(params[:shipment_id])
然后我观察到预期的行为:调用 can_add_all_items_to_work_order?
返回
true
。为什么需要急切加载?
can_add_all_items_to_work_order?
中的语句不应该按预期加载
items
吗?