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.