On Sep 26, 2007, at 5:27 PM, Frederick Cheung wrote:

>
> I think you are correct in assuming this is your problem. bits of
> create are wrapped in a transaction (eg so that the callbacks either
> run or don't etc...
> sqlite doesn't allow nested transaction, by using
> ActiveRecord::Base.connection.transaction (ie fiddling at the adapter
> level), you're starting the transaction, but not letting rails know
> about it.

then that method should not be exposed.  it should be private.  we  
always have

   execute 'BEGIN'

after all.  the fact that it's exposed and takes a block means it  
should work for us.


> If you use ActiveRecord::Base.transaction then rails counts
> the transactions opened (so when it's about to do a begin inside
> create it can see it's already in a transaction and thus omit the
> actual begin)
>
> The exception you get isn't your raise - it's the sqlite3 library
> complaining about nested transactions. I don't know sqlite3 much, but
> say in mysql then 'BEGIN' is one of those magic things that
> automatically commits the current transaction, which would explain
> what you see.

right.  the fact is that it's brain dead *easy* for rails to avoid  
this issue with all dbs at once.

>
> In postgres land the path which gets you there is different: the
> first begin executes, rails doesn't know about it.

but it should *unless* i did something sneaky 'like execute BEGIN'

> Then you get the
> second begin (from create), which (as per postgresql docs) is a no-op
> (but note the warning you get): you don't actually get the nested
> transaction. rails reaches the end of the transaction it was trying
> to handle in create, since it's not aware of anything else it sends
> commit back to the database:

yeah, but again, it *should* be aware of it since it's so easy to do.

> your raise causes no actual rollback
> (you can see rails tried from the warning about there being no
> transaction in progress) because it's too late: the creation of Foo
> has already committed.

yup.  the fact is that the multiple routes to get at transactions do  
not play well together.

>
> Anyway, what I was wondering is why not use
> ActiveRecord::Base.transaction ?

nested transactions are only *one* issue sane_transactions.rb  
addresses, the others are

- a throw/catch based mechanism for commit/rollback.  in the current  
rails there is no way, that i know of, of committing a transaction  
other than falling through to the end of the block.  this means all  
logic must be contained in a single block, rather than split out into  
methods, to commit early if logic dictates.  you cannot raise because  
this rolls back the exception.

- the current mechanism is using raise/exceptions to rollback doesn't  
seem to be good form: as using exceptions for control flow never is.   
a throw/catch mechanism allows the user to rollback a pending  
transaction without ALSO have to deal with catching the error and  
avoids all the risks of accidentally swallowing a real error (not one  
used for control flow)

- transactions and savepoints need to be integrated.   
sane_transactions.rb does this do in a way that connection adapters  
can utilize, ignore, or extend.

this, and the nested transacitons work across the board in a POLS way  
regardless of the entry point.  the main benefit i see, however, is  
that the implementation is also vastly simpler with far less state  
tracking - this is mostly due to the use of throw/catch.

anyhow, i hope it's food for thought.

kind regards.

a @ http://drawohara.com/
--
we can deny everything, except that we have the possibility of being  
better. simply reflect on that.
h.h. the 14th dalai lama




--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To post to this group, send email to rubyonrails-core@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-core?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to