I finally got this to work with Rails 4.x. This is based off of Dmitry/ScotterC's answer, so +1 to them.
STEP 1. To begin, here is the full model with polymorphic association:
# app/models/polymorph.rb
class Polymorph < ActiveRecord::Base
belongs_to :associable, polymorphic: true
accepts_nested_attributes_for :associable
def build_associable(params)
self.associable = associable_type.constantize.new(params)
end
end
# For the sake of example:
# app/models/chicken.rb
class Chicken < ActiveRecord::Base
has_many: :polymorphs, as: :associable
end
Yes, that's nothing really new. However you might wonder, where does polymorph_type
come from and how is its value set? It's part of the underlying database record since polymorphic associations add <association_name>_id
and <association_name>_type
columns to the table. As it stands, when build_associable
executes, the _type
's value is nil
.
STEP 2. Pass in and Accept the Child Type
Have your form view send the child_type
along with the typical form data, and your controller must permit it in its strong parameters check.
# app/views/polymorph/_form.html.erb
<%= form_for(@polymorph) do |form| %>
# Pass in the child_type - This one has been turned into a chicken!
<%= form.hidden_field(:polymorph_type, value: 'Chicken' %>
...
# Form values for Chicken
<%= form.fields_for(:chicken) do |chicken_form| %>
<%= chicken_form.text_field(:hunger_level) %>
<%= chicken_form.text_field(:poop_level) %>
...etc...
<% end %>
<% end %>
# app/controllers/polymorph_controllers.erb
...
private
def polymorph_params
params.require(:polymorph).permit(:id, :polymorph_id, :polymorph_type)
end
Of course, your view(s) will need to handle the different types of models that are 'associable', but this demonstrates one.
Hope this helps someone out there. (Why do you need polymorphic chickens anyway?)