はじめに
あなたはすでに同志のポストから知っているように Rails 3.0の
ActiveModel抽象化に関するYehuda Katzには、ActiveRecordに検証モジュールなどのActiveModelのいくつかの側面が含まれるようになりました。
そして、始める前に、すでに持っている検証方法を思い出しましょう。
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
それらのすべてはまだ動作中ですが、Rails 3はいくつかの新しい素晴らしい代替手段を提供します。
新しいvalidate
方法
validate
メソッドは、検証オプション付きの属性とハッシュを受け入れます。 これは、通常の検証を次のように記述できることを意味します。
class Person < ActiveRecord::Base validates :email, :presence => true end
転送できるオプションは次のとおりです。
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
これにより、特定の属性に対して非常にシンプルで簡潔なオプションの広範な領域が提供され、必要なすべての検証を1か所に書き込むことができます。
たとえば、名前とメールを確認する必要がある場合は、次の操作を実行できます。
class User < ActiveRecord::Base validates :name, :presence => true, :length => {:minimum => 1, :maximum => 254} validates :email, :presence => true, :length => {:minimum => 3, :maximum => 254}, :uniqueness => true, :format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[az]{2,})$/i} end
したがって、モデルをすぐに見て、各属性にどの検証がハングしているのかを確認できます-コードと可読性にわずかな勝利があります:)
使い慣れたユースケースの取得
ただし、
:format => {:with => EmailRegexp}
を書くことは、いくつかの場所で書くのが少し重いです。これは、他のモデルに適用できる再利用可能な検証を作成するアイデアを示唆しています。
先に進みましょう-そして、Googleがどれだけかっこいいかを示すために、数文字以上の表現力豊かな正規表現を使用する必要がある場合はどうでしょうか。 :)
まあ、検証も手書きで書くことができます。 まず、アプリケーションの腸内の
lib
ディレクトリに
email_validator.rb
ファイルを作成します。
# lib/email_validator.rb class EmailValidator < ActiveModel::EachValidator EmailAddress = begin qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]' dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]' atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-' + '\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+' quoted_pair = '\\x5c[\\x00-\\x7f]' domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d" quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22" domain_ref = atom sub_domain = "(?:#{domain_ref}|#{domain_literal})" word = "(?:#{atom}|#{quoted_string})" domain = "#{sub_domain}(?:\\x2e#{sub_domain})*" local_part = "#{word}(?:\\x2e#{word})*" addr_spec = "#{local_part}\\x40#{domain}" pattern = /\A#{addr_spec}\z/ end def validate_each(record, attribute, value) unless value =~ EmailAddress record.errors[attribute] << (options[:message] || " ") end end end
lib
ディレクトリからの各ファイルは自動的にロードされ、バリデーターは
ActiveModel::EachValidator
から継承されるため、
ActiveModel::EachValidator
の名前は
ActiveModel::Validations
アクセスできるオブジェクトで使用できる動的バリデーターとして使用されます。 つまり、たとえば、これらはすべてActiveRecordオブジェクトです。
動的バリデーターの名前は、「Validator」という単語の左側にあるすべてのもので、小文字に変換されます。
したがって、
User
クラスは次のようになります。
# app/models/person.rb class User < ActiveRecord::Base validates :name, :presence => true, :length => {:minimum => 1, :maximum => 254} validates :email, :presence => true, :length => {:minimum => 3, :maximum => 254}, :uniqueness => true, :email => true end
注意してください
:email => true
? 非常に簡単ですが、最も重要なのは、どこでも使用できることです!
コンソールには、次のようなものが表示されます(独自のメッセージ「正しくない」):
$ ./script/console Loading development environment (Rails 3.0.pre) ?> u = User.new(:name => 'Mikel', :email => 'bob') => #<User id: nil, name: "Mikel", email: "bob", created_at: nil, updated_at: nil> >> u.valid? => false >> u.errors => #<OrderedHash {:email=>[" "]}>
クラスの検証
しかし、たとえば、3つの異なるモデル(
user
、
visitor
および
customer
)があり、それぞれが共通の検証を使用する必要がある場合はどうでしょう。 この場合、
validates
を
validates_with
に置き換え、これを行うだけです:
# app/models/person.rb class User < ActiveRecord::Base validates_with HumanValidator end # app/models/person.rb class Visitor < ActiveRecord::Base validates_with HumanValidator end # app/models/person.rb class Customer < ActiveRecord::Base validates_with HumanValidator end
そして、
lib
ディレクトリにファイルを置きます:
class HumanValidator < ActiveModel::Validator def validate(record) record.errors[:base] << "This person is dead" unless check(human) end private def check(record) (record.age < 200) && (record.age > 0) end end
そして、明らかにはるかにフェッチされた例をチェックしてください:
$ ./script/console Loading development environment (Rails 3.0.pre) >> u = User.new => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil> >> u.valid? => false >> u.errors => #<OrderedHash {:base=>["This person is dead"]}>
トリガー時間
予想どおり、各検証では次のサブオプションを使用できます。
:on :if :unless :allow_blank :allow_nil
:on :if :unless :allow_blank :allow_nil
:on :if :unless :allow_blank :allow_nil
:on :if :unless :allow_blank :allow_nil
:on :if :unless :allow_blank :allow_nil
それぞれが任意のメソッドの呼び出しを取得できます。 このように:
class Person < ActiveRecord::Base validates :post_code, :presence => true, :unless => :no_postcodes? def no_postcodes? true if ['TW'].include?(country_iso) end end
これは、おそらく、新しいレベルの柔軟性の第一印象を作るのに十分でしょう。