如何回滚rails save / transaction?

时间:2015-02-21 18:07:01

标签: ruby-on-rails activerecord rollback

在我的控制器中,我有一些代码,如...

...
if user.save
    something = Something.where("thing = ?", thing)
    if !(something.nil?)
        render json: { something: something }
    else
        #I WOULD LIKE TO ROLLBACK THE user.save HERE
    end
else
    render json: { error: user.errors.full_messages }, status: :bad_request
end

我试过了

raise ActiveRecord::Rollback, "Could not create new User, Something was not found."
render json: { error: "Could not create new User, Something was not found"}, status: :unprocessable_entity

代替上面的ROLLBACK COMMENT区域,但这不起作用。 user.save最终会通过。它向“rails s”吐出一些东西,但它不会回滚最后一笔交易。

3 个答案:

答案 0 :(得分:5)

如果您想使用与您提到的相同意义上的交易,您可以做类似的事情

User.transaction do
  if user.save
    something = Something.where("thing = ?", thing)
    if !(something.nil?)
      render json: { something: something }
    else
      raise ActiveRecord::Rollback
    end
  else
   render json: { error: user.errors.full_messages }, status: :bad_request
  end
end

不确定在事务中包装响应是否有效,但您需要对其进行测试。

PS: 这两行

something = Something.where("thing = ?", thing)
if !(something.nil?)

等同于

if Something.exists?(thing: thing)

答案 1 :(得分:3)

您需要将代码包装在事务中以使回滚正常工作。这是文档: http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

这样的东西
ActiveRecord::Base.transaction do
  # the code from your question
end

关键是user.save调用(修改数据库)和raise ActiveRecord::Rollback调用都需要在该块中。

答案 2 :(得分:1)

您可以这样做:

something = Something.where(thing: thing)

if something && user.save
    render json: { something: something }
else
    render json: { error: user.errors.full_messages }, status: :bad_request
end