您可以手动管理事务提交/回滚吗?

时间:2015-04-16 16:58:14

标签: mysql ruby-on-rails activerecord transactions

我想做这样的事情:

["START", "a", "b", "c", "STOP", "START", "d", "e", "STOP"].each do |message|
  if message == "START"
    Transaction.begin
  elsif message == "STOP"
    Transaction.commit if Transaction.active?
  else
    begin
      Message.create!(body: message)
    rescue
      Transaction.rollback
    end
  end
end

简而言之,我有一串消息'并且我想对该流的部分进行交易。

每当" START"出现在流上,开始新的交易。每当一个"停止"出现,交易已经提交。

我在交易中苦苦挣扎。

我可以看到我可以做ActiveRecord :: Base.transaction do ... end,但是在这种情况下我不会工作,除非我批量处理所有事情,因为这里不可能流。

我看到有一个埋在ActiveRecord中的事务管理器我可能会使用(https://github.com/rails/rails/blob/0d76ab9c6f01e6390ba8878a296ff9d3ac6b9aa8/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb),但我还没有能够通过它来测试我的测试。

我认为问题的一部分也是RSpec的交易设备干扰,虽然禁用它们似乎也没有解决问题。

任何帮助都将不胜感激。

由于

2 个答案:

答案 0 :(得分:2)

我这样做:

messages.chunk {|value| value != 'START' && value != 'STOP'}.each do |is_data, bodies|
  if is_data
    Message.transaction do
      bodies.each {|body| Message.create(body: body)}
    end
  end
end

第一步是使用chunk对邮件进行分组。这个输出是一对数组。如果该对的第一个值为true,则第二个值是body的数组,如果不是,则body只是true false。通过这样重组的数据,使用现有的交易方法是微不足道的。

答案 1 :(得分:0)

您可以通过以下方式管理交易

manager = ActiveRecord::Base.connection.transaction_manager
...
manager.begin_transaction
...
manager.commit_transaction
...
manager.rollback_transaction

或在你的情况下

manager = ActiveRecord::Base.connection.transaction_manager
["START", "a", "b", "c", "STOP", "START", "d", "e", "STOP"].each do |message|
  if message == "START"
    manager.begin_transaction
  elsif message == "STOP"
    manager.commit_transaction
  else
    begin
      Message.create!(body: message)
    rescue
      manager.rollback_transaction
    end
  end
end