Как объявить ресурс рельсов с параметром для нового действия?

У меня есть модель с именем Entree, для которой для действия new требуется параметр, идентификатор другой модели с именем Cave. Я не хочу встраивать Entree в пещеру, так как Cave уже вложен.
Я сделал объявление ресурса Entree, как показано ниже в routes.rb:

resources :entrees, :except => [:new]
match "/entrees/new/:id", :to => "Entrees#new", :as => 'new_entree'

Это работает, но проблема в том, что при ошибке в действии create я хочу снова отобразить страницу с недопустимым вводом. Но поскольку нет действия new, я должен сделать redirect_to new_entree_path, который не позволяет вводить пользователя.

Я пробовал следующий (самый простой) маршрут:

resources :entrees

Но тогда путь http://localhost:3000/entrees/new/32 возвращает ошибку:

No route matches [GET] "/entrees/new/32"

Вопрос в том, как я могу объявить ресурс Entree в файле маршрутов с параметром для действия new?

Ответ 1

Я не уверен, что это взломать или нет, но следующее работает и кажется более чистым, чем вложение 2-уровня.

resources :entrees, :except => [:new] do
  collection do
    get 'new/:id', :to => "entrees#new", :as => 'new'
  end
end

Теперь я могу сделать render "new" вместо redirect_to. Должен сказать, что я, должно быть, неправильно задал свой вопрос, плохой.

Ответ 2

Rails имеет помощник маршрута под названием path_names, который делает это:

resources :entrees, path_names: { new: 'new/:id' }

Ответ 3

Чтобы улучшить решение gwik (что на самом деле не помогло мне):

resources :things, except: [:new] do
  new do
    get ':param', to: 'things#new', as: ''
  end
end

Он получает вас new_thing_ * помощников (вместо new_things_ *) бесплатно.

Ответ 4

Если вы хотите использовать маршруты Rail s, вам придется вложить их в соответствии с тем, как они работают

resources :caves do
  resources :entrees
end

чтобы получить маршрут /caves/70/entrees/new

В противном случае вы находитесь в мире создания маршрутов ручного сопоставления.

match "/entrees/new/:id", :to => "entrees#new", :as => 'new_entrees'

Я не понимаю, почему вы вынуждены использовать перенаправление? Маршрут new_entrees действителен. Вы не сможете использовать form_for helper, так как это не ресурс, но help_tag helper будет работать.

ОБНОВЛЕНИЕ: рендеринг и маршрут

Маршрут напрямую не изменяет вид rendered в контроллере. Это определяется самим контроллером. Примеры визуализации:

  • render: new отобразит новое представление действий
  • render 'entrees/new' отобразит представление/новый шаблон

Ответ 5

Я обнаружил, что это создает правильный метод new_thing_path, а не new_things_path как решение Antoine.

resources :things, :except => [:new] do
  with_scope_level(:new) do
    get 'new/:param', :to => "things#new", :as => ''
  end
end