Goal: structuring multiple Birds within each Nest, so that we could find all birds within a specific nest with routes such as /nests/:nest_id/birds.
Step 1: Create Models
#app/models/nest.rb class Nest < ActiveRecord::Base has_many :birds end class Bird < ActiveRecord::Base belongs_to :nest end
Step 2: Generate Migrations
$ rails g migration CreateNests
And edit the file generated under db/migrate:
class CreateNests < ActiveRecord::Migration
def change
create_table :nests do |t|
t.string :name
t.timestamps null: false
end
create_table :birds do |t|
t.belongs_to :nest, index: true
t.string :name
t.timestamps null: false
end
end
end
And do a rake db:migrate.
Step 3: Create Controller
#app/controllers/nests_controller.rb, in my case #app/controllers/api/nests_controller.rb
class NestsController < Api::BaseController # I'm using module Api therefore ApplicationController was changed to Api::BaseController here
before_action :set_nest, only: [:show, :edit, :update, :destroy]
def index # GET /nests
nests = Nest.all
render json: nests
end
def show # GET /nests/1
render json: @nest
end
def create # POST /nests
nest = Nest.new(nest_params)
if nest.save
render json: nest, root: false
else
render json: { error: 'Internal Server Error'}, status: :internal_server_error
end
end
def update # PATCH/PUT /nests/1
if @nest.update(nest_params)
render json: @nest, status: :ok
else
render json: @nest.errors, status: :unprocessable_entity
end
end
def destroy # DELETE /nests/1
@nest.destroy
render json: {}, status: :no_content
end
private
def set_nest
@nest = Nest.find(params[:id])
end
def nest_params
params.permit(:nest, :name)
end
end
And likewise for birds_controller.rb, except:
class BirdsController < Api::BaseController
before_action :set_nest, only: [:index, :create]
def index
birds = @this_nest.birds
render json: birds # render json in all conditions
end
def create
bird = @this_nest.birds.build(bird_params)
if bird.save
render json: bird, root: false
else
render json: { error: 'Internal Server Error'}, status: :internal_server_error
end
end
...
private
...
def set_nest
@this_nest = Nest.find(params[:nest_id])
end
Step 4: Set Up Routes
#config/routes.rb
# since I'm using module Api, I have this line here:
namespace :api do
...
resources :nests, only: [:index, :show, :create, :update, :destroy] do
resources :birds, only: [:index, :create, :update, :destroy]
end
end
And a rake routes reveals that we now have:
GET/POST /api/nests PATCH/PUT/DELETE /api/nests/:id GET/POST /api/nests/:nest_id/birds PATCH/PUT/DELETE /api/nests/:nest_id/birds/:id
Just what we need.
