4

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

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

4

2 回答 2

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
于 2013-02-03T17:17:24.563 回答
2

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

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

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

RSpec.configure do |config|
  config.use_transactional_fixtures = false
end
于 2013-02-02T19:07:34.343 回答