itora web

9Dec/110

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

2Dec/110

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

Tagged as: No Comments