Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphic association in Simpleform

Is there a way to display polymorphic association in simple_form view?

So far I've got below:

= simple_form_for(@chat, :html => { :class => "form-horizontal" }, :wrapper => "horizontal", defaults: { :input_html => { class: "form-control"}, label_html: { class: "col-lg-4" } } ) do |f|
    = f.error_notification

    .form-inputs
        = f.association :from_user
        = f.association :to_user
        = f.input :message
        = f.association :chattable

    .form-actions
        = f.button :submit

And below model:

class Chat < ActiveRecord::Base
    belongs_to :from_user, :foreign_key => 'from_user_id', class_name: 'User'
    belongs_to :to_user, :foreign_key => 'to_user_id', class_name: 'User'
    belongs_to :chattable, polymorphic: true

    validates :from_user, associated: true, presence: true
    validates :message, presence: true
end

This throws out below error:

uninitialized constant Chat::Chattable
like image 318
Passionate Engineer Avatar asked Dec 18 '13 03:12

Passionate Engineer


People also ask

What is polymorphic association in Rails?

Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.

How is polymorphic association set up in Rails?

The basic structure of a polymorphic association (PA)sets up 2 columns in the comment table. (This is different from a typical one-to-many association, where we'd only need one column that references the id's of the model it belongs to). For a PA, the first column we need to create is for the selected model.


2 Answers

I found other solution that does not require JS manipulation and can still use simple form input. You can use input select with id and type separated by comma passed as option value.

= f.input :chattable, collection: @chat.chattables, selected: f.object.chattable.try(:signature),

Then in Chat model:

  def chattables
    PolymorphicModel.your_condition.map {|t| [t.name, t.signature] }
  end

  def chattable=(attribute)
    self.chattable_id, self.chattable_type = attribute.split(',')
  end

And in your PylymorphicModel

  def signature
    [id, type].join(",")
  end

Remember to add chattable to secured params if you use them.

like image 81
mingle Avatar answered Sep 20 '22 00:09

mingle


Through much hem, hawing, and back and forth, we've determined that SimpleForm does not do this.

Here's why! (Well, probably why)

SimpleForm needs to figure out what class the association is for. Since the default case is that the association name is the de-capitalized name of the class, it ends up looking for the class "Chattable", and doesn't find it, which is where your error comes from.

Good news is that all you need to do is replace the f.association :chattable line with something that does what you need. http://guides.rubyonrails.org/form_helpers.html#making-select-boxes-with-ease has the info you need to do this "easy way" - aka, with the Rails form helpers.

My suggestion is to have a selection box for chattable_type, and some JS that un-hides the HTML for the selection box of that type. So you'd get something like

= select_tag(:chattable_type, ["Booth", "Venue"])

= collection_for_select(:chattable_id, Booth.all)
= collection_for_select(:chattable_id, Venue.all)
...

not including the JS and CSS. Check the docs linked above for the actual syntax; I think mine's a bit off.

like image 37
Narfanator Avatar answered Sep 21 '22 00:09

Narfanator