Handling multiple fields with same name (params array)

37 views
Skip to first unread message

George Adamson

unread,
Dec 7, 2009, 9:07:49 AM12/7/09
to merb
After some investigation it seems that submitted fields names are not
parsed as expected.

If the post includes more than one field with the same name, only one
of them (the latter) will be present in the params hash when the form
is submitted.

For example the request.raw_post may contain:
trip[countries][id]=1&trip[countries][id]=2&trip[countries][id]=3

...but the params hash will only contain: "countries"=>{"id"=>"3"}
I would expect something like: "countries"=>[{"id"=>"1"}{"id"=>"2"}
{"id"=>"3"}]
(The Merb::Parse.query method seems to be responsible for this.)

Ideally merb would handle the update of trip.countries but at the very
least we should have an array of trip countries to loop through to
update the countries.

Is this a bug or have I misunderstood?
(The scenario is a bunch of checkboxes on a Trip page, allowing the
user to choose one or more countries. The Trip class "has
n, :trip_countries" and "has n, :countries, :through
=> :trip_countries")

Here are links to related threads:
- Merb thread:
http://groups.google.com/group/merb/browse_thread/thread/d1a192fbe2919497/ec18932cddb9f86d?lnk=gst&q=field+array#ec18932cddb9f86d
- Datamapper thread:
http://groups.google.com/group/datamapper/browse_thread/thread/3dd67743015fa46c/6c806cc72036a3df?lnk=gst&q=george+adamson#6c806cc72036a3df

George

Martin Gamsjaeger

unread,
Dec 7, 2009, 9:18:51 AM12/7/09
to me...@googlegroups.com
George,

I will try to reply to your previous post to the list later, and I
gotta admit I haven't got enough time now to think about your question
in this thread. However, I found

http://wonderfullyflawed.com/2009/02/17/rails-forms-microformat/

to be a very nice article that explains how params should be
constructed and sent, in case you want to work with nested model
assignment. It's definitely worth a read, imho.

cheers
snusnu
> --
>
> You received this message because you are subscribed to the Google Groups "merb" group.
> To post to this group, send email to me...@googlegroups.com.
> To unsubscribe from this group, send email to merb+uns...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/merb?hl=en.
>
>
>

George Adamson

unread,
Dec 7, 2009, 3:37:41 PM12/7/09
to merb
Thanks snusnu, that is indeed an excellent link.
Some very useful info there about arranging field name square-brackets
to receive the desired arrays and hashes etc.

I'm now ploughing on with my own controller-action code to handle an
array of checkboxes. As far as I can see, merb does not natively
handle multiple fields with the same name. Shame because I have a lot
of pages that include child fields.

Cheers,
George

On Dec 7, 2:18 pm, Martin Gamsjaeger <gamsnj...@gmail.com> wrote:
> George,
>
> I will try to reply to your previous post to the list later, and I
> gotta admit I haven't got enough time now to think about your question
> in this thread. However, I found
>
> http://wonderfullyflawed.com/2009/02/17/rails-forms-microformat/
>
> to be a very nice article that explains how params should be
> constructed and sent, in case you want to work with nested model
> assignment. It's definitely worth a read, imho.
>
> cheers
> snusnu
>
> On Mon, Dec 7, 2009 at 15:07, George Adamson
>
> <George.Adam...@softwareunity.com> wrote:
> > After some investigation it seems that submitted fields names are not
> > parsed as expected.
>
> > If the post includes more than one field with the same name, only one
> > of them (the latter) will be present in the params hash when the form
> > is submitted.
>
> > For example the request.raw_post may contain:
> > trip[countries][id]=1&trip[countries][id]=2&trip[countries][id]=3
>
> > ...but the params hash will only contain: "countries"=>{"id"=>"3"}
> > I would expect something like: "countries"=>[{"id"=>"1"}{"id"=>"2"}
> > {"id"=>"3"}]
> > (The Merb::Parse.query method seems to be responsible for this.)
>
> > Ideally merb would handle the update of trip.countries but at the very
> > least we should have an array of trip countries to loop through to
> > update the countries.
>
> > Is this a bug or have I misunderstood?
> > (The scenario is a bunch of checkboxes on a Trip page, allowing the
> > user to choose one or more countries. The Trip class "has
> > n, :trip_countries" and "has n, :countries, :through
> > => :trip_countries")
>
> > Here are links to related threads:
> > - Merb thread:
> >http://groups.google.com/group/merb/browse_thread/thread/d1a192fbe291...
> > - Datamapper thread:
> >http://groups.google.com/group/datamapper/browse_thread/thread/3dd677...

George Adamson

unread,
Dec 8, 2009, 7:58:30 AM12/8/09
to merb
@snusnu's plugin "accepts_nested_attributes" is probably the answer
but as a noobie I'm not having any luck getting it work.
(http://github.com/snusnu/dm-accepts_nested_attributes)

Here's the scenario again:

MODELS:

class Trip
...
has n, :trip_countries
has n, :countries, :through => :trip_countries
accepts_nested_attributes_for :countries
end

class Country
...
has n, :trip_countries
has n, :trips, :through => :trip_countries
accepts_nested_attributes_for :trips
end

class TripCountry
property :id, Serial
belongs_to :trip
belongs_to :country
end

In the trip VIEW form we have:
<% Country.all( :order=>[:name] ).each do |country| %>
<% checked = trip.countries.include?(country) ? 'checked' : nil %>
<%= check_box :name => "trip[countries][][id]",
:value => country.id, :checked => checked,
:boolean=>false, :label => country.name
%>
<% end %>


I'm formatting the checkbox field names as "trip[countries][][id]"
but I'm not sure whether they should be
"trip[countries][]" or "trip[countries][id][]" etc?!
(See http://wonderfullyflawed.com/2009/02/17/rails-forms-microformat )
Either way the checkbox selections will not save.

Any help greatly appreciated!
Many many thanks,
George

George Adamson

unread,
Dec 11, 2009, 8:03:47 AM12/11/09
to merb
Ok I've now solved this myself but I suspect there may be a better
way!
(My problems were simply due to my lack of understanding of merb and
the way arrays of fields should be handled)

It seems that while the accespt_nested_attributes plugin (http://
github.com/snusnu/dm-accepts_nested_attributes) can help with changing
the actual values of nested fields, it cannot help with adding and
removing them.

Hence when we have a bunch of checkboxes representing a has-n-through
association, our model needs to have a "relations_ids=" method.
(Better explanation here: http://asciicasts.com/episodes/17-habtm-checkboxes)

So, looking at the "trip has n countries" relationship described in my
earlier post, if we render several Country checkboxes like this:
<input type="checkbox" name="trip[countries_ids][]" value="587"/
><label>Algeria</label>

...then we must define a method in the Trip model to receive an array
of countries_ids, like this:

def countries_ids=(ids)
self.countries.reject!{|model| !ids.include?(model.id) }
self.countries.concat Country.all( :id => ids )
end

This handles all the creating and deleting of counties in the
trip_countries table.

(Notice also that the controller's update action will need to allow
for when all checkboxes have been un-ticked because the posted data
will not include an mention of the countries_ids array. Hence we add
the line "trip[:countries_ids] ||= []" before "if
@trip.update_attributes(trip)"

I wasted a lot of time on this so I hope this info helps someone.
Maybe an experienced rails/merber can suggest a better way, perhaps
one that does not require custom code on the model.

Cheers,
George

On Dec 8, 12:58 pm, George Adamson <George.Adam...@SoftwareUnity.com>
wrote:
Reply all
Reply to author
Forward
0 new messages