J Manuel
J Manuel

Reputation: 3070

Ruby on Rails 5: How to print nested json

I'm learning Ruby on Rails (Specially for API development) and I need some help with something. Lets say we have 2 tables, "Brands" and "Cars".
What I'm trying to do is basically:

  1. Get a car: Instead of displaying "brand_id: x", I want to display "brand = { id: X, name: Y}", just as a nested JSON.
  2. Do that for each car.

Now, when I try to reach a car, it brings me:

{
    "id": 1,
    "name": "Veneno",
    "brand_id": 1,
    "created_at": "2016-12-03T21:47:01.000Z",
    "updated_at": "2016-12-03T21:47:01.000Z"
  }

My files contains the following: Migration files:

class CreateBrands < ActiveRecord::Migration[5.0]
  def change
    create_table :brands do |t|
      t.string :name

      t.timestamps
    end
  end
end

class CreateItems < ActiveRecord::Migration[5.0]
  def change
    create_table :items do |t|
      t.string :name
      t.integer :brand_id

      t.timestamps
    end
    add_index :items, :brand_id
  end
end

Models:

class Brand < ApplicationRecord
  has_many :items
end

class Item < ApplicationRecord
  belongs_to :brand
end

Currently, my items_controller.rb is:

class ItemsController < ApplicationController
  before_action :set_item, only: [:show, :update, :destroy]

  # GET /items
  def index
    @items = Item.all
    render json: @items
  end

  # GET /items/1
  def show
    render json: @item, :only => [:id, :name]
  end

  # POST /items
  def create
    @item = Item.new(item_params)

    if @item.save
      render json: @item, status: :created, location: @item
    else
      render json: @item.errors, status: :unprocessable_entity
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_item
      @item = Item.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def item_params
      params.require(:item).permit(:name, :brand_id)
    end
end

Thank you! I'm online 24/7 to provide more info about this issue. I googled it a lot but I couldn't find out how to fix this.

Upvotes: 0

Views: 576

Answers (1)

Robert Nubel
Robert Nubel

Reputation: 7522

What you're describing is how you want to serialize your model. There are gems that provide high-powered solutions to this problem (the venerable but still-relevant active_model_serializers, for example), but for basic use-cases, you can get away with leveraging Rails' surprisingly-powerful as_json.

For example, to make your show method include the brand object:

class ItemsController
  # GET /items/1
  def show
    render json: @item, :includes => [:brand]
  end
end

You can also override the default as_json at the model level, but that solution becomes tricky when different callers want different serializations and levels of detail. See Include associated model when rendering JSON in Rails for another example similar to what you're describing, but more involved.

Upvotes: 2

Related Questions