ActiveRecord Validation #1
公式ドキュメント: http://guides.rubyonrails.org/active_record_validations.html
公式ドキュメントを読みつつ進めてみようかと。ただやたらと長いので何回かに分けて書く予定
基本的な使い方
require "rails_helper"
class Entry < ActiveRecord::Base
validates :name, presence: true
end
describe Entry do
it "(valid?|invalid?)メソッド" do
entry = Entry.new
# valid等を実行する前だとerrosはempty
expect(entry.errors).to be_empty
expect(entry.valid?).to eq false
expect(entry.invalid?).to eq true
# valid等を処理した後だとerrorsには検証エラーが入る
errors = entry.errors
expect(errors).not_to be_empty
messages = errors.messages
expect(messages).not_to be_empty
message = messages.first
expect(message).not_to be_nil
expect(message).to eq([:name, ["can"t be blank"]])
end
end
っていうような感じになる。valid等を動かさなくてもsaveやupdate等のメソッドを実行すると検証エラーな場合はfalseが返り、破壊的メソッドとして実行するとActiveRecord::RecordInvalidがスローされる模様
っていう感じで、基本的な事は終わり。presence等のValidation Helpersな所を進める
presence
.blank?でチェックされるバリデーションルール。上記の基本的な所なセクションでほとんど買いちゃってるけど
require "rails_helper"
class Entry < ActiveRecord::Base
validates :name, presence: { message: "can`t be empty" }
end
describe Entry do
it "presenceのテスト" do
entry = Entry.new
expect(entry.save).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).not_to be_nil
expect(message).to eq([:name, ["can`t be empty"]])
end
end
っていうようにエラーメッセージ辺りを変える事も可能。特にpresenceに限った機能じゃないはずなので(ry
acceptance
「規約に同意する」等の機能があるようなチェックボックス等によるデータ処理を検証するバリデーションヘルパーな模様。デフォルトであれば「"1″」を挿入しているかどうかで検証される(変更可能)。又、オプションで指定しない限りはnilじゃない場合にのみバリデーションが作用するようになる模様
require "rails_helper"
class Entry < ActiveRecord::Base
validates :terms_of_service, acceptance: true
end
describe Entry do
it "acceptanceのテスト" do
entry = Entry.new({ terms_of_service: "1" })
expect(entry.valid?).to be true
end
it "terms_of_serviceを指定しない場合" do
expect(Entry.new.valid?).to eq true
end
end
このテストは通る。2つ目のテストでterms_of_serviceを指定しなくてもvalid?がtrueになるのはnilな状態であればバリデーションが作用しない為かと。なので
class Entry < ActiveRecord::Base
validates :terms_of_service, acceptance: true, allow_nil: false
end
とした場合には上記でテストは成功する2つ目が成功しなくなる。allow_nilはグローバルオプション?だと思われるのでacceptanceに限って指定出来る物ではないのではと。でデフォルトだと"1″を入れなければならないが、acceptanceオプションを設定する事で変更可能
require "rails_helper"
class Entry < ActiveRecord::Base
validates :terms_of_service, acceptance: { accept: "yes" }, allow_nil: false
end
describe Entry do
it "acceptanceのテスト" do
entry = Entry.new({ terms_of_service: "yes" })
expect(entry.valid?).to be true
end
it "terms_of_serviceを指定しない場合" do
expect(Entry.new.valid?).to eq false
end
end
っていうような感じでacceptanceオプションを修正することで"1″以外で作用させる事も可能
んまぁ規約に同意するような機能とかなら同意してないならDB処理しないような仕組みをやれば良いだけなので、こういうのをする必要性はあんま無いと思うけど「メールによるお知らせを受け取る」ような設定オプションとかであればこういうのを使えば良いのではと(そういう場合はallow_nilを設定するべきではないはず)
confirmation
require "rails_helper"
class Entry < ActiveRecord::Base
validates :email, confirmation: true
end
describe Entry do
it "confirmationのテスト" do
entry = Entry.new({
email: "A@example.com",
email_confirmation: "B@example.com"
})
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).not_to be_nil
expect(message).to eq [:email_confirmation, ["doesn"t match Email"]]
end
it "email_confirmationを指定しない場合" do
entry = Entry.new({ email: "A@example.com" })
expect(entry.valid?).to eq true
end
end
ってな感じでconfirmation validation helperを使っているのに対して、_confirmationな仮想的属性の値を比較して同一かをチェック出来る。但しその仮想的属性がnilでは無い場合にのみチェックされる模様なので、2つ目のテストではemail_confirmationを指定してない為にバリデーションが作用しない為trueが返るような感じかと
exclusion
指定した項目が入ってはいけない場合のようなケースを検証出来る。逆がinclusion
require "rails_helper"
class Entry < ActiveRecord::Base
validates :subdomain, exclusion: { in: %w(www blog) }
end
describe Entry do
it "exclusionのテスト" do
expect(Entry.new({ subdomain: "user" }).valid?).to eq true
expect(Entry.new({ subdomain: "www" }).valid?).to eq false
expect(Entry.new({ subdomain: "blog" }).valid?).to eq false
end
end
inで指定したリストに該当するのが入るとバリデーションとしては不整合という形になる模様。恐らくはnilな場合だと検証が作用しないんかと思われる
inclusion
上記にあるexclusionの反対であるinclusion。リストにマッチする値のみが許可されるようなケースで使うっぽい
require "rails_helper"
class Entry < ActiveRecord::Base
validates :subdomain, inclusion: { in: %w(www blog) }
end
describe Entry do
it "inclusionのテスト" do
expect(Entry.new({ subdomain: "www" }).valid?).to eq true
expect(Entry.new({ subdomain: "blog" }).valid?).to eq true
expect(Entry.new({ subdomain: "user" }).valid?).to eq false
end
end
inで指定してあるのみ許容される。
format
正規表現とかで値の検証を行うようなパターンの場合に使う
require "rails_helper"
class Entry < ActiveRecord::Base
validates :postal_code, format: { with: /\A[\d]{3}\-[\d]{4}\z/ }
end
describe Entry do
it "formatのテスト" do
expect(Entry.new({ postal_code: "123-4567" }).valid?).to eq true
entry = Entry.new({ postal_code: "123-456a" })
expect(entry.errors).to be_empty
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).not_to be_nil
expect(message).to eq([:postal_code, ["is invalid"]])
end
end
てな感じでwithで指定した正規表現で値をチェック出来る。
とりあえず今回は以上。続きは後日