Anyone who's had to deal with nested resources knows that it can get really messy to have to make everything conditional to support them. Basically it's just a pain in the ass. If you want to support a nesting structure like the one in the example below you'll be looking at a big tangled bowl of spaghetti in no time.
Automatic Resources saves you the trouble. It dynamically defines finder methods in your controllers and helpers as well as simple named urls that are 100% compatible with the standard ones but produce beautiful nested resource urls just like you should expect them to.
Automatic Resources doesn't delve into Rails internals or do anything your grandmother would disapprove of. You can expect it to keep on keepin' on.
map.resources :blogs do |blog| blog.resources :categories, :has_many => [:posts] blog.resources :posts end class PostsController < ApplicationController automatic_resources :blog, :category, :post # Add a prepend_before_filter that ensures that the blog resource exists, otherwise # call +record_not_found+ require_resource :blog, :filter_method => :prepend_before_filter # This resource is required to be valid if it is in the url, otherwise it # is not required. Defaults to using the before_filter if :filter_method is # not specified. sometimes_require_resource :category # All other options are passed on to the selected filter method. require_resource :post, :only => [:show, :update] # Normal filter methods are created and used so they can be handled in the # usual way: skip_before_filter :sometimes_require_category_filter def show # blog, category, post methods are generated and available as helpers @blog_name = blog.name if blog? @category_name = category.name if category? @title = post.title # blogs, categories, posts collection methods as well: @category_names = categories.map(&:name) if category? @post_dates = posts.map(&:created_on) # Passing a collection method false for the execute parameter returns the # correctly scoped collection object without executing find(:all), which # allows you to apply other operations instead: @blog_count = blogs(false).count end def new # parent is automatically determined as either blog or category depending # on the route we used to get here. @post = build_post end def update if post.update_attributes(params[:post]) flash[:notice] = 'Item was successfully updated.' # The correctly nested path will be produced automatially without # explicitly specifying it: redirect_to(post) else render :action => "edit" end end end <% form_for(item) do |f| %> Name: <%= f.text_field :name %> <% end %> <%= link_to 'Show', item %> | <%= link_to 'Back', items_path %>
Copyright © 2009 Darrick Wiebe, released under the MIT license