Форма отправляет меня не на тот контроллер, несмотря на правильный 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 не имеет никакого смысла, так как у пользователя может быть только одно предсказание сезона на пул. Следовательно, с таким подходом я хотел достичь

  1. URL после сбоя действия должен быть максимально похож на оригинал /pool/:pool_id/match_predictions,
  2. Удалите:id в конце URL, который принадлежит @season_prediction.
  3. Используйте ту же форму для создания или обновления @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' в конце, чтобы отличить трассу контроллера от предсказаний совпадений. Это совсем не похоже на лучшую практику. При чтении кода это может сбить с толку других людей, но, по крайней мере, пользователь вряд ли заметит это изменение.

Другие вопросы по тегам