Rails form_for, использующий базовый класс STI

У меня есть довольно простая (я думаю) настройка наследования одной таблицы (STI) в моем приложении Rails.

Есть модель User с вложенным ресурсом Post. Используя STI, у меня есть так, что некоторые сообщения могут быть объектами Post::Urgent.

Я заметил, что мои помощники URL, такие как <%= [@user, @post] %>, должны быть жестко запрограммированы на <%= user_post_path[@user, @post] %>, иначе я в конечном итоге увижу ошибки о том, что Rails не находит метод user_post_urgent_path. Хорошо, это было достаточно легко.

(Альтернативный способ сделать это также <%= [@user, post: @post] %>.)

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

<%= form_for [@user, @post] do |f| %>

, я получаю такие же ошибки, как и в случае со вспомогательной функцией URL, но в контексте формы: undefined method 'user_post_urgen_path'.

Я исправил это, указав:

<%= form_for [@user, @post], url: :user_post do |f| %>

Но это не работает полностью, потому что, когда я иду отправлять форму, у меня возникают проблемы в моем контроллере, говоря, что строка сильных параметров params.require(:post) не удалась:

param is missing or the value is empty: post

Если я проверю params, то обнаружу, что форма передает объект post_urgent, а не объект post.

Я мог бы, конечно, вручную ввести некоторую логику, которая всегда говорит if !params[:post] and params[:post_urgent], then params[:post] = params[:post_urgent]. Но это кажется слишком слишком хакерским, особенно для Rails.

Есть ли лучший способ заставить подобную форму «просто работать» независимо от того, каким подклассом модели Post она фактически является?


person isthmuses    schedule 24.10.2015    source источник


Ответы (2)


Не уверен, что вы уже нашли решение, но я использую следующее для своих форм.

= form_for [@user, @post.becomes(Post)] do |f|
  - f.object = @post.becomes @post.class

ссылка: http://thepugautomatic.com/2012/08/rails-sti-and-form-for/

person AxelTheGerman    schedule 14.01.2016
comment
Это работает, но фу! Кажется, должен быть лучший способ, но спасибо! - person Kyle Heironimus; 01.03.2019

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

  def unpermitted_model_params
    polymorphic_form_params = params.to_unsafe_hash
        .slice('sub_model1', 'sub_model2')
    form_values = polymorphic_form_params.first.to_a.second
    ActionController::Parameters.new(parent_model: form_values)
  end

  def allowed_params
    unpermitted_model_params.require(:parent_model)
                            .permit(:type, :etc, :etc)
  end
person ecoologic    schedule 02.06.2020