krishnar krishnar - 3 years ago 140
Ruby Question

eager loading nested object rails

I have models like below

Customer.rb

has_many :appointments
has_many :addresses
has_many :contacts


Address.rb

belongs_to :customer


Contact.rb

belongs_to :customer


Appointment.rb

belongs_to :customer


I have defined API's to return customers like below but with one extra attribute i.e appointment_id.

customers: [
{
appointment_id: 'xxxxxxx'
..
..
..
addresses: [{...}, {...}]
contacts: [{...},{...}]
},
{
..
},
.....

]


The above api is defined in a way that I pass @customers (which is array of customers along with their nested objects address, contacts). Problem is How should write active record query to return so so data.

Current Approach:

// I got list of appointment id's and I should return corresponding customers data as shown in above api.

cust_ids = Appointment.where(blah blah blah).pluck(:customer_id)
@customers = Customer.where(appointment_id: cust_ids).includes(:addresses, :contacts)


What I want?

My above approach doesnt have appointment_id in @customers object. How should I get it? Do I need to join table
along with includes. ??

Answer Source

Add inverse of to association definitions to avoid n+1 during preload

# customer.rb
has_many :appointments, inverse_of: :customer

# appointment
belongs_to :customer, inverse_of: :appointment

Now you can fetch your appointments from the DB and construct JSON

# in the controller
appointments = Appointment.where(blah blah blah)
  .preload(customer: [:contacts, :addresses])

customers = appointments.map do |appointment|
  appointment.customer
   .as_json(include: [:contacts, :addresses])
   .merge(appointment_id: appointment.id)
end

render json: { customers: customers }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download