如何挽救模型事务并向用户显示错误



假设您有2个模型,Person和Address,并且每个人只有一个地址可以标记为'Main'。如果我想改变一个人的主地址,我需要使用一个交易,将新地址标记为主地址,并取消旧地址的标记。据我所知,在控制器中使用事务是不好的所以我在模型中有一个特殊的方法,这就是我得到的:

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

问题是,如果模型方法中的事务失败,我需要挽救它并通知用户错误,我该怎么做?是否有一种方法,使这个模型方法返回真或假取决于是否成功的事务,像保存方法吗?

我可能可以把那个事务放在控制器中,并在救援部分呈现错误消息,但我猜这是不对的,或者我可以把那个方法放在回调中,但想象一下,有一些原因为什么我不能这样做,替代方案是什么?

PS不要注意寻找具有参数id和id2的实例,只是随机的东西来显示我有2个实例

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

最新更新