Направляет именованные маршруты с использованием сложных имен параметров - PullRequest
2 голосов
/ 11 октября 2009

Мне нужно создать симпатичный маршрут для действия, которое ожидает уродливые имена вложенных параметров (это задано, а я не могу что-то изменить в это время).

Так что вместо

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

Опять же, я не могу изменить контроллер - он настроен на ожидание этих имен параметров на основе набора уже существующих форм поиска. Я просто хочу создать более читаемый маршрут для некоторых предопределенных поисков.

Конечно, должен быть способ создать маршрут, который передает входные данные в параметры с более сложными именами, чем single-word-downcase-alpha.

Ответы [ 2 ]

2 голосов
/ 11 октября 2009

Боюсь, что встроенные механизмы маршрутизации не будут делать то, что вы ищете. Вы, конечно, могли бы обезопасить механизм маршрутизации, но это кажется большой работой и может легко вызвать появление других ошибок.

Задумывались ли вы о предварительном фильтре в сочетании с более привлекательным маршрутом? Например:

# 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 прямо в инициализаторе.

2 голосов
/ 11 октября 2009

Из того, что я собрал из вашего поста, вы хотите URL, как

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

для получения хэша params типа

: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

Тогда мне нужно было бы каким-то образом обмануть контроллер, заставив его думать, что ему был передан более глубокий хэш params.

В программном_контроллере:

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, чтобы понять, как лучше всего это сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...