Rails 2.0 scaffolding
16th May, 2008The most valuable usage for scaffolding is when you use it in the administration part of the site. The administration is usually separated in separate module/folder.
The new rails scaffolding is not good because:
- It is time taking to setup nested scaffold
- I have tons of uselss source code in the scaffolding like
respond_to ...that is usable very rare or never. - The HTML that is generated is ugly and not usable for CSS skin
- Not using the nice ruby style iterations
.eachinstead offor's - Code repetition, the “new” and the “edit” views has the same form elements
- Not easy to find documentation
I find Akita article for scaffolding. It is is great that he has covered some real cases. It is a lot of reading and I must read/copy/paste every time I need to make a scaffold. Here is step by step on making scaffold for administration.
- ruby script/generate scaffold admin::BadArticle NOT PLURAL!
- user:references
- description:text,string
- fixed:boolean
- timestamps are automaticaly added
- Add in routes.rb
map.namespace :admin do |admin| admin.resources :bad_articles end
- Model
- Rename
admin::BadArticles -> BadArticle, - move it to the model directory
- rename the file
- Rename
- Fix the migration file:
- remove the prefix from the migration class,
- remove the prefix from table name
- rename the file
- URL references
- admin_bad_articles_url
- redirect_to([:admin, bad_article])
- Controller
- rename all Admin::BadArticles -> BadArticle except in the controller name
- Probably you will want to make your scaffold inhired your base admin controller
def create ... format.html { redirect_to([:admin, @filtered_url]) } ... end-
def update ... format.html { redirect_to([:admin, @filtered_url]) } ... end class Admin::BadArticlesController < ApplicationController
class Admin::BadArticlesController < Admin::AuthController layout 'admin' (in case that you don't have it in the base controller)-
def index @admin_bad_articles = BadArticle.find(:all) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @admin_bad_articles } end end
- Index.rhtml.erb
<td><%= link_to 'Edit', edit_admin_bad_article_path(bad_articles) %></td>
<%= link_to 'New bad_articles', new_admin_bad_articles_path %>
- edit.rhtm
<%= link_to 'Show', @bad_article %> | <%= link_to 'Back',bad_articles_path %><%= link_to 'Show', [:admin, @bad_article_url] %> | <%= link_to 'Back', admin_bad_articles_path %>
- show.html.erb
<%= link_to 'Edit', edit_filtered_url_path(@filtered_url) %> | <%= link_to 'Back', filtered_urls_path %>
- new.rhtml
<% form_for(@bad_article) do |f| %><% form_for([:admin, @bad_article]) do |f| %>
<%= link_to 'Back', bad_articles_path %><%= link_to 'Back', admin_bad_articles_path %>
Traps:
The order of the routes in routes.rb does matter! In order to make the REST work you must have this block at the bottom of your routes.rb like this:
map.namespace :admin do |admin| admin.resources :bad_articles end
# Install the default route as the lowest priority. map.connect ':controller/:action/:id.:format' map.connect ':controller/:action/:id'
Remove simply_helpful plugin if you get the error:
undefined method `new_record?' for #Array:0x532a3e8
Debuging tools:
rake routes
Tips:
How to add custom actions to the REST
map.namespace :admin do |admin|
admin..esources :bad_articles, :member => {:toggle => :get}
admin.resources :orders, :member => { :resend => :post }
admin.resources :users, :collection => { :filter => :any }
end
Then in the controller:
def toggle @bad_article = BadArticle.find(params[:id]) @bad_article.fixed = ! @bad_article.fixed @bad_article.save redirect_to admin_bad_articles_url end
And in the view:
<%= toggle_admin_bad_article_url(filtered_url) %>
More reading here
Resources:
Tags: rails