バリデーション(5)
バリデーションの仕上げにトランザクションの書き方メモ。
Rails 2.0のActiveRecordでは、トランザクションブロックにブロック引数が渡されないようだ。*1
古いヘルプによると以前は
# 以下のようにバリデーションがある場合 # Class Sample < ActiveRecord::Base # validates_presence_of :name # end transaction do |t| s1 = Sample.create(:name => 'n1', :value => 'v1') s2 = Sample.create(:value => 'v2') # error! if s1.errors.count + s2.errors.count > 0 t.rollback end end
こんな感じに書けたらしいが、現状だとこの書き方はできない*2。どうするかというと
transaction do s1 = Sample.create!(:name => 'n1', :value => 'v1') s2 = Sample.create!(:value => 'v2') # error! end rescue # rollback!!
こんなふうに、create!やsave!を使って例外を投げ、トランザクションの外側で受けるとよい。ちなみにトランザクションの内側で例外を受けてしまうとロールバックされない。
バリデーションメッセージを使いたい場合は、オブジェクトへの参照を設定してから例外を投げるとよい。
transaction do s1 = (@sample = Sample.new(:name => 'n1', :value => 'v1').save! s2 = (@sample = Sample.new(:value => 'v2')).save! # error! end rescue
こうしておくとビュー側の <%= error_messages_for :sample %> でバリデーションメッセージが拾える。