How can I elegantly construct a form for a model that has a polymorphic association?

主宰稳场 提交于 2019-12-04 10:38:24

If you don't wish to use STI, you can do something similar: create a new model Topic(name:string) which will polymorphically reference Subject or Category.

class Lesson < ActiveRecord::Base
  belongs_to :topic
  validates_presence_of :topic_id  
end

class Topic < ActiveRecord::Base
  belongs_to :topicable, :polymorphic => true
end

class Subject < ActiveRecord::Base
   has_one :topic, :as => :topicable
   has_many :lessons, :through => :topic
   accepts_nested_attributes_for :topic
end

class Category < ActiveRecord::Base  
   has_one :topic, :as => :topicable
   has_many :lessons, :through => :topic
   accepts_nested_attributes_for :topic
end

In the view where you create a new Subject/Category:

<%= form_for @subject do |subject_form| %>
  <%= subject_form.fields_for :topic do |topic_fields| %>
    <%= topic_fields.text_field :name %>
  <% end %>
<% end %>

After thinking this through, the less dirty implementation IMO would be to hire the JS shenanigans (b):

= f.input_field :topic_type, as: :hidden, class: 'topic_type'
- (@subjects + @categories).each do |topic|
  = f.radio_button :topic_id, topic.id, {:'data-type' => topic.class.name, class: 'topic_id'}

With a sprinkle of JS (your needs may vary):

$('input:radio.topic_id').change(function() {
  $('input:hidden.topic_type').val($(this).attr('data-type'));
});

Notes:

  • I use a radio button to select a topic (category or subject) in a list
  • The class name of each of possible topic is stored in an attribute 'data-type'
  • When a radio button is selected, the class name is copied to the hidden input via JS
  • Using: HTML5, jQuery, haml, simple_form
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!