I wanted to define custom routes to certain resources in addition to those that Rails defines by default. To do this, the relevant parts of my routes.rb look something like this:
resource :top, only: [:show] scope module: :top do resource :reso, only: [:show] end get 'foo_reso' => 'top/reso#foo' get 'bar_reso' => 'top/reso#bar'
As you can see, I only need the ResoController routes of the show , foo and bar methods. This works because rake routes gives:
reso GET /reso(.:format) top/reso
This works: clicking on the link in the application, which will lead you to the foo_reso route, will cause ResoController#foo to be ResoController#foo and then display the corresponding view.
However, I thought the route definition was just a little ugly, and instead of defining route exploits I wanted Rails to automatically generate them, telling it that the resource has two additional REST methods, foo and bar (while limiting the standard methods using only: argument.
I went for advice in this answer and changed routes.rb to this:
resource :top, only: [:show] scope module: :top do resource :reso, only: [:show] do member do get :foo get :bar end end end
Now rake routes gives:
reso GET /reso(.:format) top/reso
Note the difference between the paths in two cases: while the auxiliary path and the action of the # controller are the same, the path has changed from /foo_reso(.:format) to /reso/foo(.:format) .
(I have all the resource names that are defined as unsountable in config/initializers/inflections.rb , so I do not get automatic name pluralization, because in my application each controller is associated with a specific screen and not with a model, so pluralization does not fit for the image. In this application, REST methods are really more like function calls than resource operations, so I need a different set than the standard.)
Now, by clicking the link to foo_reso in the application, you will get a page with a Rails routing error, which reads:
No route matches [GET] "/foo_reso"
Any ideas on what I could do to rectify the situation other than using my original solution?
Added to edit, 2013-07-12:
As I noted in the comment below, according to the result of rake routes , the helper route foo_reso corresponds to the controller and the method I want to call top/reso#foo , and when I manually enter the corresponding URL ( reso/foo ) in the line URLs that work as intended. However, attempting to open the foo_reso route from the application will result in No route matches [GET] "/foo_reso" . foo_reso_path and foo_reso_url lead to the same error.
What could be the problem? Surely not a mistake in Rails?
Added to edit, 2013-07-22:
To make the use case more understandable, the idea is that when the user clicks the "Reset" button on the page, the reset controller method is called, which clears the inputs and outputs of the page. I abstracted the question by changing the actual reset identifier to foo . ( reso and a few other identifiers are also the result of "obfuscation.") I will continue to use the same translations for consistency, but the code below should be clearer if you remember that foo is actually reset . ( bar is something else, but it doesn't matter since the routing problem is the same.)
To answer the questions of Tong Kua and John Hinnegan, I use foo_reso_path . Relevant parts of reso_controller file:
class Top::ResoController < Top::ResoSuperController
Relevant parts of the file app/views/top/reso/show.html.erb :
<%= render partial: "top/resosuper_inputs", locals: { the_form_path: reso_path } %> ... <input type="hidden" id="reset_path" name="reset_path" value="<%= @reset_path %>">
The form includes a partial _resosuper_inputs.html.erb , the relevant parts of which are:
<%= javascript_include_tag "my_reset_form.js" %> <%= simple_form_for :filtering_criteria, url: the_form_path, method: :get do |f| %> ... inputs elided ... <%= f.button :submit, value: "Search" %> <%= f.button :submit, type: 'button', value: "Reset"), id: 'reset_button' %> <% end %>
resosuper is a superclass of two different resources, but I don't think this affects the case. Anyway, here's the Javascript file app/assets/javascripts/my_reset_form.js :
$(document).ready(function() { $('#reset_button').click(function () { var reset_path = $('#reset_path').val(); window.open(reset_path, "_self") }); })
In jQuery and, as the comment says, the "Reset" button opens a path whose value was stored in a hidden input variable with id reset_path . This value is what was given to the Top::ResoController in the @reset_path variable, namely "foo_reso" .
Keep in mind that all this worked fine when I defined foo_reso in routes.rb as follows:
get 'foo_reso' => 'top/reso#foo'
Also keep in mind that replacing foo_reso with foo_reso_path or foo_reso_url in the assignment operator in ResoController does not matter.
The places where I use foo_reso are in the controller and in the view, so this should not be a problem.