访问关联的 ActiveRecord 模型为空,需要显式重新加载

问题描述 投票:0回答:0

我在 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
 吗?

ruby-on-rails activerecord
© www.soinside.com 2019 - 2024. All rights reserved.