Yuv*_*rmi 3 ruby-on-rails rails-routing ruby-on-rails-3
我正在尝试编写一个通用路由,允许我通过控制器的操作来引用它.
我正在使用以下行:
match ':action' => 'pages#:action', :as => 'action'
Run Code Online (Sandbox Code Playgroud)
让我们说一下页面控制器中名为`foobar'的动作.我希望能够写作
link_to 'Click Me', pages_foobar_path
Run Code Online (Sandbox Code Playgroud)
在一个视图中.问题是Invalid route name: ':action'当我尝试编写该路由时出现错误.
请注意,行
match ':action' => 'pages#:action'
Run Code Online (Sandbox Code Playgroud)
没有:as参数完美的工作,但后来我必须手动编写路径,如下:
link_to 'Click Me', '/pages/foobar'
Run Code Online (Sandbox Code Playgroud)
任何方式?
如果动态意味着"在Rails启动时识别我的动作并动态生成路径":
这不是我会做的事情,但它可以做你想要它做的事情,没有任何重定向和method_missing运行时开销.
在 config/routes.rb
controller_filenames = Dir.new("#{Rails.root}/app/controllers").entries
controller_filenames.each do |filename|
# you could restrict to only the pages_controller.rb on the next line,
# and in that case, you could simplify even more (see next example)...
if filename =~ /_controller\.rb$/
controller_name = filename.sub(/.rb$/, "")
controller_route_name = controller_name.sub(/_controller$/, "")
controller = controller_name.camelize.constantize.new
controller.action_methods.each do |action|
# if you don't want the controller name in your path match, just omit it...
match "#{controller_route_name}/#{action}" => "#{controller_route_name}##{action}", :as => "#{controller_route_name}_#{action}"
end
end
end
Run Code Online (Sandbox Code Playgroud)
如果您只想为pages_controller.rb文件执行此操作,则:
controller_name = "pages_controller"
controller_route_name = "pages"
controller = controller_name.camelize.constantize.new
controller.action_methods.each do |action|
# I've removed the controller_route_name from the match here...
match "#{action}" => "#{controller_route_name}##{action}", :as => "#{controller_route_name}_#{action}"
end
Run Code Online (Sandbox Code Playgroud)
现在,如果动态意味着"每当我动态生成新动作时生成路径":
你真的可以玩火.您现有的任何操作都可以定义新的操作和路径.例如,我可以定义一条路线config/routes.rb(但这可能是任何现有的路线):
match '/dynamic_define' => 'application#dynamic_define'
Run Code Online (Sandbox Code Playgroud)
结合使用方法ApplicationController(再次,这可能是任何现有的操作):
def dynamic_define
method_name = params[:mname]
self.class.send(:define_method, method_name) {
render :text => "output from #{method_name}"
}
Rails.application.routes.disable_clear_and_finalize = true
Rails.application.routes.draw do
match "/#{method_name}" => "application##{method_name}", :as => "application_#{method_name}"
end
render :text => "dynamic_define just created a new action named #{method_name}"
end
Run Code Online (Sandbox Code Playgroud)
在您的浏览器中,您可以访问:
/dynamic_define?mname=my_new_dynamic_action
# browser renders "dynamic_define just created a new action named my_new_dynamic_action"
Run Code Online (Sandbox Code Playgroud)
然后访问:
/my_new_dynamic_action
# browser renders "output from my_new_dynamic_action"
Run Code Online (Sandbox Code Playgroud)