【问题标题】:Rails named routes using complex parameter namesRails 使用复杂的参数名称命名路由
【发布时间】:2010-12-05 15:55:02
【问题描述】:

我需要为一个期望丑陋的嵌套参数名称的动作创建一个漂亮的路线(这是设置的,我目前无法更改)。

所以不是

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=>...

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

肯定有一种方法可以创建一个路由,将输入数据传递给名称比单字大写字母更复杂的参数。

【问题讨论】:

    标签: ruby-on-rails parameters routes


    【解决方案1】:

    根据我收集到的你的帖子,你想要一个像

    这样的网址

    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
    

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

    在程序控制器中:

    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
    

    注意。我列出的 link_to 包装器是不完整的。我用它来做一个简单的演示。如果您打算将其他选项传递给它,甚至以其他方式使用它(即:link_to (@project),您将需要重写它。查看 link_to 源以了解最佳方式它。

    【讨论】:

    • 好吧,既然您指出了嵌套哈希示例,我想知道它是否可以使用嵌套路由来完成。否则,您在控制器中的示例看起来像是一个合理的选择。虽然理想情况下,我会找到一个类似的解决方案,可以完全在路由定义中处理,并且完全不受控制器的影响。像:map.programs 'programs/:type/:id', :remap=>{:type=>'programs[type]', :id=>'programs[leader_id]'} 幸运的是,我没有担心路由助手和包装器。这种特殊情况是让客户在其静态 html 中嵌入可读链接。
    • 我只建议包装器允许您使用通用 Rails 语法来动态生成链接。嵌套路由不起作用,因为它们仍然只会创建一个浅参数哈希。至于 :remap 选项。这是可能的,但您需要修改处理 routes.rb 的代码。 Rails 源代码可能很难破译。
    • 哇,时间过得真快……以上两个答案都非常有帮助。我最终在 ProgramsController 中创建了一个友好的路由workshops/search/:search_type/*criteria 加上一个 before_filter 来重新排列查询,然后再将其发送到 Program 模型。保存评论”并出现错误。
    【解决方案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 就在初始化程序中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-15
      • 1970-01-01
      • 1970-01-01
      • 2016-05-01
      相关资源
      最近更新 更多