除了 Rails 默认定义的资源之外,还希望将自定义路由定义到某些资源中。为此,我的routes.rb
文件的相关部分如下所示:
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'
如您所见,我只想要到ResoController
的方法show
、foo
和的路由bar
。这有效,如下rake routes
所示:
reso GET /reso(.:format) top/reso#show
foo_reso GET /foo_reso(.:format) top/reso#foo
bar_reso GET /bar_reso(.:format) top/reso#bar
这有效:单击应用程序中的链接将您带到路线foo_reso
确实会导致调用ResoController#foo
,并随后显示相关视图。
然而,我认为路由定义有点难看,而不是明确定义路由,而是希望 Rails 通过告诉它资源有两个额外的 REST 方法来自动生成它们,foo
并且bar
(同时仍然通过only:
论据)。
我遵循了这个答案中的建议,并改为routes.rb
:
resource :top, only: [:show]
scope module: :top do
resource :reso, only: [:show] do
member do
get :foo
get :bar
end
end
end
现在,rake routes
给出:
reso GET /reso(.:format) top/reso#show
foo_reso GET /reso/foo(.:format) top/reso#foo
bar_reso GET /reso/bar(.:format) top/reso#bar
注意这两种情况下路径的区别:虽然 helper 路径和 controller#action 相同,但路径已从/foo_reso(.:format)
变为/reso/foo(.:format)
。
(我在 中将所有资源名称定义为不可数config/initializers/inflections.rb
,所以我没有得到名称的自动复数,因为在我的应用程序中,每个控制器都与特定屏幕相关联,而不是与模型相关联,因此复数不适合图片。在这个应用程序中,REST 方法实际上更像是函数调用,而不是对资源的操作,这就是为什么我需要一个不同于标准的集合。)
现在,单击foo_reso
应用程序中的链接会导致 Rails 路由错误页面显示:
No route matches [GET] "/foo_reso"
除了使用我原来的解决方案之外,我可以做些什么来解决这个问题?
添加于编辑,2013-07-12:
正如我在下面的评论中所指出的,根据 的输出rake routes
,辅助路由foo_reso
与我要调用的控制器和方法相匹配top/reso#foo
,并且当我在 URL 栏中手动输入匹配的 URL ( reso/foo
) 时,它按预期工作。但是,尝试foo_reso
从应用程序中打开路由会导致No route matches [GET] "/foo_reso"
. foo_reso_path
并foo_reso_url
导致相同的错误。
到底是什么问题?肯定不是 Rails 中的错误?
添加于编辑,2013-07-22:
为了使用例更清晰,想法是当用户按下页面上的“重置”按钮时,reset
会调用控制器的方法,该方法会清除页面的输入和输出。我一直在通过将实际标识符更改reset
为foo
. (reso
以及其他几个标识符也是“混淆”的结果。)为了保持一致性,我将继续使用相同的翻译,但是当您记住foo
实际上是reset
. (bar
是别的东西,但没关系,因为路由问题是一样的。)
为了回答 Thong Kuah 和 John Hinnegan 的问题,我就是这样使用foo_reso_path
. 文件的相关部分reso_controller
:
class Top::ResoController < Top::ResoSuperController
# GET /reso
def show
...
@reset_path = "foo_reso"
...
end # show
# GET /foo_reso
def foo
perform_foo_action
redirect_to reso_path
end
...
end
文件的相关部分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 %>">
表格包括 partial _resosuper_inputs.html.erb
,其相关部分是:
<!-- For using the "Reset" button. -->
<%= 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
是两种不同资源的超类,但我认为这对案例没有任何影响。无论如何,这是 Javascript 文件app/assets/javascripts/my_reset_form.js
:
$(document).ready(function() {
/* Hang functionality on the "Reset" button. */
$('#reset_button').click(function () {
var reset_path = $('#reset_path').val();
window.open(reset_path, "_self")
});
})
它在 jQuery 中,正如评论所说,使“重置”按钮打开其值已存储在 id 的隐藏输入变量中的路径reset_path
。Top::ResoController
该值是变量中赋予表单的值@reset_path
,即"foo_reso"
。
请记住,当我这样定义时,所有这些工作都foo_reso
很好routes.rb
:
get 'foo_reso' => 'top/reso#foo'
另请记住,在赋值语句中替换foo_reso
为foo_reso_path
或替换没有任何区别。foo_reso_url
ResoController
我使用的地方在foo_reso
控制器和视图中,所以这应该不是问题。