Rails 在 save() 失败后不回滚事务



我有这个域模型:用户有一组项目,项目的状态可能无法通过验证。

验证工作正常,我什至看到当我使用 save! 时调用异常。

在我的控制器中,我有这个:

@user.items() << item
if @user.save
  render :json => {}, :status => :ok
else
  render :json => {:status => :error, :errors => item.errors}, :status => :bad_request
end

第一个 POST 成功,第二个 POST 失败,但是当我点击索引时,我仍然看到两个对象,好像第二个事务从未回滚。这是怎么回事?

我的测试是这样的:

  post :create
  post :create
  get :index
  ActiveSupport::JSON.decode(response.body).length.should == 1

编辑:即使在运行服务器时,事务也不会回滚(sqlite3)。

将项目添加到集合会立即保存它(除非用户未保存)。对 save 的调用创建自己的事务,这是回滚的内容,而不是保存项目的事务

您可以通过显式创建一个事务来强制所有内容进入同一事务。

begin
  User.transaction do
    @user.items << item
    @user.save!
    render :json => {}, :status => :ok
  end
rescue ActiveRecord::RecordInvalid
  render :json => {:status => :error, :errors => item.errors}, :status => :bad_request
end

听起来你在测试中遇到了嵌套事务问题。

我不相信 Postgres 的 Ruby 驱动程序处理嵌套事务,因此您只能获得外部事务的范围。 如果启用了事务夹具,则会有一个外部事务包装测试执行。 这意味着,如果受测控制器创建第二个内部事务并尝试回滚它,则可能无法获得正确的行为。

您可以通过关闭 rspec 中的事务来确认事务干扰:

RSpec.configure do |config|
  config.use_transactional_fixtures = false
end

最新更新