Request parsing and params hash

If I submit a request that ends in:

?foo=bar&foo=baz

Then my assumption would be that params[:foo] would have an array in it:
[‘bar’, ‘baz’]. But it doesn’t. It only has the first value, ‘bar’, and
the ‘baz’ is apparently completely ignored.

Is there any way to fix this?

Jonathan

Jonathan R. wrote:

If I submit a request that ends in:

?foo=bar&foo=baz

Then my assumption would be that params[:foo] would have an array in it:
[‘bar’, ‘baz’]. But it doesn’t. It only has the first value, ‘bar’, and
the ‘baz’ is apparently completely ignored.

Is there any way to fix this?

Rails uses PHP’s array notation so you want your URL to be:

?foo[]=bar&foo[]=baz

In this case params[:foo] will be [‘bar’, ‘baz’]

Eric

Eric A. wrote:

Rails uses PHP’s array notation so you want your URL to be:

?foo[]=bar&foo[]=baz

In this case params[:foo] will be [‘bar’, ‘baz’]

Eric

Hmm, thanks. I ran into that with PHP, and I was hoping it would be
solved in Rails!

The problem is, that I don’t have complete control over the incoming
URLs. They are generated in some cases by external applications, and
even when generated by me, they need to conform with a certain standard
format, that does not allow the [] trick, and does require me to deal
with repeated parameter keys.

So, do I have any hope? Any easy way to override Rails request-parsing
stuff to make it behave how I like?

Jonathan R. wrote:

Hmm, thanks. I ran into that with PHP, and I was hoping it would be
solved in Rails!

I’m not sure it is a problem to be solved. Perl’s CGI library works like
you indicate and the problem with functionality like that is you never
know what you are getting back. Are you getting a scalar, array, hash,
what? So if the user checks only one checkbox you will get an scalar but
if they check two you have to deal with a hash. Then you code get’s ugly
with things like:

foo = [params[:foo]].flatten

Just to get a simple set of values from a checkbox. The PHP/Rails way is
better because the form is specifying “I am going to send you an array,
even if it is just one value”.

The PHP/Rails method also kicks butt because you can send complex data
structures. Want to update a user object and account object each with
their own (possibly overlapping attributes). Easy with the Rails/PHP
method:

User

Account

On the receiving side you can just do:

User.update_attributes = params[:user]
Account.update_attributes = params[:account]

and you are done.

The problem is, that I don’t have complete control over the incoming
URLs. They are generated in some cases by external applications, and
even when generated by me, they need to conform with a certain standard
format, that does not allow the [] trick, and does require me to deal
with repeated parameter keys.

If that is the case you could either do something like:

foo_1=bar&foo_2=baz

then in a before filter massage and param ending in to
create a array at param foo and delete all the foo

or you could override Rails.

So, do I have any hope? Any easy way to override Rails request-parsing
stuff to make it behave how I like?

Overriding the behavior is possible although it may violate the
principal of least surprise for other developers since Rails normally
allows complex data structures to be sent over the wire. But if you
really want it Ruby has open classes so override all you want.

Eric

Eric A. wrote:

I’m not sure it is a problem to be solved. Perl’s CGI library works like
you indicate and the problem with functionality like that is you never
know what you are getting back.

Ah, but the Rails parser already can sometimes give you complex data in
the “params” hash, can’t it? As you (and Agile Developemnt with Rails)
note, it’s already the case that a value in params can sometimes be a
string, and sometimes be a complex structure, depending on the nature of
the request:

form parameter params
user[name]=Dave { :user => { :name => “Dave” } }

How is this so different than what I’m wishing for?

You say you’re not sure it’s a problem to be solved. But, I’m in the
case where I need to deal with URLs of a format that is not of my own
devising, it is an external standard. And that external format says that
keys can be repeated. This is perfectly allowable by HTTP and URI/URL
specs (and in some cases is indeed the best way to make pretty REST
style URLs–I don’t like having details of my platform/implementation
embedded in my exposed URLs!).

