Search code examples
ruby-on-railspaginationactive-model-serializers

Rails - activerecord model serializer group results by specific column in the foreign table


I want to use the ActiveRecord model serializer to show results from the primary key table and foreign key table. However, I want the results to be presented grouped by a column in the foreign key table.

cats = Cats.paginate(page: params[:page], per_page: 20)
render json: cats, meta: pagination(cats), adapter: :json

In the ActiveRecord model serializer:

class CatSerializer < ActiveModel::Serializer
attributes :cat, :persons

 def persons
   object.person
 end

 def cat
   { id: object.id, cat_name: object.name}
 end

Now cat_name is not unique and Persons can share many cat_names. please note that Person => has_many Cats, but cat_name can be similar to multiple Persons. How can I show the data in this format:

"results": [
{
  "cat": {
    "id": 11,
    "cat_name": "Luzi",
    ...
  },
  "persons": [
    {
      "id": 1,
      "name": "andy"
    },
    {
      "id": 2,
      "name": "david"
    }

Please also note that groyp_by(&:cat_name) does not work with pagination.


Solution

  • You can use custom serializer that accepts an already groupby ActiveRecord result

    def index
      @cats = Cat.joins(:persons).group("persons.name")
      render json: @cats, serializer: GroupedCatSerializer
    end
    

    And you can define custom serializer like

    class GroupedCatSerializer < ActiveModel::Serializer
    
      # method override
      def serializable_object(options={})
        @object.map do |group_key, models|
          [ group_key , serialized_models(models) ]
        end.to_h
      end
    
      private
    
      def serialized_models models
        models.map{ |model| CatSerializer.new(model, root: 
        false) }
      end
    
    end