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