如何将关联加载到实例变量中?

How to eager load associations into an instance variable?

在模型中我有:

class CalendarItem < Resource
  belongs_to :schedule

  has_many :people
  has_many :documents

  acts_as_list scope: :schedule, column: :visual_position

  validates :schedule, :title, presence: true
end

然后在控制器中:

class ScheduleController < ApplicationController
  def show
    @calendar_items = CalendarItem.where(schedule: @schedule).includes(:people, :documents)
  end

  ...
end

在视图中,我正在使用 react-rails 渲染一个 react_component(但这应该会有所不同):

= react_component('CalendarItemsList', calendar_items: @calendar_items)

但是它不会将关联数据传递给视图 (react_component),只有主模型。

这个我以前遇到过,用非react前端,也没用。有什么问题吗?

问题不在于实例变量中的数据,而在于序列化。

如果第二个参数不是字符串,react_component 视图助手将调用 to_json 方法。在您的情况下:{calendar_items: @calendar_items}.to_json,递归工作,因此您要确保 @calendar_items.to_json returns 预期的 JSON 输出。您可以使用 @calendar_items.serializable_hashrails console 中对其进行测试,它 returns 是一个散列,对人类而言更具可读性。

或者您将数据序列化为一个字符串,然后将其提供给 react_component

我不知道 Rails 5 序列化,但它似乎与 ActiveModelSerializers 类似,因此您可以在序列化输出中包含关系,例如:@calendar_items.to_jso(include: [:documents])。在 ActiveModelSerializers 中,您可以为每个 class 指定一个序列化程序,并指定它们之间的关系,这些关系可以自动包含。

所以一个可行的解决方案可能是:

def show
  calendar_items = CalendarItem.where(schedule: @schedule).includes(:people, :documents)
  @react_component_props = { calendar_items: calendar_items.to_json(include: [:people, :documents]) }
end

= react_component('CalendarItemsList', @react_component_props)

一个小提示:您可以在 CalendarItem 模型上创建一个 by_schedule 作用域,以便稍后使用它:CalendarItem.by_schedule @schedule

编辑

如果你需要视图中其他地方的数据,那么你可以使用as_json方法:

def show
  calendar_items_scope = CalendarItem.where(schedule: @schedule).includes(:people, :documents)
  @calendar_items = calendar_items_scope.as_json(include: [:people, :documents])
end

解决方案是添加 as_json 并在其中包含关联:

@calendar_items = CalendarItem.where(schedule: @schedule)
                              .as_json(include: [:people, :documents])

这会按预期加载/序列化关联。