Forum: Italian Ruby user group Riutilizzo delle validazioni

Posted by pezzuya .. (pezzuya)
on 2010-01-30 19:27
Ciao a tutti.
Vista la mia poca conoscenza di rails mi trovo sempre più spesso a dover
fare operazioni di copia e incolla per fare le stesse validazioni (ad
esempio sul formato di indirizzi mail, numeri di telefono ecc) su
modelli diversi (cosa poco pratica e poco furba).
Quindi mi domandavo come (sicuramente ci deve essere un modo) é
possibile creare un "contenitore di validazioni" per le validazioni più
comuni e usarle "al bisogno" all'interno dei singoli modelli.
Avevo pensato di usare l'ereditarietà creando una classe
"ValidationsContainer" che eredita da "ActiveRecord" (Class
ValidationsContainer < ActiveRecord).
All'interno di "ValidationsContainer" definisco le mie validazioni "più
comuni" tipo:

def valid_email?
...
end

Poi faccio in modo che ogni modello che deve usare le validazioni di
"ValidationsContainer" erediti da quest'ultimo xes.

Class User < ValidationsContainer

A questo punto all'interno di User richiamando:

validate_valid_email? :email, :message => "L'email inserita non ha un
formato valido"

Dovrei poter "riusare" la validazione precedentemente creata...

Questo descritto é il giusto modo di procedere? O c'è un modo più
corretto?

Un grazie anticipato a tutte le persone che mi aiuteranno.

Ciao
Posted by Paolo Montrasio (pmontrasio)
on 2010-01-31 10:28
Le validazioni sono definite nel modulo Validations contenuto nel modulo 
ActiveRecord, per cui potresti mettere nella lib delle tue applicazioni 
un file validations_ext.rb fatto così:

module ActiveRecord
  module Validations

    def validates_email
      validates_format_of :email, :with => 
/\A([^@\s]+)@((?:[-a-z0-9]+\.)+
[a-z]{2,})\Z/i, :message => "L'email inserita non ha un formato valido"
    end

  end
end

Alle fine di config/environment.rb aggiungi require "validations_ext" e 
nel modello scrivi semplicemente

validates_email

Non l'ho testato ma dovrebbe funzionare. In questo modo non hai bisogno 
di far derivare i modelli da classi diverse dal solito ActiveRecord e 
non dovrai modificare i modelli già esistenti, salvo inserire le tue 
validazioni.

Lascio a te trovare il modo di passare argomenti a validates_email.
Magari guarda come fa active record nel suo file 
lib/active_record/validations.rb

Paolo

pezzuya .. wrote:
> Ciao a tutti.
> Vista la mia poca conoscenza di rails mi trovo sempre più spesso a dover
> fare operazioni di copia e incolla per fare le stesse validazioni (ad
> esempio sul formato di indirizzi mail, numeri di telefono ecc) su
> modelli diversi (cosa poco pratica e poco furba).
> Quindi mi domandavo come (sicuramente ci deve essere un modo) é
> possibile creare un "contenitore di validazioni" per le validazioni più
> comuni e usarle "al bisogno" all'interno dei singoli modelli.
> Avevo pensato di usare l'ereditarietà creando una classe
> "ValidationsContainer" che eredita da "ActiveRecord" (Class
> ValidationsContainer < ActiveRecord).
> All'interno di "ValidationsContainer" definisco le mie validazioni "più
> comuni" tipo:
> 
> def valid_email?
> ...
> end
> 
> Poi faccio in modo che ogni modello che deve usare le validazioni di
> "ValidationsContainer" erediti da quest'ultimo xes.
> 
> Class User < ValidationsContainer
> 
> A questo punto all'interno di User richiamando:
> 
> validate_valid_email? :email, :message => "L'email inserita non ha un
> formato valido"
> 
> Dovrei poter "riusare" la validazione precedentemente creata...
> 
> Questo descritto é il giusto modo di procedere? O c'è un modo più
> corretto?
> 
> Un grazie anticipato a tutte le persone che mi aiuteranno.
> 
> Ciao
Posted by pezzuya .. (pezzuya)
on 2010-01-31 12:23
> Lascio a te trovare il modo di passare argomenti a validates_email.
> Magari guarda come fa active record nel suo file 
> lib/active_record/validations.rb

Grazie Paolo.
Non ho sott'occhio "validation.rb" ma, in teoria, se la validazione 
richiedesse degli argomenti non mi basterebbe passarglieli alla 
chiamata?

per esempio così:

validates_email(argomento1, argomento2, ...)

Alla fine una validazione dovrebbe essere come una semplicissima azione 
o mi sbaglio?
Posted by Pietro Giorgianni (giorgian)
on 2010-01-31 14:09
(Received via mailing list)
Il 31 gennaio 2010 12.23, pezzuya .. <pezzuya-gruppi@yahoo.it> ha 
scritto:
> validates_email(argomento1, argomento2, ...)
>
> Alla fine una validazione dovrebbe essere come una semplicissima azione
> o mi sbaglio?

in validation.rb, i metodi di validazione si appoggiano a validates_each
http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M002161

L'help riporta un esempio semplice:
  class Person < ActiveRecord::Base
    validates_each :first_name, :last_name do |record, attr, value|
      record.errors.add attr, 'starts with z.' if value[0] == ?z
    end
  end

Questo perché il metodo validates_qualcosa viene chiamato durante la
definizione della classe, ma la validazione deve avvenire in una fase
successiva (di default è :on => :save, ma può essere :create o
:update).

Sempre da validations.rb viene un esempio più concreto:

      def validates_format_of(*attr_names)
        configuration = { :on => :save, :with => nil }
        configuration.update(attr_names.extract_options!)

        raise(ArgumentError, "A regular expression must be supplied as
the :with option of the configuration hash") unless
configuration[:with].is_a?(Regexp)

        validates_each(attr_names, configuration) do |record, attr_name, 
value|
          unless value.to_s =~ configuration[:with]
            record.errors.add(attr_name, :invalid, :default =>
configuration[:message], :value => value)
          end
        end
      end


pietro
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.