Nested Resources July 2012 by Anton Nested resources resources - - PowerPoint PPT Presentation

nested resources
SMART_READER_LITE
LIVE PREVIEW

Nested Resources July 2012 by Anton Nested resources resources - - PowerPoint PPT Presentation

Nested Resources July 2012 by Anton Nested resources resources :pages do resources :posts end Routes and helpers page_posts GET /pages/:page_id/posts(.:format) posts#index POST /pages/:page_id/posts(.:format)


slide-1
SLIDE 1

Nested Resources

July 2012
 by Anton

slide-2
SLIDE 2

Nested resources

resources :pages do resources :posts end

slide-3
SLIDE 3

Routes and helpers

page_posts GET /pages/:page_id/posts(.:format) posts#index POST /pages/:page_id/posts(.:format) posts#create new_page_post GET /pages/:page_id/posts/new(.:format) posts#new edit_page_post GET /pages/:page_id/posts/:id/edit(.:format) posts#edit page_post GET /pages/:page_id/posts/:id(.:format) posts#show PUT /pages/:page_id/posts/:id(.:format) posts#update DELETE /pages/:page_id/posts/:id(.:format) posts#destroy

slide-4
SLIDE 4

routes.rb

resources :pages, :only => :index resources :pages do resources :posts end

slide-5
SLIDE 5

Same controller Same action Same view

slide-6
SLIDE 6

class PostsController < ApplicationController before_filter :load_page def index if @page @posts = @page.posts.all else @posts = Post.all end end def show ... end def load_page @page = Page.find(params[:page_id]) if params[:page_id] end ...

posts_controller.rb

slide-7
SLIDE 7

h1 Listing posts table tr th Title th Content th Post type

  • unless @page

th Page th th th

  • @posts.each do |post|

tr td= post.title td= post.content td= post.post_type

  • unless @page

td= post.page.name td= link_to 'Show', [post.page, post] td= link_to 'Edit', edit_page_post_path(post.page, post) td= link_to 'Destroy', [post.page, post], confirm: 'Are you sure?', method: :delete

/posts/index.slim

slide-8
SLIDE 8

Problems

‘IF’ statements everywhere Dirty views

slide-9
SLIDE 9

Split index view into /posts/index.slim /posts/page_index.slim

Solution

slide-10
SLIDE 10

Same controller Same action Different views

slide-11
SLIDE 11

h1 Listing posts table tr th Title th Content th Post type th th th

  • @posts.each do |post|

tr td= post.title td= post.content td= post.post_type td= link_to 'Show', [post.page, post] td= link_to 'Edit', edit_page_post_path(post.page, post) td= link_to 'Destroy', [post.page, post], confirm: 'Are you sure?', method: :delete

/posts/page_index.slim

slide-12
SLIDE 12

class PostsController < ApplicationController before_filter :load_page def index if @page @posts = @page.posts.all render 'page_index' else @posts = Post.all end end def show ... end def new ... end ...

posts_controller.rb

slide-13
SLIDE 13

Problems

Introducing new view naming (‘page_index’) @page specific views can’ t be reused

slide-14
SLIDE 14

Since ‘show’, ‘new’, ‘page_index’, ‘edit’ specific for page, why not to group them under /pages/posts Note: renaming ‘page_index’ back to ‘index’

Solution

slide-15
SLIDE 15

class PostsController < ApplicationController before_filter :load_page def index if @page @posts = @page.posts.all render 'pages/posts/index' else @posts = Post.all end end def show @post = @page.posts.find(params[:id]) render 'pages/posts/show' end def new @post = @page.posts.new render 'pages/posts/new' end def edit @post = @page.posts.find(params[:id]) render 'pages/posts/edit' end

slide-16
SLIDE 16

Problem

Specifying views manually “you have to type it with your hands”


  • Tim Oxley

Views and Controller are in different scopes

slide-17
SLIDE 17

Split controller posts_controller.rb into posts_controller.rb /pages/posts_controller.rb

Solution

slide-18
SLIDE 18

Two controllers Same action Two views

slide-19
SLIDE 19

routes.rb

resources :pages, :only => :index resources :pages, :module => "pages" do resources :posts end

slide-20
SLIDE 20

class PostsController < ApplicationController def index @posts = Post.all end end

/posts_controller.rb

slide-21
SLIDE 21

class Pages::PostsController < ApplicationController before_filter :load_page def index @posts = @page.posts.all end def show @post = @page.posts.find(params[:id]) end def new @post = @page.posts.new end ... end

/pages/posts_controller.rb

slide-22
SLIDE 22

Don’ t need to specify views
 e.g. ‘pages/posts/show’ No ‘IF’ s

Wins

slide-23
SLIDE 23

Problem

You will probably will have other resources nested under /pages/ and all of them require @page variable in controller resources :pages, :only => :index resources :pages do resources :posts resources :images end

slide-24
SLIDE 24

Solution

Inherit application controller for page nested resources

slide-25
SLIDE 25

/pages/application_controller.rb

class Pages::ApplicationController < ApplicationController before_filter :load_page private def load_page @page = Page.find(params[:page_id]) end end

slide-26
SLIDE 26

/pages/posts_controller.rb

class Pages::PostsController < Pages::ApplicationController def index @posts = @page.posts.all end def show @post = @page.posts.find(params[:id]) end def new @post = @page.posts.new end ... end

slide-27
SLIDE 27

A lot of repetition for a standard controller actions

Problem

slide-28
SLIDE 28

Solution

CanCan
 https:/ /github.com/ryanb/cancan/

slide-29
SLIDE 29

/pages/posts_controller.rb

class Pages::PostsController < Pages::ApplicationController load_and_authorize_resource :through => :page def index end def show end def new end def edit end ... end

slide-30
SLIDE 30

Summary

Controllers:
 /posts_controller.rb
 /pages/posts_controller.rb
 /pages/application_controller.rb Views
 /posts/index
 /pages/posts/index
 /pages/posts/show
 /pages/posts/new
 /pages/posts/ edit
 /pages/posts/_form