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.