A volte le 7 azioni CRUD stanno un po' strette e sarebbe bello poter espoandere le azioni del nostro controller senza troppi problemi, ma quando vale la pena aggiungere nuove azioni? Un caso particolare potrebbe essere quello di voler effettuare delle ricerce su un modello o di ordinare i risultati ottenuti.
Supponiamo di avere un modello post e di avere in posts_controller:
def index @posts = Post.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @posts } end end
ora volgiamo ordinare i risultati per data di creazione o nome del post, in questo caso non sarà necessario aggiungere nessuna nuova azione, ma basterà aggiungere un parametro nella querystring
def index sort_by = (params[:order] == 'created_at' ? 'created_at desc' : 'name') @posts = Post.find(:all, :order => sort_by) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @posts } end end
chiamando http://localhost:3000/posts?order=created_at ordineremo i posts per data di creazione e così via.
Se vogliamo cercare tutti i post che contengono una determinata chiave dobbiamo aggiungere una nuova azione nel nostro controller che ci permetta di filtrare i posts visualizzati in index.html.erb, questo perchè stiamo cercando di implementare una azione che non è compresa nelle 7 azioni CRUD.
def search @posts = Post.find(:all, :conditions => ['title LIKE ?', '%'+params[:q]+'%']) respond_to do |format| format.html # search.html.erb format.xml { render :xml => @posts } end end
in questo caso è necessario modificare il file config/routes.rb, in quanto la nuova azione non fa parte delle famose sette azioni CRUD. Modifichiamo la riga
map.resources :posts
in questo modo
map.resources :post, :collection => { :search => :get }
questo ci aprirà una route verso l'azione search accessibile attraverso GET, l'opzione collection indica che l'azione opera su un insieme di oggetti e non su un singolo post.
Nella view index.html.erb è d'obbligo aggiungere il form che passerà i dati al controller
<% form_tag search_posts_path, :method => :get do -%> <%= text_field_tag :q, params[:q] %> <%= submit_tag 'Search' %> <% end -%>
Notate che abbiamo usato l'opzione method settata a GET per forzare l'invio del form usando una richiesta GET.
CONCLUSIONI
Aggiungere azioni customizzate ad un controller è consigliabile solo quando l'operazione che vogliamo svolgere non è prensent nelle azioni CRUD standard e quando nessuna di esse può essere riutizilizzata per svolgere il compito che ci siamo posti.