Rails 3. Nested Transactions. Child Block Exception

Why doesn’t ActiveRecord rollback change in nested transactions after an exception in a child block?

Here are some examples:

1.


>> Client.transaction do
?>   Client.create(:name => 'Pavel')
>>   Client.transaction do
?>     Client.create(:name => 'Elena')
>>     raise ActiveRecord::Rollback
>>   end
>> end
=> nil
>> Client.all.map(&:name)
=> ["Pavel", "Elena"] # instead of []

2.


>> Client.transaction do
?>   Client.create(:name => 'Pavel')
>>   Client.transaction(:requires_new => true) do
?>     Client.create(:name => 'Elena')
>>     raise ActiveRecord::Rollback
>>   end
>> end
=> nil
>> Client.all.map(&:name)
=> ["Pavel", "Elena"] # instead of ["Pavel"]

Thank.

Debian GNU / Linux 5.0.6;

Ruby 1.9.2;

Ruby on Rails 3.0.1;

SQLite 3.7.3.

+3
source share
2 answers

I have the same problem and I can accurately reproduce the result. If I activate ActiveRecord :: Rollback in an external block, then the whole transaction is rolled back, but otherwise nothing will be rolled back.

-, ActiveRecord , SQLite3, ActiveRecord , SQLite 3.6.8.

, ActiveRecord , ...

> List.connection.supports_savepoints?
=> false

Ubuntu 11.04 - Natty Narwhal;

ruby ​​1.8.7 (2010-04-19 patchlevel 253) [i486-linux], MBARI 0x8770, Ruby Enterprise Edition 2010.02;

Ruby on Rails 3.0.3;

sqlite3 gem 1.3.3

SQLite 3.7.2;

+3

rails ( ), . .

:

begin -- starts transaction 1
  begin -- start transaction 2

    insert into something (foo) values ('bar');

  commit -- ends transaction 1
rollback -- is ignored

commit rollback .

, . .

begin -- starts transaction 1
  savepoint foo -- starts "transaction" 2

    insert into something (foo) values ('bar');

  release -- commit for transaction 2
rollback -- roll back the data of the savepoint and everything else within transaction 1

, , .

: . sql

begin  -- transaction.do
  begin  -- Client.create
    insert into clients ( name ) values ('Pavel')  -- Client.create
  commit  -- Client.create, closes the out-most transaction
  begin -- transaction.do
    begin  -- Client.create
      insert into clients ( name ) values ('Elena')  -- Client.create
    commit  -- Client.create, closes the out-most transaction

, Exception .

, .

PS: -- sql. mysql..

0

Source: https://habr.com/ru/post/1774284/


All Articles