diff --git a/Manifest b/Manifest new file mode 100644 index 0000000..5684f64 --- /dev/null +++ b/Manifest @@ -0,0 +1,19 @@ +README +Rakefile +generators/nested_restful_scaffold/USAGE +generators/nested_restful_scaffold/nested_restful_scaffold_generator.rb +generators/nested_restful_scaffold/templates/controller.rb +generators/nested_restful_scaffold/templates/fixtures.yml +generators/nested_restful_scaffold/templates/functional_test.rb +generators/nested_restful_scaffold/templates/helper.rb +generators/nested_restful_scaffold/templates/layout.html.erb +generators/nested_restful_scaffold/templates/migration.rb +generators/nested_restful_scaffold/templates/model.rb +generators/nested_restful_scaffold/templates/style.css +generators/nested_restful_scaffold/templates/unit_test.rb +generators/nested_restful_scaffold/templates/view_edit.html.erb +generators/nested_restful_scaffold/templates/view_index.html.erb +generators/nested_restful_scaffold/templates/view_new.html.erb +generators/nested_restful_scaffold/templates/view_show.html.erb +nested_restful_scaffold.gemspec +Manifest diff --git a/README b/README new file mode 100644 index 0000000..bea95c0 --- /dev/null +++ b/README @@ -0,0 +1,96 @@ += Nested Restful Scaffold + +== What is NestedRestfulScaffold +NestedRestfulScaffold is a gem built by BadrIT (http://www.badrit.com) for easily generating controller, views, model and routes of nested resources. + +== Why NestedRestfulScaffold +The story begins when I was working on a project at BadrIT (http://www.badrit.com) using Ruby on Rails. +We needed to generate simple scaffold controller, views, models and routes for many nested resources. +There were a huge number of resources and nested resources and sometimes the length of nesting was more than two. +The problem I faced that I need to create them with rails scaffold generator then I need to update all generated controllers, views and models. +* I need to update routes.rb to handle nested paths like /libraries/1/books +* In the controller I need to be sure I am accessing the correct resource in the nested chain. +* All ActiveRecord calls in the controller must be scoped. +* Views will have a lot of work to support nested forms and links. +* Create the Active Record associations in my models. +This was a big overhead to do all of that with all resources, so I decided to create a generator to do all that work for me. + +== How to install +To install QuickMagick just type at your command line: + gem install nested_restful_scaffold +... and it's done. +You don't have to install any libraries or compile code from source. + +== How to use +Usage: + script/generate nested_restful_scaffold ModelName [field:type, field:type, resource1,resource2,...:resources] + +Lets start with an example of a library resource and each library has books and each book has pages. + +=== Library Resource +Use the following command to create library resource + script/generate nested_restful_scaffold library name:string address:text +It will use rails scaffold generator because there isn't any nested resources included in the previous command. + +=== Book & Page Resources +Use the following command to create library resource + script/generate nested_restful_scaffold book name:string description:text library:references library:resources + script/generate nested_restful_scaffold page contents:text book:references library,book:resources + +As it is shown, we used library:resources for books resources and library,book:resources for pages resources. +They will do the same job of rails scaffold generator in addition to the following: N.B. I will explain the result of the pages generation and it will be the same for book resources. + +* It will update the routes.rb file with libraries, books and pages routing to be as the following: + map.resources :libraries do |library| + library.resources :books do |book| + book.resources :pages + end + end +If you run rake routes, we can see the pages routes as the following: + library_book_pages GET /libraries/:library_id/books/:book_id/pages {:controller=>"pages", :action=>"index"} + formatted_library_book_pages GET /libraries/:library_id/books/:book_id/pages.:format {:controller=>"pages", :action=>"index"} + POST /libraries/:library_id/books/:book_id/pages {:controller=>"pages", :action=>"create"} + POST /libraries/:library_id/books/:book_id/pages.:format {:controller=>"pages", :action=>"create"} + new_library_book_page GET /libraries/:library_id/books/:book_id/pages/new {:controller=>"pages", :action=>"new"} + formatted_new_library_book_page GET /libraries/:library_id/books/:book_id/pages/new.:format {:controller=>"pages", :action=>"new"} + edit_library_book_page GET /libraries/:library_id/books/:book_id/pages/:id/edit {:controller=>"pages", :action=>"edit"} +formatted_edit_library_book_page GET /libraries/:library_id/books/:book_id/pages/:id/edit.:format {:controller=>"pages", :action=>"edit"} + library_book_page GET /libraries/:library_id/books/:book_id/pages/:id {:controller=>"pages", :action=>"show"} + formatted_library_book_page GET /libraries/:library_id/books/:book_id/pages/:id.:format {:controller=>"pages", :action=>"show"} + PUT /libraries/:library_id/books/:book_id/pages/:id {:controller=>"pages", :action=>"update"} + PUT /libraries/:library_id/books/:book_id/pages/:id.:format {:controller=>"pages", :action=>"update"} + DELETE /libraries/:library_id/books/:book_id/pages/:id {:controller=>"pages", :action=>"destroy"} + DELETE /libraries/:library_id/books/:book_id/pages/:id.:format {:controller=>"pages", :action=>"destroy"} + +* Pages controller has new method book to get its parent resource + protected + def book + @book ||= Library.find(params[:library_id]).books.find(params[:book_id]) + end +* All ActiveRecord calls for page resource will be through its book to be well scoped. + @pages = book.pages +* The most bunch of work in in views files +
Path: | +README + | +
Last Update: | +Thu Sep 17 15:21:24 +0200 2009 | +
+NestedRestfulScaffold is a gem built by BadrIT (www.badrit.com) for easily generating +controller, views, model and routes of nested resources. +
++The story begins when I was working on a project at BadrIT (www.badrit.com) using Ruby on Rails. We +needed to generate simple scaffold controller, views, models and routes for +many nested resources. There were a huge number of resources and nested +resources and sometimes the length of nesting was more than two. The +problem I faced that I need to create them with rails scaffold generator +then I need to update all generated controllers, views and models. +
++This was a big overhead to do all of that with all resources, so I decided +to create a generator to do all that work for me. +
++To install QuickMagick just type at your command line: +
++ gem install nested_restful_scaffold ++
+… and it‘s done. You don‘t have to install any libraries +or compile code from source. +
++Usage: +
++ script/generate nested_restful_scaffold ModelName [field:type, field:type, resource1,resource2,...:resources] ++
+Lets start with an example of a library resource and each library has books +and each book has pages. +
++Use the following command to create library resource +
++ script/generate nested_restful_scaffold library name:string address:text ++
+It will use rails scaffold generator because there isn‘t any nested +resources included in the previous command. +
++Use the following command to create library resource +
++ script/generate nested_restful_scaffold book name:string description:text library:references library:resources + script/generate nested_restful_scaffold page contents:text book:references library,book:resources ++
+As it is shown, we used library:resources for books resources and +library,book:resources for pages resources. They will do the same +job of rails scaffold generator in addition to the following: N.B. I will +explain the result of the pages generation and it will be the same for book +resources. +
++ map.resources :libraries do |library| + library.resources :books do |book| + book.resources :pages + end + end ++
+If you run rake routes, we can see the pages routes as the following: +
++ library_book_pages GET /libraries/:library_id/books/:book_id/pages {:controller=>"pages", :action=>"index"} + formatted_library_book_pages GET /libraries/:library_id/books/:book_id/pages.:format {:controller=>"pages", :action=>"index"} + POST /libraries/:library_id/books/:book_id/pages {:controller=>"pages", :action=>"create"} + POST /libraries/:library_id/books/:book_id/pages.:format {:controller=>"pages", :action=>"create"} + new_library_book_page GET /libraries/:library_id/books/:book_id/pages/new {:controller=>"pages", :action=>"new"} + formatted_new_library_book_page GET /libraries/:library_id/books/:book_id/pages/new.:format {:controller=>"pages", :action=>"new"} + edit_library_book_page GET /libraries/:library_id/books/:book_id/pages/:id/edit {:controller=>"pages", :action=>"edit"} ++
+formatted_edit_library_book_page GET +/libraries/:library_id/books/:book_id/pages/:id/edit.:format +{:controller=>"pages", :action=>"edit"} +
++ library_book_page GET /libraries/:library_id/books/:book_id/pages/:id {:controller=>"pages", :action=>"show"} + formatted_library_book_page GET /libraries/:library_id/books/:book_id/pages/:id.:format {:controller=>"pages", :action=>"show"} + PUT /libraries/:library_id/books/:book_id/pages/:id {:controller=>"pages", :action=>"update"} + PUT /libraries/:library_id/books/:book_id/pages/:id.:format {:controller=>"pages", :action=>"update"} + DELETE /libraries/:library_id/books/:book_id/pages/:id {:controller=>"pages", :action=>"destroy"} + DELETE /libraries/:library_id/books/:book_id/pages/:id.:format {:controller=>"pages", :action=>"destroy"} ++
+ protected + def book + @book ||= Library.find(params[:library_id]).books.find(params[:book_id]) + end ++
+ <td><%= link_to 'Show', library_book_page_path(page.book.library,page.book,page) %></td> + <td><%= link_to 'Edit', edit_library_book_page_path(page.book.library,page.book,page) %></td> + <td><%= link_to 'Destroy', library_book_page_path(page.book.library,page.book,page), :confirm => 'Are you sure?', :method => :delete %></td> ++
+and two links at the end of the html page to new page and to return to +books page +
++ <%= link_to 'New page', new_library_book_page_path %> + <%= link_to 'Return to books', library_books_path %> ++
+NestedRestfulScaffold is very easy to install, very easy to use and allows +you to generate all that work for you. +
++It will be very suitable for you if you are building a RESTful API or +application with nested resources. +
++It will reduce the overhead of updating controller, views, models and +routes. +
++For more information on nested resources check: +
++adam.blog.heroku.com/past/2007/12/20/nested_resources_in_rails_2 +
++www.akitaonrails.com/2007/12/12/rolling-with-rails-2-0-the-first-full-tutorial +
+ +
+ <%= attribute.column.human_name %>
+ <% if attribute.type.to_s != "references" || options[:skip_select] %>
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
+ <% else %>
+ <%%= select("<%= singular_name %>", "<%= attribute.name %>_id", <%= attribute.name.classify %>.find(:all<%= generate_conditions singular_name, attribute.name %>).collect{|p| [p.name, p.id]}) %>
+ <% end %>
+
+ <%%= f.submit "Update" %> +
+<%% end %> + +<%%= link_to 'Show', <%= nested_resource_path singular_name, :instance_object => true %> %> | +<%%= link_to 'Back', <%= nested_resource_path singular_name, :instance_object => true, :plural => true %> %> diff --git a/generators/nested_restful_scaffold/templates/.tmp_view_index.html.erb.16528~ b/generators/nested_restful_scaffold/templates/.tmp_view_index.html.erb.16528~ new file mode 100644 index 0000000..df8dcae --- /dev/null +++ b/generators/nested_restful_scaffold/templates/.tmp_view_index.html.erb.16528~ @@ -0,0 +1,26 @@ +<%= attribute.column.human_name %> | +<% end -%> +|||
---|---|---|---|
<%%=h <%= singular_name %>.<%= attribute.name %><%= ".name" if attribute.type.to_s == "references" && !options[:skip_select] %> %> | +<% end -%> +<%%= link_to 'Show', <%= nested_resource_path singular_name %> %> | +<%%= link_to 'Edit', <%= nested_resource_path singular_name, :prefix => "edit" %> %> | +<%%= link_to 'Destroy', <%= nested_resource_path singular_name %>, :confirm => 'Are you sure?', :method => :delete %> | +
+ <%= attribute.column.human_name %>
+ <% if attribute.type.to_s != "references" || options[:skip_select] %>
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
+ <% else %>
+ <%%= select("<%= singular_name %>", "<%= attribute.name %>_id", <%= attribute.name.classify %>.find(:all<%= generate_conditions singular_name, attribute.name %>).collect{|p| [p.name, p.id]}) %>
+ <% end %>
+
+ <%%= f.submit "Create" %> +
+<%% end %> + +<%%= link_to 'Back', <%= nested_resource_path singular_name, :instance_object => true, :plural => true %> %> diff --git a/generators/nested_restful_scaffold/templates/.tmp_view_show.html.erb.31581~ b/generators/nested_restful_scaffold/templates/.tmp_view_show.html.erb.31581~ new file mode 100644 index 0000000..9200800 --- /dev/null +++ b/generators/nested_restful_scaffold/templates/.tmp_view_show.html.erb.31581~ @@ -0,0 +1,9 @@ +<% for attribute in attributes -%> ++ <%= attribute.column.human_name %>: + <%%=h @<%= singular_name %>.<%= attribute.name %><%= ".name" if attribute.type.to_s == "references" && !options[:skip_select] %> %> +
+<% end -%> + +<%%= link_to 'Edit', <%= nested_resource_path(singular_name, :prefix => "edit", :instance_object => true) %> %> | +<%%= link_to 'Back', <%= nested_resource_path singular_name, :instance_object => true, :plural => true %> %> diff --git a/generators/nested_restful_scaffold/templates/controller.rb b/generators/nested_restful_scaffold/templates/controller.rb new file mode 100644 index 0000000..3d23b01 --- /dev/null +++ b/generators/nested_restful_scaffold/templates/controller.rb @@ -0,0 +1,94 @@ +class <%= controller_class_name %>Controller < ApplicationController + # GET /<%= table_name %> + # GET /<%= table_name %>.xml + <% resource_name = parent_resource_name %> + def index + @<%= table_name %> = <%= resource_name %>.<%= table_name %> + + respond_to do |format| + format.html # index.html.erb + format.xml { render :xml => @<%= table_name %> } + end + end + + # GET /<%= table_name %>/1 + # GET /<%= table_name %>/1.xml + def show + @<%= file_name %> = <%= resource_name %>.<%= table_name %>.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.xml { render :xml => @<%= file_name %> } + end + end + + # GET /<%= table_name %>/new + # GET /<%= table_name %>/new.xml + def new + @<%= file_name %> = <%= class_name %>.new + @<%= file_name %>.<%= resource_name %> = <%= resource_name %> + + respond_to do |format| + format.html # new.html.erb + format.xml { render :xml => @<%= file_name %> } + end + end + + # GET /<%= table_name %>/1/edit + def edit + @<%= file_name %> = <%= resource_name %>.<%= table_name %>.find(params[:id]) + end + + # POST /<%= table_name %> + # POST /<%= table_name %>.xml + def create + @<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>]) if params[:<%= file_name %>][:<%= resource_name %>_id].nil? || params[:<%= file_name %>][:<%= resource_name %>_id] == <%= resource_name %>.id.to_s + @<%= file_name %>.<%= resource_name %>_id = <%= resource_name %>.id + + respond_to do |format| + if @<%= file_name %>.save + flash[:notice] = '<%= class_name %> was successfully created.' + format.html { redirect_to(<%= nested_resource_path singular_name, :instance_object => true %>) } + format.xml { render :xml => @<%= file_name %>, :status => :created, :location => @<%= file_name %> } + else + format.html { render :action => "new" } + format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity } + end + end + end + + # PUT /<%= table_name %>/1 + # PUT /<%= table_name %>/1.xml + def update + @<%= file_name %> = <%= resource_name %>.<%= table_name %>.find(params[:id]) + + respond_to do |format| + if @<%= file_name %>.update_attributes(params[:<%= file_name %>]) + flash[:notice] = '<%= class_name %> was successfully updated.' + format.html { redirect_to(<%= nested_resource_path singular_name, :instance_object => true %>) } + format.xml { head :ok } + else + format.html { render :action => "edit" } + format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity } + end + end + end + + # DELETE /<%= table_name %>/1 + # DELETE /<%= table_name %>/1.xml + def destroy + @<%= file_name %> = <%= resource_name %>.<%= table_name %>.find(params[:id]) + url_path = <%= nested_resource_path singular_name, :instance_object => true, :plural => true %> + @<%= file_name %>.destroy + + respond_to do |format| + format.html { redirect_to(url_path) } + format.xml { head :ok } + end + end + + protected + def <%= resource_name %> + @<%= resource_name %> ||= <%= generate_find_statement %> + end +end diff --git a/generators/nested_restful_scaffold/templates/fixtures.yml b/generators/nested_restful_scaffold/templates/fixtures.yml new file mode 100644 index 0000000..c210351 --- /dev/null +++ b/generators/nested_restful_scaffold/templates/fixtures.yml @@ -0,0 +1,19 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +<% unless attributes.empty? -%> +one: +<% for attribute in attributes -%> + <%= attribute.name %>: <%= attribute.default %> +<% end -%> + +two: +<% for attribute in attributes -%> + <%= attribute.name %>: <%= attribute.default %> +<% end -%> +<% else -%> +# one: +# column: value +# +# two: +# column: value +<% end -%> diff --git a/generators/nested_restful_scaffold/templates/functional_test.rb b/generators/nested_restful_scaffold/templates/functional_test.rb new file mode 100644 index 0000000..3b430a2 --- /dev/null +++ b/generators/nested_restful_scaffold/templates/functional_test.rb @@ -0,0 +1,45 @@ +require 'test_helper' + +class <%= controller_class_name %>ControllerTest < ActionController::TestCase + def test_should_get_index + get :index + assert_response :success + assert_not_nil assigns(:<%= table_name %>) + end + + def test_should_get_new + get :new + assert_response :success + end + + def test_should_create_<%= file_name %> + assert_difference('<%= class_name %>.count') do + post :create, :<%= file_name %> => { } + end + + assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>)) + end + + def test_should_show_<%= file_name %> + get :show, :id => <%= table_name %>(:one).id + assert_response :success + end + + def test_should_get_edit + get :edit, :id => <%= table_name %>(:one).id + assert_response :success + end + + def test_should_update_<%= file_name %> + put :update, :id => <%= table_name %>(:one).id, :<%= file_name %> => { } + assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>)) + end + + def test_should_destroy_<%= file_name %> + assert_difference('<%= class_name %>.count', -1) do + delete :destroy, :id => <%= table_name %>(:one).id + end + + assert_redirected_to <%= table_name %>_path + end +end diff --git a/generators/nested_restful_scaffold/templates/helper.rb b/generators/nested_restful_scaffold/templates/helper.rb new file mode 100644 index 0000000..9bd821b --- /dev/null +++ b/generators/nested_restful_scaffold/templates/helper.rb @@ -0,0 +1,2 @@ +module <%= controller_class_name %>Helper +end diff --git a/generators/nested_restful_scaffold/templates/layout.html.erb b/generators/nested_restful_scaffold/templates/layout.html.erb new file mode 100644 index 0000000..5c1f304 --- /dev/null +++ b/generators/nested_restful_scaffold/templates/layout.html.erb @@ -0,0 +1,17 @@ + + + + + +<%%= flash[:notice] %>
+ +<%%= yield %> + + + diff --git a/generators/nested_restful_scaffold/templates/migration.rb b/generators/nested_restful_scaffold/templates/migration.rb new file mode 100644 index 0000000..382fd11 --- /dev/null +++ b/generators/nested_restful_scaffold/templates/migration.rb @@ -0,0 +1,16 @@ +class <%= migration_name %> < ActiveRecord::Migration + def self.up + create_table :<%= table_name %> do |t| +<% for attribute in attributes -%> + t.<%= attribute.type %> :<%= attribute.name %> +<% end -%> +<% unless options[:skip_timestamps] %> + t.timestamps +<% end -%> + end + end + + def self.down + drop_table :<%= table_name %> + end +end diff --git a/generators/nested_restful_scaffold/templates/model.rb b/generators/nested_restful_scaffold/templates/model.rb new file mode 100644 index 0000000..5650dba --- /dev/null +++ b/generators/nested_restful_scaffold/templates/model.rb @@ -0,0 +1,5 @@ +class <%= class_name %> < ActiveRecord::Base +<% for attribute in attributes -%> +<%= "belongs_to :#{attribute.name}" if attribute.type.to_s == "references" %> +<% end -%> +end diff --git a/generators/nested_restful_scaffold/templates/style.css b/generators/nested_restful_scaffold/templates/style.css new file mode 100644 index 0000000..093c209 --- /dev/null +++ b/generators/nested_restful_scaffold/templates/style.css @@ -0,0 +1,54 @@ +body { background-color: #fff; color: #333; } + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { color: #000; } +a:visited { color: #666; } +a:hover { color: #fff; background-color:#000; } + +.fieldWithErrors { + padding: 2px; + background-color: red; + display: table; +} + +#errorExplanation { + width: 400px; + border: 2px solid red; + padding: 7px; + padding-bottom: 12px; + margin-bottom: 20px; + background-color: #f0f0f0; +} + +#errorExplanation h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + background-color: #c00; + color: #fff; +} + +#errorExplanation p { + color: #333; + margin-bottom: 0; + padding: 5px; +} + +#errorExplanation ul li { + font-size: 12px; + list-style: square; +} + diff --git a/generators/nested_restful_scaffold/templates/unit_test.rb b/generators/nested_restful_scaffold/templates/unit_test.rb new file mode 100644 index 0000000..96bd34a --- /dev/null +++ b/generators/nested_restful_scaffold/templates/unit_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class <%= class_name %>Test < ActiveSupport::TestCase + # Replace this with your real tests. + def test_truth + assert true + end +end diff --git a/generators/nested_restful_scaffold/templates/view_edit.html.erb b/generators/nested_restful_scaffold/templates/view_edit.html.erb new file mode 100644 index 0000000..8551f59 --- /dev/null +++ b/generators/nested_restful_scaffold/templates/view_edit.html.erb @@ -0,0 +1,20 @@ +
+ <%= attribute.column.human_name %>
+ <% if attribute.type.to_s != "references" %>
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
+ <% end %>
+
+ <%%= f.submit "Update" %> +
+<%% end %> + +<%%= link_to 'Show', <%= nested_resource_path singular_name, :instance_object => true %> %> | +<%%= link_to 'Back', <%= nested_resource_path singular_name, :instance_object => true, :plural => true %> %> diff --git a/generators/nested_restful_scaffold/templates/view_index.html.erb b/generators/nested_restful_scaffold/templates/view_index.html.erb new file mode 100644 index 0000000..c5035da --- /dev/null +++ b/generators/nested_restful_scaffold/templates/view_index.html.erb @@ -0,0 +1,26 @@ +<%= attribute.column.human_name %> | +<% end -%> +|||
---|---|---|---|
<%%=h <%= singular_name %>.<%= attribute.name %> %> | +<% end -%> +<%%= link_to 'Show', <%= nested_resource_path singular_name %> %> | +<%%= link_to 'Edit', <%= nested_resource_path singular_name, :prefix => "edit" %> %> | +<%%= link_to 'Destroy', <%= nested_resource_path singular_name %>, :confirm => 'Are you sure?', :method => :delete %> | +
+ <%= attribute.column.human_name %>
+ <% if attribute.type.to_s != "references" %>
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
+ <% end %>
+
+ <%%= f.submit "Create" %> +
+<%% end %> + +<%%= link_to 'Back', <%= nested_resource_path singular_name, :instance_object => true, :plural => true %> %> diff --git a/generators/nested_restful_scaffold/templates/view_show.html.erb b/generators/nested_restful_scaffold/templates/view_show.html.erb new file mode 100644 index 0000000..1883003 --- /dev/null +++ b/generators/nested_restful_scaffold/templates/view_show.html.erb @@ -0,0 +1,9 @@ +<% for attribute in attributes -%> ++ <%= attribute.column.human_name %>: + <%%=h @<%= singular_name %>.<%= attribute.name %> %> +
+<% end -%> + +<%%= link_to 'Edit', <%= nested_resource_path(singular_name, :prefix => "edit", :instance_object => true) %> %> | +<%%= link_to 'Back', <%= nested_resource_path singular_name, :instance_object => true, :plural => true %> %>