Search code examples
ruby-on-railsrails-api

Rails - Render JSON for one object and another object's attribute


I'm quite new on rails like I just started a week ago. I was wondering if it is possible to render json one object and another object's attribute. I don't know actually if I'm asking the right question.

Anyway, here is the code so far in my controller:

def create
  log_date = LogDate.find_or_initialize_by(date: log_params[:date])

  log_date.save if log_date.new_record?

  log = Log.new(log_params.except(:date))
  log.log_date_id = log_date.id

  if log.save
    render json: log.to_json(include: :log_date), status: :created
end

The current response I'm getting when I test the code is this:

{
   "id": 1,
   "log_date_id": 1,
   "hours": 1,
   "ticket_number": "1",
   "description": "sample description",
   "created_at": "2021-08-11T11:41:59.636Z",
   "updated_at": "2021-08-11T11:41:59.636Z",
   "log_date": {
       "id": 1,
       "date": "2021-01-01",
       "max_hours": 8,
       "created_at": "2021-08-11T11:36:20.853Z",
       "updated_at": "2021-08-11T11:41:39.282Z"
   }
}

What I'm trying to achieve is a response like this at least, but I don't know if it's possible:

{
   "id": 1,
   "log_date_id": 1,
   "hours": 1,
   "ticket_number": "1",
   "description": "sample description",
   "created_at": "2021-08-11T11:41:59.636Z",
   "updated_at": "2021-08-11T11:41:59.636Z",
   "date": "2021-01-01"
}

The "date" at the bottom basically came from log_date. I don't mind where it's positioned whether it's at the top or bottom as long as the response format looks something like that instead of what it currently looks like.

I really do hope it's possible and someone can help me. Anyway if it's not possible it's cool. Thank you in advance!


Solution

  • Use delegation to expose the method on log_date as if it was a method on the log instance:

    class Log < ApplicationRecord
      belongs_to :log_date
      delegate :date, to: :log_date
    end
    

    This is basically just a shorthand for:

    class Log < ApplicationRecord
      belongs_to :log_date
    
      def date
        log_date.date
      end
    end
    

    You can include custom methods when rendering JSON through the methods option:

    render json: log, methods: [:date], status: :created