我有这个域模型:用户有一组项目,项目的状态可能无法通过验证。
验证工作正常,我甚至会在使用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)。
答案 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