Rails使用复杂的参数名称命名路由

时间:2009-10-10 20:45:24

标签: ruby-on-rails parameters routes

我需要为一个期望丑陋的嵌套参数名称的动作创建一个漂亮的路径(这是设置的,而不是我此时可以改变的东西)。

所以而不是

http://domain.com/programs/search?program[type]=leader&program[leader_id]=12345

我想要

http://domain.com/programs/search/leader/12345

问题是Rails路由定义不会处理复杂的参数名称。

map.programs 'programs/:program[type]/:program[leader_id]', :controller=>..., :action=>...

同样,我无法更改控制器 - 它设置为基于一组预先存在的搜索表单来预期这些参数名称。我只是想为一些预先定义的搜索创建一个更易读的路径。

当然,必须有一种方法可以创建一条路径,将输入数据传递给名称比单字下调-α更复杂的参数。

2 个答案:

答案 0 :(得分:2)

从我收集的帖子中,你想要一个像

这样的网址

http://domain.com/programs/search/leader/12345

生成像

这样的参数哈希
:params => { programs => {:type => "search", :leader_id => "12345"}}

我不认为这可以做到。据我所知,无法从named_route生成嵌套哈希。有解决方法,但每个都需要以某种方式修改控制器。

我觉得这是最不具侵入性的解决方案: 首先设置一个更简单的命名路径,

map.programs 'programs/:program_type/:program_leader_id',
  :controller=>..., :action=>...

然后我想让link_to或url_for包装器作为帮助器使用,这样就可以传递一个程序对象并生成正确的url。

def link_to_programs name, prog
  link_to name, programs_url(prog, 
     :programs =>{:program_type => prog[:type], :prog[:program_leader_id]})
end

然后我需要一些方法来欺骗控制器,让它认为它传递了更深层次的参数哈希。

在programs_controller中:

def fix_bad_params
  params.merge!({:programs => {:type => params[:program_type],
    :leader_id => params[:program_leader_id])
end

before_filter :fix_bad_params, :only => :action_in_named_route

<强> NB。我列出的link_to包装器不完整。我用它进行简单的演示。如果您计划将其他选项传递给它,或者甚至以其余的方式使用它(例如:link_to(@project),则需要重写它。查看link_to源以了解最佳方法它

答案 1 :(得分:2)

我担心,内置的路由机制无法满足您的需求。你肯定可能猴子修补路由机制,但这似乎很多工作,很容易导致其他错误出现。

您是否考虑过将前置过滤器与更漂亮的路线结合使用?例如:

# in config/routes.rb:
map.connect '/programs/:program_type/leader/:program_leader_id', ...

# in config/initializers/translate_pretty_program_routes.rb
module TranslatePrettyProgramRoutes
  def self.included(base)
    base.send :include, TranslatePrettyProgramRoutes::InstanceMethods
    base.send :prepend_before_filter, :translate_pretty_program_route_params
  end

  module InstanceMethods
    def translate_pretty_program_route_params
      params[:program] ||= {}
      params[:program][:type] ||= params[:program_type]
      params[:program][:leader_id] ||= params[:program_leader_id]
    end
  end
end

# in app/controllers/programs_controller.rb:
class ProgramsController < ApplicationController
  include TranslatePrettyProgramRoutes
end

TranslatePrettyProgramRoutes中的元编程是为了解决开发模式中的类重载问题。如果它不是用于类重新加载,您可以只定义方法并将其添加为初始化程序中的before_filter