Nested Routing in Rails

Tagged with Rails rest

Language: Ruby

View as text

map.resources :programs do |program|    # /programs/:id              programs_url    program_url(@program)
  program.resources :deadlines          # /programs/:program_id/deadlines/:id    program_deadlines(@program)   program_deadline(@program, @deadline)
  program.resources :pages do |page|    # /programs/:program_id/pages/:id    program_pages_url(@program)
     page.resource :images             # /programs/:program_id/pages/:page_id/images/:id
     #                                          program_page_image(@program, @page.slug, @image)
  end
end



class ApplicationController < ActionController::Base

  private
   def find_program
     @program = params[:controller] == "projects" ? Program.find(params[:id]) || Program.find(params[:program_id])
     
   end
   
   def find_page

     # we want page names to show up as a slug, rather than a numerical id
     # so we assume people will send in link_to @page.name, program_page_url(@program, @page.slug)
     # and then we find_by_slug instead of find or find_by_id
     @page = params[:controller] == "pages" ? Page.find_by_slug(params[:id]) ||  Page.find_by_slug(params[:page_id])
   end
  

end


class ProgramsController < ApplicationController

  before_filter :find_program, :except=> [:index, :create, :new]
  
  def index
   @programs = Program.all
  end

  def new
   @program = Program.new
  end

  def edit
    # you can skip this action since the filter does its job and it's not needed 
    # as the view will still render. This action will get skipped from now on.
  end

   def create
     @progra = Program.new(params[:page])
     if @page.save
        redirect_to program_url(@program)
     else
       render :action => "new"
     end
   end

   def update
     if @program.update_attributes(params[:page])
        redirect_to programs_url
     else
       render :action => "new"
     end
   end

   def destroy
     @program.destroy
     redirect_to programs_url
   end

   
end

class PagesController < ApplicationController

   before_filter :find_program
   before_filter :find_page, :except => [:index, :create, :new]

   def index
     @program.pages.find :all
   end
   
   def new
     @page = @program.pages.build
   end
   
   
   def edit
     @page = @program.pages.find(params[:id]
   end
   
   def create
     @page = @program.pages.build(params[:page])
     if @page.save
        redirect_to program_pages_url(@program)
     else
       render :action => "new"
     end
   end

   def update
     if @page.update_attributes(params[:page])
        redirect_to program_pages_url(@program)
     else
       render :action => "new"
     end
   end
   
   def destroy
     @page.destroy
     redirect_to program_pages_url(@program)
   end

end

# A singleton controller has no index action... it still has a pluralized controller name
# by default though!!!
class ImagesController < ApplicationController

   before_filter :find_program
   before_filter :find_page
   before_filter :find_image, :except => [:create, :new]


   def new
     @image = @page.images.build
   end

   def create
     @image = @page.images.build(params[:image]
     if @image.save
       redirect_to program_page_image(@program, @page, @image
     else
       render :action => "new"
     end
   end

   def edit
   
   end

   def update
     if @image.update_attributes(params[:image])
       redirect_to program_page_image(@program, @page, @image
     else
       render :action => "new"
     end
     
   end

   def destroy
     @image.destroy
   end
   
 
end





Original snippet written by Brian Hogan
Last updated at 08:42 AM on Oct 10, 2008 by Brian Hogan

SnippetStash costs money to host and develop. The service is free for everyone to use
but if you found it useful please consider making a small donation.