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

How to call an active_model_serializer to serialize records explicitly


I have a serializer for a TimeEntry model that looks like this:

class TimeEntrySerializer < ActiveModel::Serializer
  attributes :id, :description, :duration

  has_one :project
end

And It works as expected when I just return all the records:

def index
    @time_entries = current_user.time_entries.all

    respond_to do |format|
      format.html
      format.json { render json: @time_entries }
    end
end

However, I want to return the entries organized by day, something like this:

[
      { "2016-03-16" => [TimeEntry1, TimeEntry2, TimeEntry3] },
      { "2016-03-17" => [TimeEntry1, TimeEntry2] }
]

I do it like this form my model:

def self.get_entries_for_user(current_user)
    current_user.time_entries
    .group_by { |item| item.created_at.to_date.to_s }
    .map { |day, entries| { day => entries  } }
end

But now, the serializer is not working for the TimeEntry object, I'm not quite sure if it's actually supposed to work in this situation... I want to avoid having to format the data myself:

def self.get_entries_for_user(current_user)
    current_user.time_entries
    .group_by { |item| item.created_at.to_date.to_s }
    .map do |day, entries|
      {
        day => entries.map do |entry|
          {
            :id => entry.id,
            :description => entry.description,
            :duration => entry.duration_ms,
            :start_time => entry.time.begin,
            :end_time => entry.time.end,
            :project_id => entry.project.id
          }
        end
      }
    end
end

Is it possible to use the active_model_serializer for this situation? If not possible, how can I format the data more efficiently an avoid the nested map calls?


Solution

  • To call and be able to reuse the serializer:

    options = {}
    serialization = SerializableResource.new(resource, options)
    serialization.to_json
    serialization.as_json
    

    So I used it like this:

    def self.get_entries_for_user(current_user)
        current_user.time_entries
        .group_by { |item| item.created_at.to_date.to_s }
        .map do |day, entries|
          {
            :day => day,
            :entries => entries.map do |entry|
              entry = ActiveModel::SerializableResource.new(entry)
              entry.as_json
            end
          }
        end
    end