How to eager load associations into an instance variable?

这一生的挚爱 提交于 2019-12-13 06:46:54

问题


In Model I have:

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

Then in controller:

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

  ...
end

In the view I'm rendering a react_component with react-rails (but that should make any difference):

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

However it does not pass the associated data to the view (react_component), only main model.

I have experienced this before, with non-react front-end, and it didn't work either. What could be wrong?


回答1:


The problem is not with the data in in the instance variable but with the serialisation.

The react_component view helper will call the to_json method on the second argument if it is not a string. In your case: {calendar_items: @calendar_items}.to_json, which works recursively, so you want to make sure @calendar_items.to_json returns the expected JSON output. You can use @calendar_items.serializable_hash for testing it in the rails console, it returns a hash, which is more readable for humans.

Or you serialise your data into a string and feed the react_component with it.

I dont know Rails 5 serialization but it seems to be similar to ActiveModelSerializers so you can include the relationships in the serialised output like: @calendar_items.to_jso(include: [:documents]). In ActiveModelSerializers you can specify a serialiser to each class, and specify the relationships on them, those can be included automatically.

So one working solution could be:

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)

A modest tip: you can create a by_schedule scope on the CalendarItem model, so later you can use it: CalendarItem.by_schedule @schedule

EDIT

If you need the data other places in the view then you can use the as_json method:

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



回答2:


The solution-workaround is to add as_json and include the associatiosn there:

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

This loads / serializes the associations as expected.



来源:https://stackoverflow.com/questions/42606013/how-to-eager-load-associations-into-an-instance-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!