Как удалить имена контроллеров из маршрутов рельсов?

Я хотел бы обрезать маршруты в своем приложении, чтобы:

http://myapplication.com/users/peter/info/how-do-i-create-urls

становится...

http://myapplication.com/peter/how-do-i-create-urls

У меня есть пользовательский контроллер и хотел бы, чтобы он был находчив. Пользователи также имеют вложенный ресурс, называемый вопросами.

Файл основных маршрутов

Без корректировки URL-адресов файл маршрутов выглядит так:

...
resources :users do
  resources :questions
end

Однако URL-адреса этого типа имеют вид

http://myapplication.com/users/peter/info/how-do-i-create-urls

а не

http://myapplication.com/peter/how-do-i-create-urls

Частичный успех Я попытался сделать следующее:

...
resources :users, :path => '' do
  resources :questions
end

Это работает и производит:

http://myapplication.com/peter/info/how-do-i-create-urls

Однако, если я попытаюсь:

...
resources :users, :path => '' do
  resources :questions, :path => ''
end

Тогда все начинает идти не так.

Это правильный подход, и если да, то можно ли это сделать и с вложенными ресурсами?

Ответ 1

То, как вы это делаете, должно работать. Я не знаю, какую проблему вы испытываете, но если вы скопировали код примера из вашего приложения напрямую, это может быть из-за дополнительного end, который вы положили на свои маршруты. Вероятно, это должно выглядеть так:

resource :users, :path => '' do
  resource :questions, :path => ''
end

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

resource :users, :path => '' do
  resource :questions, :path => ''
end

resources :posts

Если вы сделаете это таким образом, ни один запрос не будет перенаправлен на контроллер сообщений, так как запрос /posts/ 1 будет отправлен на контроллер вопросов с помощью: user_id = > 'posts',: id = > 1

Edit:

Кроме того, теперь я заметил, что вы используете ресурс вместо ресурсов. Не знаю, предназначено ли это или если это ошибка.

Ответ 2

Спасибо и @mark и @DanneManne за помощь. С их помощью и немного большим количеством настроек я получил все это. Это не совсем тривиально, но я не уверен, что вы могли бы сделать его намного короче:


Конечный рабочий код

# setup the basic resources while holding some back for creation below
resources :users, :except => [:show, :index, :new, :create], :path => '/' do
  resources :questions, :except => [:show]
end

# for clarity, pick out routes that would otherwise go 
# to root (such as new_user => '/new')
resources :users, :only => [:index, :new, :create]


# setup questions#show to give clean URLS
match ':user_id/:question_id', :as => :user_question, 
                               :via => :get,
                               :controller => :questions, 
                               :action => :show

# setup users#show method to give clean URLS
match ':user_id', :as => :user, 
                  :via => :get, 
                  :controller => :user, 
                  :action => :show

Выход Rake Routes

    user_questions GET    /:user_id/questions(.:format)          {:action=>"index", :controller=>"questions"}
                   POST   /:user_id/questions(.:format)          {:action=>"create", :controller=>"questions"}
 new_user_question GET    /:user_id/questions/new(.:format)      {:action=>"new", :controller=>"questions"}
edit_user_question GET    /:user_id/questions/:id/edit(.:format) {:action=>"edit", :controller=>"questions"}
     user_question PUT    /:user_id/questions/:id(.:format)      {:action=>"update", :controller=>"questions"}
                   DELETE /:user_id/questions/:id(.:format)      {:action=>"destroy", :controller=>"questions"}
         edit_user GET    /:id/edit(.:format)                    {:action=>"edit", :controller=>"users"}
              user PUT    /:id(.:format)                         {:action=>"update", :controller=>"users"}
                   DELETE /:id(.:format)                         {:action=>"destroy", :controller=>"users"}
             users GET    /users(.:format)                       {:action=>"index", :controller=>"users"}
                   POST   /users(.:format)                       {:action=>"create", :controller=>"users"}
          new_user GET    /users/new(.:format)                   {:action=>"new", :controller=>"users"}
     user_question GET    /:user_id/:question_id(.:format)       {:controller=>"questions", :action=>"show"}
              user GET    /:user_id(.:format)                    {:controller=>"user", :action=>"show"}

Ответ 3

Не уверен в вложенности, но попробуйте

:path => '/'

Ответ 4

Просто подумал, что добавлю еще одно возможное решение, если кто-то еще приедет из Google позднее.

После просмотра этой вложенной статьи ресурсов это может быть более чистое решение с почти такой же гибкостью в маршрутах:

resources :users, :path => ''
resources :users, :path => '', :only => [] do
  resources :questions, :path => '', :except => [:index]

В принципе, включив второй родительский блок, дочерние ресурсы не будут выдаваться перед родительскими ресурсами.

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