0

I am using Ruby 2.1.1 and Ruby on Rails 4.1.1.

Given...

... I access the URL

http://www.example.org/users/1/ciao/edit?hash[controller]=articles&hash[action]=index

... in the rendered edit view, within the form, I have:

<% hash[:hash].each do |key, value| %>
  <%= hidden_field_tag("hash[#{key}]", value) %>
<% end %>

... in my controller I have:

logger.debug "params        => #{params.inspect}" 
logger.debug "params[:hash] => #{params[:hash].inspect}" 

url_for(params[:hash].merge(:only_path => true))

When I submit the form then, by logging, I get:

params        => { "hash" => { "controller" => "articles", "action" => "index" }, "user_id" => "1", "controller" => "users/ciao", "action" => "update", "users_ciao" => { "language"=>"it" }, "_method" => "patch", "commit" => "Update", "utf8" => "✓"}
params[:hash] => { "controller" => "articles", "action" => "index" }

ActionController::UrlGenerationError (No route matches { :controller => "users/articles", :action => "show", :user_id => "1"}):

In url_for I passed params[:hash] that should be { "controller" => "articles", "action" => "show" }, right? Why I get :controller => "users/articles" and the added :user_id => "1"?! Is it a bug?

The strange behavior relates an automatic namespacing: when I inspect params[:hash] it is { "controller" => "articles", "action" => "index" } but when I pass it to the url_for method it becomes { :controller => "users/articles", :action => "show", :user_id => "1"}.


Note: The problem does not occur with not nested resources. That is, for instance, when the initial URL is as-like

http://www.example.org/users/1/edit?hash[controller]=articles&hash[action]=index

By looking at the ActionDispatch::Routing::UrlFor#url_for source code I see it runs reverse_merge!(url_options) when options is a Hash.

After some deeping I came up by using the following code (that seems to work as expected) in order to skip the reverse_merge!(url_options):

_routes.url_for(params[:hash].merge(:only_path => true).symbolize_keys)

instead of using:

url_for(params[:hash].merge(:only_path => true))

It happens even by using Ruby on Rails 4.2.0.

4

1 回答 1

0

url_for自动提示控制器的命名空间,除非它是绝对的,所以如果你不需要user命名空间,那么你可以写:

controller: '/articles'

于 2015-02-07T09:19:40.583 回答