Hello everyone!
Ive been on rails for the last month or so and really enjoyed this
framework.
However its very hard to find documentation on how to do things right!
For example every beginner after a while realizes that having similar
CRUD actions in every controller and views for them is not DRY at all!
Few days ago I found http://dereksivers.com/rails-shared-controller.html
I quite like his generic controller, not Nub class though !
And I’ve adopted it for my project as:
controllers/basic_crud_controller.rb
…
class BasicCRUDController < ApplicationController
ITEMS_PER_PAGE = 15
before_filter :initialize_crud_controller
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }
def index
list
end
def list
@items = model_class.find :all, :limit => ITEMS_PER_PAGE,
:offset => ITEMS_PER_PAGE * (@sess[:page] -
1)
@pages = Paginator.new self, model_class.count, ITEMS_PER_PAGE,
@sess[:page]
render ‘shared/list’
end
def new
@item = model_class.new
#@editform = model_class.editform
render ‘shared/new’
end
def edit
@item = model_class.find(params[:id])
#@editform = model_class.editform
render ‘shared/edit’
end
def create
@item = model_class.new(params[:edit])
if @item.save
#flash[:notice] = ‘Region was successfully created.’
flash[:notice] = sprintf(_(:added),
(model_class.table_name.to_sym))
redirect_to :action => :list
else
#@editform = model_class.editform
render ‘shared/new’
end
end
def update
@item = model_class.find(params[:id])
if @item.update_attributes(params[:edit])
#flash[:notice] = ‘Region was successfully updated.’
flash[:notice] = sprintf((:updated),
(model_class.table_name.to_sym))
redirect_to :action => :list #:edit, :id => @region
else
#@editform = model_class.editform
render ‘shared/edit’
end
end
def destroy
model_class.find(params[:id]).destroy
flash[:notice] = sprintf((:deleted),
_(model_class.table_name.to_sym))
redirect_to :action => :list
end
private
def initialize_crud_controller
id = self.object_id
session[id] = { :page => 1 } unless session[id]
@sess = session[id]
@model_name = model_class.table_name.singularize
end
end
…
By the way, is this a good way to go?
Should something like this be generated when you generate scaffold?
I believe it should!
Then our custom controller looks like this:
controller/regions_controller.rb
…
class RegionsController < BasicCRUDController
def model_class
Region
end
end
…
Looks very DRY to me!
Now I would like to DRY the views as well
Its very easy with list:
views/shared/list.rhtml
…
Listing <%= @model_name.pluralize %>
<%= link_to 'New ' + @model_name, :action => :new %> <%= link_to 'Previous Page', { :page => @pages.current.previous } if @pages.current.previous %> <%= pagination_links(@pages) %> <%= link_to 'Next Page', { :page => @pages.current.next } if @pages.current.next %> <% for column in controller.model_class.content_columns %> <% end %><% for item in @items %>
<%= render :partial => 'list', :locals => { :item => item } %> <% end %><%= column.human_name %> | |
---|---|
<%= link_to 'Edit', :action => :edit, :id => item %> | <%= link_to 'Destroy', { :action => :destroy, :id => item }, :confirm => "Delete #{@model_name}: #{item.name} ?", :post => true %> |
And the custom view for list item:
views/region/_list.rhtml
…
Thats looks promising?
But there always will be but!
The new/edit templates seem not working so far
Consider this:
views/shared/new.rhtml
…
New <%= @model_name %>
<%= start_form_tag :action => :create %> <%= render :partial => 'shared/form' %> <%= submit_tag 'Create' %> <%= end_form_tag %> <%= link_to 'Back', :action => :list %> ...views/shared/_form.rhtml
…
<%= error_messages_for @model_name.to_sym %>
<%= render :partial => ‘edit’ %>
…
views/region/_edit.rhtml
…
Name
<%= text_field :region, :name %>
This way of doing thigs seems to be the right one.
So if anyone will get this last bit (new/edit) to work please let me
know!
I would appreciate any help and suggestions!
Thanks!