Active RecordのConditional Validation便利
- ステータス(status)が1になるまでデータが送られ続ける
- ステータスが1の時は配送完了日(completion_date)が入る
- ステータスが1以外の時は配送完了日がnilになる
みたいなデータ連携をした時に便利だった。 外部のアプリケーションで作られたデータを自分のアプリケーションのDBにInsertする時、 データの不整合が起きないように、条件を指定して検証できる。
実行環境
- Ruby 2.2.2
- Rails 4.2.3
- RSpec 3.3
- factory_girl 4.5.0
- sqlite3 1.3.10
Item
delivered?
が true の時(statusが1の時)だけ completion_date
のバリデーションを実行する。
以下のように書くとできる。
class Item < ActiveRecord::Base validates :status, format: { with: /\A([1-9])\z/}, presence: true validates :completion_date, format: { with: /(\A\d{4}/\d{1,2}/\d{1,2}\z)/ }, presence: true, if: :delivered? def delivered? status == 1 end end
バリデーションのテスト
RSpec.describe Item, :type => :model do describe 'completion_date' do it 'ステータスが4で対応完了日がnilの時' do item = build(:item, status: 4, completion_date: nil) expect(item.valid?).to be_truthy end it 'ステータスが1で対応完了日がnilの時' do item = build(:item, status: 1, completion_date: nil) expect(item.valid?).to be_falsey end it 'ステータスが1で対応完了日が2015/07/29の時' do item = build(:item, status: 1, completion_date: 2015/07/29) expect(item.valid?).to be_truthy end end end
他にも条件を指定する方法はいくつかある。続きはRailsGuidesで。