When building an an API, the consumer (the developer) doesn't have any visual queues in order how to user your application, so, if they are not to solely rely on documentation, your interface needs to be intuitive. One way to get far with this is to be consistent in the objects that you respond with. One way to achieve this in rails is to use Active Model Serializers.

To install simply add to your Gemfile

gem 'active_model_serializers'

And run 'bundle install', now when you render json, rails will look for a serializer for the object it's trying to convert to json. Let's say you have a 'Car' model. To generate a serializer for this it's simply

rails g serializer Car

this will generate a file in serializers within your app folder, for example.

class CarSerializer < ActiveModel::Serializer  
  attributes :id, :color, :engine_id, :number_of_doors
end  

An example of the output of this is:

{
  "car": {
    "color": "black",
    "engine_id": 1,
    "number_of_doors: 5
  }
}

This is saying that we should include the attributes listed, if the Car model also had, lets say a weight property, this will not be output as it is not within the attributes listed.

Adding a property

Lets say we want to add a computed property to the serializer, it could be a property related to the context of the current request, so might not fit within the model itself, you'll need to make a judgement on that, but if we wanted to add an 'is_dark' attribute, we could do so as below:

class CarSerializer < ActiveModel::Serializer  
  attributes :id, :color, :engine_id, :number_of_doors, :is_dark

  def is_dark
    object.color == "black" || object.color == "brown"
  end

end  

Notice we have added the isdark property to the list of attributes, but we have also defined a method called isdark to return our desired value. Note this will also override an existing model function, however, I strongly would discourage that. The above serializer would output

{
  "car": {
    "color": "black",
    "engine_id": 1,
    "number_of_doors: 5,
    "is_dark": true
  }
}

Embedding Children

Now, as we are building an API we want it to be efficient for the consuming application, so sometimes we need to embed child objects within the one response to avoid N+1 performance issues.

Our Car class has a related object of Engine, which we would like to embed, this is as simple as calling its serializer to generate the engine json object.

class CarSerializer < ActiveModel::Serializer  
  attributes :id, :color, :engine, :number_of_doors, :is_dark

  def is_dark
    object.color == "black" || object.color == "brown"
  end

  def engine
    EngineSerializer.new(object.engine)
  end

end  

We have now changed engine_id in the attributes call to engine and added a method below for this. The method creates a new EngineSerializer which you would also have created and setup for an Engine class. We need to pass in the object to serialize, in this case it is the related engine for our car, this outputs:

{
  "car": {
    "color": "black",
    "engine": {
      "size": 2300,
      "fuel_type": "diesel"
    },
    "number_of_doors: 5,
    "is_dark": true
  }
}

I've found this to be an excellent way of packaging up your objects to make API's predictable and easier to consume. Testing is also easier, and I also use json-schema which i use to test the output of all controllers to make sure that they all conform to the documentation.