Richard Sandilands <richard-RM3k1VUOk2kk+I/owrrOrA@public.gmane.org>
writes:
> My tag now looks like this:
>
radio_button_tag("for_participant_id[#{participant.id}][competency_id][#{competency.id}]",
> 3, checked=true)
>
> I''m really stuck writing an action to iterate through the @params
hash, but
> can''t seem to get it right. I know you''ve got better
things to do, but if you
> could give me the next piece of the puzzle it would be appreciated!
>
Instead of iterating through the @params hash, you should structure
your form so that you get back a hash with keys approximately equal to
your attributes on your object. Re-read that until it sinks in. As
an example. Let''s say I''m trying to update a Reservation
object.
Ideally, I want my @params hash to have a single key for
"reservation". If this is for an update action (as opposed to a
new/create action), then I''ll also need a key for the "id" to
update.
The value of this hash key should also be a hash of the attributes and
values for the reservation. For instance:
@params => { "reservation" => { "date" =>
"2005-10-31", "place" =>
"Salem, MA", "length" => "1" }, "id"
=> "10" }
In your action you would load the reservation to update and then call
update_attributes:
@reservation = Reservation.find(@params[:id]
if @reservation.update_attributes(@params[:reservation]
flash[:notice] = "Reservation updated"
else
render_action "edit"
end
The update_attributes method for AR is quite handy. Learn to milk
it. That is what will iteration across the hash for you. Basically,
in this example it will call:
@reservation.date = "2005-10-31"
@reservation.place = "Salem, MA"
@reservation.length = "1"
@reservation.save
If the save method fails, then @reservation.errors will be updated
with all the validations (or whatnot) that fail. Rendering the
"edit" action will hopefully display these errors, highlight the form
elements where the errors occurred, and preload the form elements
with the values previously entered.
Here''s the nifty part of update_attributes that lets this work.
There''s no real magic about iterating across the keys of the
@params[:reservation] hash. For each key, it only calls the object''s
setter if the object responds_to? a settor for that key name. So, to
do non-standard things all you need to do is create new setter methods
on your object.
> An example @params hash back from the form looks like this:
>
> {"participant_id"=>"43",
>
"for_participant_id"=>{"44"=>{"competency_id"=>{"7"=>"3",
"12"=>"3",
> "10"=>"3"}},
>
"45"=>{"competency_id"=>{"7"=>"3",
"12"=>"3", "10"=>"3"}},
>
"47"=>{"competency_id"=>{"7"=>"3",
"12"=>"3", "10"=>"3"}},
>
"43"=>{"competency_id"=>{"7"=>"3",
"12"=>"3", "10"=>"3"}}},
> "submit"=>"Submit",
"value"=>"1"}
>
> So all the data is there, I just can''t seem to get at it.
I''m wanting to
> update the Scores table with the values of the radio_button; (all the
3''s in
> the above example hash). I know I need to iterate through the hash and
create
> Score.new with the correct params but am stuck!
In your case, you might implement a competency_ids= method that accepts
a hash of ids and competency levels (or whatever). I don''t really
understand your data models or their associations. However, I''m
guessing you''d need something like:
class Participant
def competency_ids=(hash)
self.competencies.clear
hash.keys.each do |key|
competencies.push_with_attributes (Competency.find(key),
{ "level" => hash[key] })
end
end
end
This particular example isn''t necessarily complete or the best
approach. I''m just trying to show that arbitrary setter functions on
an AR model class can be defined to handle update_attributes from an
action.
There was a good thread on has and belongs to many associations and
check boxes a while back on the mailing list. You could search on my
name and checkbox to find it in the unofficial archives at gmane.org.
Also, there''s some notes about this on the wiki if you search for
checkbox too.
--
doug-jGAhs73c5XxeoWH0uzbU5w@public.gmane.org