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

24Jul/110

Ruby on Rails themes generator

Questa gemma leva un sacco di castagne dal fuoco. Aggiungere stili e classi ad un'applicazione fatta prevalentemente da form e' decisamente noioso.
web-app-theme e' la gemma che fa al caso nostro.
Aggiungete al vostro Gemfile (su rails 3)

group :development, :test do
  gem 'web-app-theme', '>= 0.6.2'
end

poi

bundle install

e scegliete quale tema installare. Qua una lista con i relativi esempi.

rails g web_app_theme:theme --theme="drastic-dark" --app-name="Nome della mia app"

via bryanbibat

24Jul/110

Ruby on Rails Devise authentication

Aggiungete devise nel vostro Gemfile e lanciate "bundle install".
Ora create i file di configurazione necessari:

rails generate devise:install

Definite l'url che verra' utilizzata per i link di conferma sulle email di registrazione. In configurations/environments/development.rb

#Devise email
config.action_mailer.default_url_options = { :host => 'localhost:3000' }

Creiamo il file di migrazione e lo user model

rails generate devise User

Nello User model appena creato Models/user.rb , possiamo scegliere quali moduli includere od escludere, semplicemente togliendo quelli di default o aggiungendo quelli presenti nel commento del file user.rb.  A mio avviso quelli di default vanno piu' che bene.

class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable, :lockable and :timeoutable :recoverable,
devise :database_authenticatable, :registerable,
:rememberable, :trackable, :validatable

# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
end

Ora aprite il file Migrations/***devise_create_users.rb e commentate o aggiungete i moduli che avete aggiunto to tolto nello User Model. Poi fate la migrazione.

rake db:migrate

Con "rake routes" potete vedere tutte le routes messe a disposizione dalla vostra applicazione. Trovo questo comendo davvero molto utile, anche nel debug di un applicazione, o quando vogliamo verificare che ogni action abbia la sua view ben fatta.Un'altra cosa che cakePHP non ha (cominciano ad essere tante).
Ora se puntate il browser alla seguente url /users/sign_in potrete loggarvi. Per registrarvi andate qui /users/sign_up. Io ho incontrato il seguente errore:

No route matches "/users/sign_up"

Per risolverlo ho definito lo scope nel file routes, come spiegato qui http://stackoverflow.com/questions/2349604/using-devise-with-rails-3-beta
Per visualizzare i messaggi d'errore nella vostra applicazione, aggiungete queste linee di codice nel vostro application.html.erb.

<%- flash.each do |name, msg| -%>
  <%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
<%- end -%>

Sempre in application.html.erb, aggiungete i link alle azioni sign_in e sign_out. Scoprite i relativi path attraverso "rake routes" e aggiungete questo codice dopo il tag body:

<div id="user_nav">signed in as</div>

Per circoscrivere il raggio d'azione di un utente non loggato all'interno della nostra applicazione, definiamo quali azini sono ad esso concesse. Poniamo il caso che solo un utente loggato puo' creare o modificare un post, mentre l'utente sloggato puo' solo vederli.
Nel nostro "posts_controller" aggiungiamo la seguente funzione:

before_filter :authenticate_user!, :except => [:index, :show]

Per modificare le views di devise, lanciamo "rails g devise:views", ed otterremo un output simile a questo:

create app/views/devise
create app/views/devise/confirmations/new.html.erb
create app/views/devise/mailer/confirmation_instructions.html.erb
create app/views/devise/mailer/reset_password_instructions.html.erb
create app/views/devise/mailer/unlock_instructions.html.erb
create app/views/devise/passwords/edit.html.erb
create app/views/devise/passwords/new.html.erb
create app/views/devise/registrations/edit.html.erb
create app/views/devise/registrations/new.html.erb
create app/views/devise/sessions/new.html.erb
create app/views/devise/shared/_links.erb
create app/views/devise/unlocks/new.html.erb

Modifichiamo i seguenti file a nostro piacimento. Se vogliamo modificare i messaggi d'errore, mettiamo mano al file config/locales/devise_en.yml. Se invece vogliamo modificare le regole di controllo per la registrazione (es passare da "Password is too short (minimum is 6 characters)" a "Password is too short (minimum is 8 characters)") modifichiamo il file initializers/devise.rb.
Per modificare le URL di default con le quali avvengono le azioni di login e logout, apriamo il file routes.rb

devise_for :users, :path_names => {:sign_in => "login", :sign_up => "logout"}

.
Il nostro futuro user si logga inserendo email e password, come fare se in futuro ci venisse richiesto di sostituire il campo email con il campo username? prima di tutto aggiungiamo la colonna necessaria:

rails generate migration AddUsernameToUsers username:string
rake db:migrate

Ora in config/initializers/devise.rb aggiungiamo

config.authentication_keys = [ :username ]

Questo tutorial e' tratto dai seguenti railcasts:
http://railscasts.com/episodes/209-introducing-devise
http://railscasts.com/episodes/210-customizing-devise
Qua la pagina del progetto su github.