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 -~----------~----~----~----~------~----~------~--~---