dsw
2008-Oct-23 06:17 UTC
A has_many :bs; what is the Rails idiom to save @a and @.bs in one transaction ?
Suppose I have two models:
class A < ActiveRecord::Base
has_many :bs
end
class B < ActiveRecord::Base
belongs_to :a
end
Now, if I say in a controller
b1 = @a.build(params[:b])
I can build a new B associated to an A.
If the @ is also new, I need to also do this
b1.a = @a
but if the @a is not new, then its id is filled in for me.
(1) Why? Even though there is no @a.id to set the b1.a to, there is
an @a object that I can set b1.a to, and I do. Couldn''t build do this
for me so @a.build(...) would work in both cases?
Either way, if I now say
@a.save!
Then not only are the values of @a that may have been updated saved,
the new object b1 is also saved to the database. Not only that, this
all happens in the same transaction. Yea!
However, instead if I were to update an existing b as follows:
b1 = @a.bs[1].update(params[:b])
and then
@a.save!
then this time, the updated values of b1 are not saved to the
database.
(2) Why? Wouldn''t it be cleaner to update the associated b values
into the database as well during the save of the @a ?
Further, if I want the @a and the associated @a.bs to all be sent to
the database in the same transaction, as far as I can tell, I have the
following choices.
In my controller save the @a and @a.bs in one transaction:
ActiveRecord::Base.transaction do
@a.bs.each do |b|
b.save!
end
@a.save!
end
Or perhaps to be more elegant I could push all that into a method
save_it! on class A.
Or I can try to figure out how to get the @a.bs to save in the same
transaction as the @a. I suppose I can do that as follows:
class A < ActiveRecord::Base
before_save do |a|
bs.each do |b|
b.save!
end
end
end
This is a bit better, but -- amazingly -- I have somehow at times
gotten into an infinite loop doing this, though it was a bit more
complex than that. Even though the documentation says that if I save
on the belongs_to side, the object belonged-to will not be saved, I
had a case where saving the associated objects like this ended up
recursing on itself. Is this idiom supposed to work and was I
therefore getting an infinite loop because (a) I was not doing it
quite right, or (b) is this idiom not good.
(3) What is the right idiom for this situation, where I want to save
the @a and the associated bs in one transaction?
Daniel
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---