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