transactions with two models

Hi,

In Agile Web Development with Rails section on Transactions (p 381)
there are two main examples.

1) making changes in two records in the same database table
2) making changes in two records each in a different *database*

I want to do what is in between: changes in two records each in a
different table of the same database. Suppose they are apples and
oranges tables.

How do I write this?

Do I need to be as elaborate as this and will it work?

apple = Apple.find(:first)
orange = Orange.find(:first)

Apple.transaction(apple) do
Orange.transaction(orange) do
   apple.update_attributes(params[:apple])
   orange.update_attributes(params[:orange])
end
end

Or can I just write something much simpler like this?

Apple.transaction(apple, orange) do
apple.update_attributes(params[:apple])
orange.update_attributes(params[:orange])
end

Will the above be a problem since orange is not an Apple?

In the rails docs there is something even simpler

transaction do
apple.update_attributes(params[:apple])
orange.update_attributes(params[:orange])
end

but I think this version won't restore the apple and orange instances
back to their previous state if the transaction fails.

What I don't understand is the class name that precedes
".transaction". Does that class name make a transaction for just that
table or with the entire *database* associated with that table?

Any help greatly appreciated.

Thanks,
Peter

Do I need to be as elaborate as this and will it work?

apple = Apple.find(:first)
orange = Orange.find(:first)

Apple.transaction(apple) do
Orange.transaction(orange) do
   apple.update_attributes(params[:apple])
   orange.update_attributes(params[:orange])
end
end

Or can I just write something much simpler like this?

Apple.transaction(apple, orange) do
apple.update_attributes(params[:apple])
orange.update_attributes(params[:orange])
end

Both versions are equivalent as ActiveRecord doesn't do nested
transactions. Transaction blocks only open a transaction if one is not
already open.

Will the above be a problem since orange is not an Apple?

In the rails docs there is something even simpler

transaction do
apple.update_attributes(params[:apple])
orange.update_attributes(params[:orange])
end

but I think this version won't restore the apple and orange instances
back to their previous state if the transaction fails.

True, but object-level transactions are deprecated and will disappear
some time in the future. From this, I take it, that they haven't been
widely used. See the API docs for more info.

What I don't understand is the class name that precedes
".transaction". Does that class name make a transaction for just that
table or with the entire *database* associated with that table?

The class has no more significance than that it is used to access the
database connection. Commonly all classes share a connection to the
same database, thus it doesn't really matter which class you use here.
You could even write ActiveRecord::Base.transaction { ... }.

In cases where your model classes *are* connected to different
databases, you are out of luck regarding transactions, anyway, as
ActiveRecord doesn't ensure transactional consistency among multiple
databases; there is no support for 2-Phase-Commit.

Michael