ROR: Serializing output for multiple objects

79 views Asked by At

I am learning rails, and using active_model_serializers gem.

I need to get the customized output in JSON from two different tables. Here is an example

car: id, name, color, size, shape, date... battery: id, car_id, price, weight, name, date...

class battery < ApplicationRecord
  belongs_to :car
end

query I ran is

## This is sample query will not work
Car.includes(:battery).where(car: {color: red}).where(date >= 'blah')

I have three hashes in calculated in my controller

#cars_controller.rb
available_cars ={ 
                   available_cars:[{id:id, 
                                    name:name, 
                                    color:color, 
                                    size:size, 
                                    date:date..
                                   }] 
                  }


available_battries = {
                      available_batteries:[{id:id, 
                                             card_id:car_id, 
                                             price:price, 
                                             weight:weight, 
                                             name:name, 
                                             date:date..
                                           }]
                       }
    
cars_with_battires = {
                      cars_with_battry: [{id:id, 
                                          name:name, 
                                          color:color, 
                                          size:size, 
                                          date:date..}, 
                                          battries:[{id: 1, 
                                                     name: name1
                                                     }, 
                                                     {id: 2, 
                                                     name: name2
                                                     }
                                                   ]
                                          ]}
render json: { 
          available_cars: available_cars, 
          available_batteries: available_batteries, 
          cars_with_battry: cars_with_battry }
          serializer: CarIndexListSerializer }

This is my serializer file looks like and I need to fill those functions

#car_index_list_serializer.rb
class CarIndexListSerializer < ActiveModel::Serializer
   attributes :available_cars,
              :available_batteries,
              :cars_with_battry

   def available_cars
       #todo?      
   end

   def available_batteries
       #todo?
   end

   def cars_with_battry
       #todo?
   end

I can just remove the fields I dont want and return the result in JSON but I want to use active_model_serializers to return it in following format.

{
    available_cars:[{id: 1, name:name1, size: abc}],
    available_batteries:[{id: 1, name: name1}],
    cars_with_battry:[{id: 1, name:name1, size: abc, 
                       battries:[{id: 1, name: name1}]
                      }]
}

if any of the hash is empty, I do not want to show it in the results

1

There are 1 answers

2
Saiqul Haq On
result = {}
available_cars = Car.where xxx 
if available_cars.count.positive?
  result[:available_cars] = available_cars.map {|car| CarSerializer.new(car).as_json }
end

# do the same thing for available battery and car with battery

render json: result

just a rough idea

Update

Usually for #index action on controller, it render list of resources so CarIndexListSerializer is not required
What you have to create is two serializers:

  1. car serializer
  2. battery serializer

even you can add a relationship data to your car serializer

class CarSerializer < ActiveModel::Serializer
  has_many :batteries
end

class Car < ApplicationRecord
  has_many :batteries
end

so when you call this

car = Car.last
CarSerializer.new(car).as_json

it would return the car and batteries data

don't forget to create BatterySerializer too