Ruby on rails 如何回滚rails保存/事务?

Ruby on rails 如何回滚rails保存/事务?,ruby-on-rails,activerecord,rollback,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: {

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

...
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

代替上面的回滚注释区域,但这不起作用。user.save最终会通过。它向“rails s”吐出一些内容,但不会回滚上一个事务。

您可以这样做:

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

您需要将代码包装在事务中,回滚才能正常工作。以下是文档:

差不多

ActiveRecord::Base.transaction do
  # the code from your question
end

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

如果您想以您提到的相同方式使用事务,可以这样做

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
不确定在事务中包装响应是否有效,但您需要对此进行测试

附言: 这两条线

something = Something.where("thing = ?", thing)
if !(something.nil?)
只是相当于

if Something.exists?(thing: thing)

你必须做
某事。通过
查找
某事
是否存在。实际上,你甚至可以将其简化为
某事。存在?(thing:thing)和&user.save
我认为他可以将这部分检查转移到另一个方法中,并使用before\u save回调调用它。这将是一个更好的方法。@AbuShady,你不认为在另一个事务中结束
save
没有任何意义,而在内部
save
是使用事务实现的!我认为我们应该让他知道哪些是不好的做法,而不是让他按自己的方式去做这个事务由我控制,我可以选择什么时候回滚,什么时候不回滚,当您想要对一组查询进行分组并使其保持原子状态时使用它()对于他的条件,可能是第二个条件受第一次保存的影响,所以您不能一起测试它们,因此,如果第二个条件失败,您需要能够回滚。另一方面,我很清楚这种情况,rails正为此原因为您提供回调。您可以使用“保存后”或“保存前”回调执行此操作,它将按承诺回滚并撤消所有操作。:)这个条件很简单,或者至少没有提供太多的信息,如果第二个查询与第一个保存完全无关,您的答案会更好,但是如果它以某种方式链接,则您需要执行事务,特别是如果第一个保存创建了更多的保存,例如。然后以优雅的方式执行该操作将使用after\u save,如果我没有错,我只是在问,我总是从错误中学习这到底是什么东西,它与用户有任何关系吗?