Can you manage transaction commit/rollback manually?

I'd like to do something like this:

["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

In short, I have a stream of 'messages' and I'd like to transactionalise parts of that stream.

Whenever a "START" appears on the stream, a new transaction is begun. Whenever a "STOP" appears, the transaction is committed.

I'm struggling with the transactions.

I can see that I can do ActiveRecord::Base.transaction do ... end, but that won't work in this case unless I batch everything up, which isn't possible here because of the streams.

I saw that there's a transaction manager buried in ActiveRecord that I could potentially use (https://github.com/rails/rails/blob/0d76ab9c6f01e6390ba8878a296ff9d3ac6b9aa8/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb) but I haven't been able to get my tests passing against it.

I think part of the problem is also RSpec's transactional fixtures interfering, although disabling these didn't seem to solve the problem either.

Any help would be appreciated.

Thanks


I'd do this:

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

The first step is to use chunk to group the messages. The output of this is an array of pairs. If the first value of the pair is true, then the second value is the array of bodies, if not the bodies are just true false. With the data thus reorganised it is then trivial to use the existing transaction method.


you can manage transaction the following way

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

or in your case

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
链接地址: http://www.djcxy.com/p/66234.html

上一篇: 用GDI +填充部分圆角矩形

下一篇: 你可以手动管理事务提交/回滚吗?