Win XP
Rails 2.0.2
object_transactions plugin
(http://code.bitsweat.net/svn/object_transactions/)
transaction-simple gem 1.4 (required by object_transactions plugin)
AR SQL Server Adapter 1.0
SQL Server 2000
Using the object_transactions plugin with Rails 2.0.2 (and I assume
based on what I'm seeing that this goes for Rails 2.x) disables the
ability to save to an ActiveRecord based session store (e.g. the
sessions table).
I haven't verified this in SQLite or MySQL, but am suspecting that the
behavior would be the same.
What appears to happen is that the AR::save call is not ever made under
this configuration (see the
CGI::Session::ActiveRecordStore::Session.update method in
action_controller/session/active_record_store.rb - the call to
ActiveRecord::Base.save is never made from here).
Not sure what's happening yet, but I am sure that if I remove the
object_transactions plugin from my app., that my AR-based sessions will
start saving again.
It appears that this method (lines 52-56 of object_transactions.rb):
# Wrap the original transation instance method with one that takes
# *objects args.
def transaction_with_object_transactions(*objects, &block)
self.class.transaction(*objects, &block)
end
is attempting to call the transaction_with_object_transactions method
and pass it a block. But the transaction_with_object_transactions
method didn't take a block as a parameter and so could not ultimately
pass that block to the "real" transaction method in ActiveRecord.
If you simply add the block into the parameter list for
transaction_with_object_transactions and then pass the block on to
transaction_without_object_transactions, then it seems to work fine.
What I don't understand is why an exception isn't thrown when the call
is made in the first place. I just tested it in irb, is the &block
parameter in a Ruby method call always optional?
Here's a patch - Austin Ziegler - if you're out there, am I right?
$ diff -u orig_object_transactions.rb object_transactions.rb
--- orig_object_transactions.rb 2008-02-28 14:24:47.010000000 -0600
+++ object_transactions.rb 2008-03-19 19:11:47.055985400 -0500
@@ -59,11 +59,11 @@
# Wrap the original transaction class method with one that
manages
# an object-level transaction in addition to the database
transaction.
# If an exception is caught, the object's state is rolled back.
- def transaction_with_object_transactions(*objects)
+ def transaction_with_object_transactions(*objects, &block)
objects.each { |o| o.extend Transaction::Simple }
objects.each &:start_transaction
I assert that the object_transactions plugin, in it's current state, not
only doesn't allow for sessions to be saved - it doesn't allow for
anything to be saved to the database, since the calls that were not
being made were basically the AR::Base save calls. This implies that no
data could be persisted to the database.
$ diff -u orig_object_transactions.rb object_transactions.rb
--- orig_object_transactions.rb 2008-02-28 14:24:47.010000000 -0600
+++ object_transactions.rb 2008-03-19 19:11:47.055985400 -0500
@@ -59,11 +59,11 @@
# Wrap the original transaction class method with one that
manages
# an object-level transaction in addition to the database
transaction.
# If an exception is caught, the object's state is rolled back.
- def transaction_with_object_transactions(*objects)
+ def transaction_with_object_transactions(*objects, &block)
objects.each { |o| o.extend Transaction::Simple }
objects.each &:start_transaction
It turns out that the block needs to be passed only if present - duh.
$ diff -u orig_object_transactions.rb object_transactions.rb
--- orig_object_transactions.rb 2008-02-28 14:24:47.010000000 -0600
+++ object_transactions.rb 2008-03-27 16:50:39.796592000 -0500
@@ -59,11 +59,11 @@
# Wrap the original transaction class method with one that
manages
# an object-level transaction in addition to the database
transaction.
# If an exception is caught, the object's state is rolled back.
- def transaction_with_object_transactions(*objects)
+ def transaction_with_object_transactions(*objects, &block)
objects.each { |o| o.extend Transaction::Simple }
objects.each &:start_transaction
Here is a copy of an email that I sent to Jeremy Kemper about this
plugin. At the end of the day, I cannot get my objects to save, so I
give up. I'm going to stop using object-level transactions, and remove
this plugin from my project.
Perhaps this email will help someone who runs into the same issue.