angkiki
angkiki

Reputation: 495

Rails: Polymorphic Associations - Create Child In Form And Choose Parent

To illustrate my question, i'll use the following association as listed on ruby guides for polymorphic associations:

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true
end

class Employee < ApplicationRecord
  has_many :pictures, as: :imageable
end

class Product < ApplicationRecord
  has_many :pictures, as: :imageable
end

Now in our :pictures table, we will have 2 different columns, namely imageable_id and imageable_type.

The first thing that I am unclear of is, what exactly goes into imageable_type ? Is that something that the "rails magic" would automatically fill up when imageable_id is declared?

Moving on to my next point (which will probably indirectly answer my uncertainty above), how do I assign either a Product or Employee to my Picture.new form?

#create new picture form
#assume pre_created_array holds the :id for both Employee & Product
<%= form_for @picture do |f| %>
  #relevant fields ontop
  #choosing parent field is the one im unsure of      
  #this is what i assumed might be correct(?)
  <%= f.select :imageable_id, options_for_select(pre_created_array) %>
<% end %>

Now does this form actually work? Is the building of the association something that has to be handled in the controller action instead? I am actually not very sure because usually in a regular association the parent can be declared before .save, such as doing @post.employee = #find an employee. So are we suppose to read the :imageable_id?

#pictures controller

def create
  @picture = Picture.new(picture_params)
  #manipulate :imageable_id here???
  if @picture.save
    #blahblah other code
end

So i am actually quite unsure about this, whether it is supposed to be the form or controller handling the building of association. Which is why i'm bringing up this 2 "uncertainties".

Upvotes: 2

Views: 1028

Answers (1)

XML Slayer
XML Slayer

Reputation: 1561

A polymorphic association is cool because it allows a single table to belong_to multiple, as you know. So given a picture, we don't have to know whether it belongs to an employee or a product, we can just call picture.imageable and get the parent.

So if we don't have to know where the parent is, that must means Rails has to know. How does it know? imageable_type! imageable_type is the name of the class which it belongs to. In this case, either 'Employee' or 'Product'. That way, given the imageable_id, it knows what table in which to search.

image.imageable actually calls image.imageable_type.constantize.find(image.imageable_id)

Rails will do this "magic" for you if you simply assign objects instead of IDs. image.update(imageable: Product.first) will assign both for you.

So in your form, you should be able work with a collection of objects and let Rails do the rest for you.

Upvotes: 2

Related Questions