Contare child rows per un determinato record.
Supponiamo il caso di avere un post con relativi articoli, un autore con molti libri, una ditta che ha ricevuto degli ordini, o ancora, un la risposta piu' votata all'interno di un questionario.
In tutti questi casi, per ogni record principale avremo piu' record correlati. Supponiamo il caso di voler contare, nella pagina dove vengono elencate le risposte, quanti voti ogni risposta ha ricevuto, mostrando la piu' votata per prima. In Rails, possiamo scrivere un apposito metodo direttamente nel model.
class Answer < ActiveRecord::Base belongs_to :survey has_many :vote, :dependent => :destroy def self.more_voted(survey_id) voted_answer = find( :all, :select => 'answers.*, count(votes.id) as vote_count', :conditions => ["answers.survey_id = ?", survey_id], :joins => 'left outer join votes on votes.answer_id = answers.id', :group => 'answers.id', :Order => 'vote_count DESC' ) end end
Ora nella nostra action 'show' per il controller survey, dove vengono elencate tutte le risposte per il tal survey, possiamo recuperare le answer con il metodo appena creato.
@answers = Answer.more_voted(params[:survey_id])
e mostrare nella view il valore 'vote_count'
<% @answers.each do |a| %>
<tr class="even">
<td><%= "#{a.reply}" %></td>
<td><%= "#{a.vote_count}" %> </td>
</tr>
<% end %>
Link consigliati:
http://therailsway.com/2007/6/1/railsconf-recap-skinny-controllers
http://blog.devinterface.com/2010/06/rails-best-practices-1-fat-model-skinny-controller/
http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model
Aggiungere una action ad un controller in rails3
Rails3 cread i default sette azioni per ogni controller generato dinamicamente.
Se vogliamo aggiungere un azione, che ne so, per aggiornare un solo valore nel database, per una nuova view, o per quasiasi altra cosa, dobbiamo:
1)Scrivere la nostra azione nel controller, in questo esempio scrivero' un azione per disapprovare un commento, settando a "0" il valore del campo "approved".
def disapprove
@comment = Comment.find(params[:id])
if ( @comment.update_attribute(:approved, "0"))
respond_to do |format|
format.html { redirect_to(admin_comment_url(@comment),
:notice => 'Comment was unapproved.') }
format.xml { head:ok }
end
else
respond_to do |format|
format.html { render :action => "edit" }
format.xml {render:xml=>@comment.errors, :status => :unprocessable_entity }
end
end
end
Nel mio file routes.rb, dovro' dire alla mia app che oltre alle 7 azioni canoniche ce ne' un altra, disapprove. E dovro' specifivare che tipo di http request e', tra post, get, put e delete. Nel mio caso ho messo post, piu' dettagli qui
resources :comment do post 'disapprove',:on=>:member end
Lanciando "rake routes" nella cartella della mia app, posso vedere la nuova route creata, e vedere quale e' l'url da utlizzare nell'helper. Nel mio caso l'approvazione dei commenti si trova nell'admin area.
disapprove_admin_comment POST /admin/comments/:id/disapprove(.:format) {:controller=>"admin/comments", :action=>"disapprove"}
Ora creaimo un link all'azione
<%= link_to 'Disapprove', disapprove_admin_comment_path(@comment)%>
Dopo aver generato questo link, ottenevo un errore "No route matches..." la mia azione.
Errore risolto specificando nel link il tipo di http verb
<%= link_to 'Disapprove', disapprove_admin_comment_path(@comment), :method=>'post' %>
Consiglio questi screencast, per capire come vengono generate le routes, 1 e 2