Ruby-on-rails 如何拯救模型交易并向用户显示错误?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24218477/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:42:11  来源:igfitidea点击:

How to rescue model transaction and show the user an error?

ruby-on-railsrubyactiverecordtransactions

提问by NoDisplayName

So imagine you have 2 models, Person and Address, and only one address per person can be marked as 'Main'. So if I wanna change a person's main address, I need to use a transaction, to mark the new one as main and unmark the old one. And as far as I know using transactions in controllers is not good so I have a special method in model, thats what I've got:

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

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

Model:

模型:

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

So thequestion is, if the transaction in the model method fails, I need to rescue it and notify the user about the error, how do I do that? Is there a way to make this model method return true or false depending on whether the transaction was successful or not, like save method does?

所以问题是,如果模型方法中的事务失败,我需要挽救它并通知用户错误,我该怎么做?有没有办法让这个模型方法根据交易是否成功而返回真或假,就像 save 方法那样?

I probably could put that transaction in the controller and render the error message in the rescue part, but I guess its not right or I could put that method in a callback, but imagine there is some reason why I cant do that, whats the alternative?

我可能可以将该事务放入控制器并在救援部分呈现错误消息,但我想它不正确,或者我可以将该方法放入回调中,但是想象一下我不能这样做的原因,有什么替代方法?

PS dont pay attention to finding instances with params id and id2, just random thing to show that I have 2 instances

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

回答by apneadiving

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

FYI, an exception looks like:

仅供参考,异常如下:

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

And:

和:

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

Side note, you can change self.save!to save!

旁注,您可以更改self.save!save!



Alternate solution if you want to keep your active model errors:

如果您想保留活动模型错误,请使用替代解决方案:

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