So anyway, you might say the PHP/Rails way is better, and it’s not a
problem to be solved, but it’s a problem I’ve got to solve whether I
like it or not! Rails is kind of leaving me out in the cold.

Looking around more on google though, I find this:
http://dev.rubyonrails.org/ticket/5067

Interestingly, this guy was in the same situation, and received the same
response.

It’s not clear to me that it will have to change Rails checkbox code. I
mean, Rails is right now just throwing out subsequent values with the
same key. So I don’t think current checkbox code can rely on more than
one key with the same value? (Which is the only case in which params
would change).

But not understanding this fully, I am reluctant to try and over-ride
Rails behavior, since it might break fundamental Rails stuff. I still
feel like I’m at an impasse. Hmm. Maybe I have to parse the HTTP params
myself to get what I want? How ugly.

I have to say, I am really liking Rails and Ruby a lot. But I’m getting
rather frustrated with the typical Rails community response when someone
brings up something they need to do that Rails doesn’t do well: “Well,
don’t do that, it’s better to do this.” When, as in this case, the
thing to be done is in fact a perfectly reasonable thing, and is
additionally constrained by outside forces not under the control of the
developer.

Jonathan

Are you getting a scalar, array, hash,
what? So if the user checks only one checkbox you will get an scalar but
if they check two you have to deal with a hash. Then you code get’s ugly
with things like:

foo = [params[:foo]].flatten

Just to get a simple set of values from a checkbox. The PHP/Rails way is
better because the form is specifying “I am going to send you an array,
even if it is just one value”.

The PHP/Rails method also kicks butt because you can send complex data
structures. Want to update a user object and account object each with
their own (possibly overlapping attributes). Easy with the Rails/PHP
method:

User

Account

On the receiving side you can just do:

User.update_attributes = params[:user]
Account.update_attributes = params[:account]

and you are done.

The problem is, that I don’t have complete control over the incoming
URLs. They are generated in some cases by external applications, and
even when generated by me, they need to conform with a certain standard
format, that does not allow the [] trick, and does require me to deal
with repeated parameter keys.

If that is the case you could either do something like:

foo_1=bar&foo_2=baz

then in a before filter massage and param ending in to
create a array at param foo and delete all the foo

or you could override Rails.

So, do I have any hope? Any easy way to override Rails request-parsing
stuff to make it behave how I like?

Overriding the behavior is possible although it may violate the
principal of least surprise for other developers since Rails normally
allows complex data structures to be sent over the wire. But if you
really want it Ruby has open classes so override all you want.

Eric

But I’m getting
rather frustrated with the typical Rails community response when someone
brings up something they need to do that Rails doesn’t do well: “Well,
don’t do that, it’s better to do this.” When, as in this case, the
thing to be done is in fact a perfectly reasonable thing, and is
additionally constrained by outside forces not under the control of the
developer.

I take issue with this comment. The whole community is based on people
who
volunteer help in their free time. You are free to take the advice that
people give you and do what you will with it, but it’s not a good idea
to
blame Rails or the community because you have an edge case that the
framework was not designed to handle. It’s true that we tend to try to
steer new developers to a preferred method of doing things because you
can’t
always do things the way you did them in the language you came from.
Rails
is opinionated… it relies on you doing things its way and if you
choose to
ignore that, you’re kinda on your own.

But fear not… Rails is open-source. You can submit patches or create a
plugin to extend / modify how it works. The core team made that possible
and
really easy. So, the developer is indeed in full control of all of the
framework and is not constrained by the framework. It’s the old 80/20
rule,
or at least in a lot of cases, 95/5.

I understand your frustration, but I imagine that you will indeed need
to
parse the parameters yourself. No need to override how Rails
parameter
parsing works, just roll your own parser for that specific piece and
call it
instead of params.

I’m sorry you’re frustrated by the answers you’re receiving, but as you
learn more about Rails, you’ll discover why you get the answers you get.

Hope things work out for you! Have a great day.