したがって、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を持つインスタンスを見つけることに注意を払ってはいけません
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