url_for and arrays parameters (diffs between rails 1.1.6 and 1.2.2)

Hello,

I posted this to the main rails list (Url_for and arrays parameters (diff between 1.1.6 and 1.2.2) - Rails - Ruby-Forum), but haven't received any replies yet, so maybe this question is better suited here. Sorry if this has been brought up before, I couldn't find any previous discussion on this.

To summarize the post...

When using the latest Rails (1.2.2)

I'm passing an array to url_for like so... url_for :controller => 'test', :action => 'list', :fields => %w(a b c d)

and that generates... "/test/list?fields=a%2Fb%2Fc%2Fd"

params[:fields] in the action contains "a/b/c/d"

When using Rails 1.1.6, the same url_for call generates... "/test/list?fields=a&fields=b&fields=c&fields=d"

With this, params[:fields] contains an array like I expected.

What's the reason for the difference between the two?

Thanks, Andrew

I posted this to the main rails list (http://www.ruby-forum.com/topic/99845), but haven’t received any replies yet, so maybe this question is better suited here. Sorry if

this has been brought up before, I couldn’t find any previous discussion on this.

To summarize the post…

When using the latest Rails (1.2.2)

I’m passing an array to url_for like so…

url_for :controller => ‘test’, :action => ‘list’, :fields => %w(a b c d)

and that generates… “/test/list?fields=a%2Fb%2Fc%2Fd”

CGI.escape %w(a b c d).to_param

params[:fields] in the action contains “a/b/c/d”

When using Rails 1.1.6, the same url_for call generates… “/test/list?fields=a&fields=b&fields=c&fields=d”

Array#to_param didn’t exist in 1.1.6. Perhaps it should be removed.

jeremy

Ok, I didn't notice the to_params method on Array.

So are the results in 1.2.2 the correct results and I should be manually doing a split('/') on the string now? Getting an array in the params object automatically (as in 1.1.6) seems like the preferred way of doing things.

This seems like a pretty major change on how the parameters are handled. I can't seem to find anything on this in the CHANGELOG's either.

What's the rational behind this change? If any.

Thanks, Andrew

Andrew Kaspick wrote:

Hello,

I posted this to the main rails list (Url_for and arrays parameters (diff between 1.1.6 and 1.2.2) - Rails - Ruby-Forum), but haven't received any replies yet, so maybe this question is better suited here. Sorry if this has been brought up before, I couldn't find any previous discussion on this.

To summarize the post...

When using the latest Rails (1.2.2)

I'm passing an array to url_for like so... url_for :controller => 'test', :action => 'list', :fields => %w(a b c d)

and that generates... "/test/list?fields=a%2Fb%2Fc%2Fd"

params[:fields] in the action contains "a/b/c/d"

When using Rails 1.1.6, the same url_for call generates... "/test/list?fields=a&fields=b&fields=c&fields=d"

With this, params[:fields] contains an array like I expected.

What's the reason for the difference between the two?

Thanks, Andrew

>

There are a couple tickets relating to this. There is a patch, but it hasn't been applied yet.

http://dev.rubyonrails.org/ticket/7462 http://dev.rubyonrails.org/ticket/7047

Jack

Great, thanks for the links. Hopefully somebody from core can look at these soon and apply a fix. In the mean time, I'll look into some of the proposed "fixes" to get around this for the time being.

Andrew

Jeremy and bgipsy are on the right track with #7047 and #7462. Nicholas introduced a #to_query method in http://dev.rubyonrails.org/changeset/6038 that we should reuse and extend if needed. Anyone who’d like to merge the best of these patches, please do investigate and attach to #7047.

Essentially, we need to preserve ‘/*foo’ multi-segment routing with an array parameter as well as correctly handling array query parameters.

In other words, routes = ActionController::Routing:: RouteSet.new routes.draw { |map| map.connect ‘/*foo’, :controller => ‘dummy’ } assert_equal ‘/a/b/c?bar%5B%5D=1&bar%5B%5D=2&bar%5B%5D=3’, routes.generate(:foo => %w(a b c), :bar => %w(1 2 3), :controller => ‘dummy’)

Requiring everyone to :foo => %w(a b c).join('/) is a backward-incompatible answer, unfortunately.

Best, jeremy