保存失败后Rails没有回滚事务()

时间:2013-02-02 18:52:31

标签: ruby-on-rails ruby postgresql rspec transactions

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

验证工作正常,我甚至会在使用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)。

2 个答案:

答案 0 :(得分:3)

向集合添加项目会立即保存它(除非用户未保存)。 对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

答案 1 :(得分:2)

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

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

您可以通过关闭rspec:

中的交易来确认交易干扰
RSpec.configure do |config|
  config.use_transactional_fixtures = false
end