如何回滚rails save/transaction?

chr*_*s P 7 activerecord ruby-on-rails 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
Run Code Online (Sandbox Code Playgroud)

我试过了

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
Run Code Online (Sandbox Code Playgroud)

代替上面的ROLLBACK COMMENT区域,但这不起作用.user.save最终会通过.它向"rails s"吐出一些东西,但它不会回滚最后一个事务.

Moh*_*ady 7

如果你想使用你所提到的相同意义上的交易,你可以做这样的事情

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
Run Code Online (Sandbox Code Playgroud)

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

PS:这两行

something = Something.where("thing = ?", thing)
if !(something.nil?)
Run Code Online (Sandbox Code Playgroud)

只是相当于

if Something.exists?(thing: thing)
Run Code Online (Sandbox Code Playgroud)


小智 6

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

就像是

ActiveRecord::Base.transaction do
  # the code from your question
end
Run Code Online (Sandbox Code Playgroud)

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


Sha*_*med 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
Run Code Online (Sandbox Code Playgroud)