外部参照を行ってるデータベースの更新を行う際にトランザクションで問題が起きる。
def create generate_dept_list generate_faculty_list @user = User.new(params[:user]) @student = Student.new(params[:student]) flg = false User.transaction(@user, @student) do @user.save @student.user_id = @user.id @student.save end if flg UpdatePinger.ping('students,users') flash[:notice] = '学生の登録完了.' redirect_to :action => 'list' else render :action => 'new' end end
このように書いていると、ユーザーのDBが更新されたあと学生のDBが更新されなくてもユーザーDBの登録が行われたままになった。
そこでいろいろ調べた結果
def create generate_dept_list generate_faculty_list @user = User.new(params[:user]) @student = Student.new(params[:student]) User.transaction(@user, @student) do @user.save! @student.user_id = @user.id @student.save! end UpdatePinger.ping('students,users') flash[:notice] = '学生の登録完了.' redirect_to :action => 'list' rescue render :action => 'new' end
こう書けばトランザクションがうまくいくことが判明。
しかし、トランザクション処理が行われてもValidateが行われないので、さらに調べると
def create generate_dept_list generate_faculty_list @user = User.new(params[:user]) @student = Student.new(params[:student]) # データ検証 is_valid = true is_valid = false unless @user.valid? is_valid = false unless @student.valid? unless is_valid render :action => 'new' return end User.transaction(@user, @student) do @user.save! @student.user_id = @user.id @student.save! end UpdatePinger.ping('students,users') flash[:notice] = '学生の登録完了.' redirect_to :action => 'list' rescue render :action => 'new' end
これでトランザクション処理もValidateも行われるようになった。