Hi all! I find association collections to be quite hard to understand and use. I have a Leg class that has_many :choices, and a Choice class that belongs_to :leg. In a controller I want to update both a Leg and its Choices. If I do it like this: @leg.choices.update params[:choice].keys, params[:choice].values It updates the database directly (or more specifically only updates records that validates). So if I want to make the update to the @leg and @leg.choices as an atomic action I guess that I will have to introduce a transaction. However, then all the changes will be lost for the user since the form will reflect the unchanged database, right? So then I tried to first make the updates to the choices and then save everything in a transaction, like this: @leg.attributes = params[:leg] choices = params[:choice] if choices choices.each do |key, value| @leg.choices.find(key).attributes = value end end if request.post? Leg.transaction do @leg.save! @leg.choices.each {|choice| choice.save! } end But it tuns out that I can''t make changes to individual records in the association collection, so the @leg.choices.find().attributes=() doesn''t change anything. So now I''m basically out of ideas. Does anyone got any pointers? Thanks in advance! /Jonas -- Posted via http://www.ruby-forum.com/.
Anyone? /Jonas jonas wrote:> I find association collections to be quite hard to understand and use.-- Posted via http://www.ruby-forum.com/.
First of all, when you do @leg.choices.find(key).attributes = value, you''re asking Rails to query the database for a new instance of that particular choice and set the attributes on that. You then discard this new instance without saving it. But I''m not really sure what you''re trying to do. As far as I can see, there''s no update method on a has_many relationship, so your first bit of code shouldn''t work. Can you give a concrete example of what your params might consist of, and how you expect the database to be changed as result? Cheers, Pete Yandell On 17/11/2005, at 10:10 AM, Jonas Bengtsson wrote:> Hi all! > > I find association collections to be quite hard to understand and use. > > I have a Leg class that has_many :choices, and a Choice class that > belongs_to :leg. In a controller I want to update both a Leg and its > Choices. If I do it like this: > > @leg.choices.update params[:choice].keys, params[:choice].values > > It updates the database directly (or more specifically only updates > records that validates). So if I want to make the update to the > @leg and > @leg.choices as an atomic action I guess that I will have to > introduce a > transaction. However, then all the changes will be lost for the user > since the form will reflect the unchanged database, right? > > So then I tried to first make the updates to the choices and then save > everything in a transaction, like this: > > @leg.attributes = params[:leg] > choices = params[:choice] > if choices > choices.each do |key, value| > @leg.choices.find(key).attributes = value > end > end > if request.post? > Leg.transaction do > @leg.save! > @leg.choices.each {|choice| choice.save! } > end > > But it tuns out that I can''t make changes to individual records in the > association collection, so the @leg.choices.find().attributes=() > doesn''t > change anything. > > So now I''m basically out of ideas. Does anyone got any pointers? > > Thanks in advance! > /Jonas > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Thanks for taking the time to respond Pete! Yes, I thought that @leg.choices.find would not fetch new records from the database but find one of records that are already fetched from the database. @leg.choices.update did work, but not the way I wanted and I can''t find the documentation for it. To rehash/clarify the problem: I have Leg that has_many :choices, and Choice that belongs_to :leg. For this example Tag has :this as an attribute, and Choice got :that. Before the action the database looks like this: legs [id=1, this="Hello"] choices [id=1, leg_id=1, that="World"] [id=2, leg_id=1, that="Europe"] The parameters look like this: { "leg"=> {"this"=>"Hi"}, "choice"=> { "1"=>{"that"=>"y''all"}, "2"=>{"that"=>"everyone"} } } After the action I want the database to look like this: legs [id=1, this="Hi"] choices [id=1, leg_id=1, that="y''all"] [id=2, leg_id=1, that="everyone"] I seem to have found a way that works now, however I must be missing something since it requires way too many lines of code :-) If I change the association collection to a regular Array, it behaves the way I thought it would originally. I then update the choices with the values from the parameters. And lastly I save everything. @leg.attributes = params[:leg] if params[:choice] choices = @leg.choices.to_a params[:choice].each do |key, value| choice = choices.find {|c| c.id.to_s == key} choice.attributes = value if choice end end if request.post? Leg.transaction do err = !@leg.save @leg.choices.each {|choice| err ||= !choice.save } raise if err end end This seems to work, but is there an easier way? /Jonas pete wrote:> First of all, when you do @leg.choices.find(key).attributes = value, > you''re asking Rails to query the database for a new instance of that > particular choice and set the attributes on that. You then discard > this new instance without saving it. > > But I''m not really sure what you''re trying to do. As far as I can > see, there''s no update method on a has_many relationship, so your > first bit of code shouldn''t work. Can you give a concrete example of > what your params might consist of, and how you expect the database to > be changed as result? > > Cheers, > > Pete Yandell-- Posted via http://www.ruby-forum.com/.
Reasonably Related Threads
- "Cannot convert String to Integer" after using association
- Rails bug? Conditions on associations ignored by eager loading
- how to use activemodel collection.build for a has_many :through association
- Deleting join association of has_many :through
- Altering the accessor of an association collection