Форма отправляет меня не на тот контроллер, несмотря на правильный URL в приложении Rails
У меня определены следующие маршруты:
Приложение / Config/routes.rb
resources :pools do
resources :match_predictions, path: "predictions", as: "predictions", only:[:index, :create, :update]
post "predictions/season" => "season_predictions#create"
patch "predictions/season" => "season_predictions#update"
put "predictions/season" => "season_predictions#update
end
Что приводит к следующим действиям paths/Url/controller# (для простоты пропущены маршруты ресурсов пула):
pool_predictions GET /pools/:pool_id/predictions(.:format) match_predictions#index
POST /pools/:pool_id/predictions(.:format) match_predictions#create
pool_prediction PATCH /pools/:pool_id/predictions/:id(.:format) match_predictions#update
PUT /pools/:pool_id/predictions/:id(.:format) match_predictions#update
pool_predictions_season POST /pools/:pool_id/predictions/season(.:format) season_predictions#create
PATCH /pools/:pool_id/predictions/season(.:format) season_predictions#update
PUT /pools/:pool_id/predictions/season(.:format) season_predictions#update
Как контекст: у меня есть три модели Pool, MatchPrediction, SeasonPrediction. Каждый @pool - это спортивное соревнование, в котором участвуют has_many @match_predictions и has_one @season_prediction. Ключевым видом в моем приложении является то, где пользователь публикует / обновляет свои прогнозы. Поскольку большинство из них - @match_predictions, я использую match_predictions#index & match_predictions/index.html.erb для управления / отображения этого представления. Это представление доступно через:
/pool/:pool_id/predictions
Проблема: у меня есть форма для создания / обновления @season_prediction, которая находится в пределах ресурса match_predictions. Для того, чтобы сохранить сообщения об ошибках, в случае, если объекты не удалось сохранить, я рендеринг match_predictions/index.html.erb
после сбоя обновления / создания действий в season_predictions_controller. Это хорошо работает с маршрутами по умолчанию, скажем, если я делаю:
resources :pools do
resources :match_predictions, path: "predictions", as: "predictions", only:[:index, :create, :update]
resources :season_predictions
end
Это, однако, имеет непреднамеренное последствие изменения пути расположения к чему-то вроде:
/pool/:pool_id/season_predictions/:id
Я думаю, что это может сбить с толку пользователя, так как он все еще в том же виде, в то время как URL сильно изменился. Плюс:id в конце URL не имеет никакого смысла, так как у пользователя может быть только одно предсказание сезона на пул. Следовательно, с таким подходом я хотел достичь
- URL после сбоя действия должен быть максимально похож на оригинал
/pool/:pool_id/match_predictions
, - Удалите:id в конце URL, который принадлежит @season_prediction.
- Используйте ту же форму для создания или обновления @season_prediction в зависимости от того, обслуживаю ли я новый экземпляр или ранее сохраненный экземпляр из контроллера.
Пока у меня есть такая форма:
<%= simple_form_for([@pool, @season_prediction], url: pool_predictions_season_path) do |f| %>
<div class="form-inputs">
<%= f.input :champion %>
<%= f.input :second_place %>
<%= f.input :third_place %>
<%= f.input :last_place %>
<%= f.association :pool_participant %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Хотя отображаемая форма HTML устанавливает правильный путь действия: action="/pools/1/predictions/season"
после отправки он отправляет запрос на match_predictions#update, который я не получаю точно, потому что этот контроллер не задействован.
Не могли бы вы помочь мне понять, почему и достичь ожидаемого результата?
1 ответ
Таким образом, кажется, что при настройке маршрутов с косой чертой, например, между "предсказаниями" и "сезонами", используются следующие маршруты:
post "predictions/season" => "season_predictions#create"
patch "predictions/season" => "season_predictions#update"
put "predictions/season" => "season_predictions#update
Это мешало Rails таким образом, что контроллер season_prediction был проигнорирован, и контроллер match_predictions был достигнут с учетом настройки метода url as: "predictions"
которые целенаправленно совпадают.
resources :match_predictions, path: "predictions", as: "predictions", only:[:index, :create, :update]
В итоге я избавился от косой черты и установил маршруты season_prediction, как показано ниже:
put "predictionss" => "season_predictions#update"
Да, с двойным 's' в конце, чтобы отличить трассу контроллера от предсказаний совпадений. Это совсем не похоже на лучшую практику. При чтении кода это может сбить с толку других людей, но, по крайней мере, пользователь вряд ли заметит это изменение.