web-dev-qa-db-ja.com

モデルトランザクションをレスキューし、ユーザーにエラーを表示する方法は?

したがって、PersonとAddressという2つのモデルがあり、「Main」としてマークできるのは1人につき1つの住所だけだと想像してください。そのため、個人のメインアドレスを変更する場合は、トランザクションを使用して、新しいアドレスをメインとしてマークし、古いアドレスをマーク解除する必要があります。私の知る限り、コントローラーでトランザクションを使用するのは良くないので、モデルには特別な方法があります。

AddressesController < ApplicationController
 def update
  @new_address = Address.find(params[:id])
  @old_address = Address.find(params[:id2])
  @new_address.exchange_status_with(@old_address)       
 end
end

モデル:

class Address < ActiveRecord::Base
  def exchange_status_with(address)
    ActiveRecord::Base.transaction do
     self.save!
     address.save!
    end     
  end
end

したがって、問題は、モデルメソッドのトランザクションが失敗した場合、それをレスキューし、エラーについてユーザーに通知する必要があるということです。 saveメソッドのように、トランザクションが成功したかどうかに応じて、このモデルメソッドがtrueまたはfalseを返すようにする方法はありますか?

おそらくそのトランザクションをコントローラーに入れて、エラー部分をレスキュー部分にレンダリングすることができますが、正しくないか、そのメソッドをコールバックに入れることができますが、それができない理由があると想像してください?

PSは、params idとid2を持つインスタンスを見つけることに注意を払ってはいけません

24
NoDisplayName
def exchange_status_with(address)
  ActiveRecord::Base.transaction do
   self.save!
   address.save!
  end
rescue ActiveRecord::RecordInvalid => exception
  # do something with exception here
end

参考までに、例外は次のようになります。

#<ActiveRecord::RecordInvalid: Validation failed: Email can't be blank>

そして:

exception.message
# => "Validation failed: Email can't be blank"

サイドノート、変更できますself.save!からsave!


アクティブなモデルエラーを保持する場合の代替ソリューション:

class MyCustomErrorClass < StandardError; end

def exchange_status_with(address)
  ActiveRecord::Base.transaction do
   raise MyCustomErrorClass unless self.save
   raise MyCustomErrorClass unless address.save
  end
rescue MyCustomErrorClass
  # here you have to check self.errors OR address.errors
end
50
apneadiving