The 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
.each
instead 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