ActiveRecord Validation #3 - validates_with -

2014-08-27T00:00:00+00:00 rspec Ruby Rails

公式ドキュメント: http://guides.rubyonrails.org/active_record_validations.html#validates-with

ActiveModel::Validatorを用いて検証処理を実装する方法を提供するヘルパー的な感じなのではと

require "rails_helper"

class EntryValidator < ActiveModel::Validator
  def validate(record)
    # optionsでバリデーションオプションを取得可能

    record.errors[:name] << "can`t be blank" if record.name.blank?
  end
end

class Entry < ActiveRecord::Base
  validates_with EntryValidator,
    fields: [:name] # options
end

describe Entry do
  fixtures :entry

  it "validates_withのテスト" do
    expect(Entry.new({ name: "hoge" }).valid?).to eq true

    entry = Entry.new
    expect(entry.valid?).to eq false

    errors = entry.errors
    expect(errors).not_to be_empty

    messages = errors.messages
    expect(messages).not_to be_empty

    message = messages.first
    expect(message).to eq [:name, ["can`t be blank"]]
  end
end

てな感じっすけど、例えばvalidateメソッド内でpresenceとかを指定して既存するバリデーションで処理したいようなケースの場合には

class EntryValidator < ActiveModel::Validator
  def validate(record)
    record.validates_presence_of :name
  end
end

みたいにするか

class EntryValidator < ActiveModel::Validator
  def validate(record)
    ActiveModel::Validations::PresenceValidator.new(attributes: [:name]).validate record
  end
end

みたいな事すれば良いっぽい。これが良いのかは微妙だけど

又、別にActiveModel::Validatorを実装しなくても単純なRubyオブジェクトでメソッドを実装するだけでも出来る方法もあるっぽい

require "rails_helper"

class EntryValidator
  def initialize(entry)
    @entry = entry
  end

  def validate
    @entry.errors[:name] << "can`t be blank" if @entry.name.blank?
  end
end

class Entry < ActiveRecord::Base
  validate do |entry|
    EntryValidator.new(entry).validate
  end
end

describe Entry do
  fixtures :entry

  it "validates_withのテスト" do
    expect(Entry.new({ name: "hoge" }).valid?).to eq true

    entry = Entry.new
    expect(entry.valid?).to eq false

    errors = entry.errors
    expect(errors).not_to be_empty

    messages = errors.messages
    expect(messages).not_to be_empty

    message = messages.first
    expect(message).to eq [:name, ["can`t be blank"]]
  end
end

っていう感じで。まぁドキュメント読んだ方が良いかと

ActiveRecord Validation #4 - validates_each - ActiveRecord Validation #2