Guide to understanding polymorphism in Rails
rails g
and appending name:references{polymorphic}
can be used to quickly establish the _type
and _id
polymorphic column names (all done by Rails).rails g model Person first_name last_name
rails g model Business name
rails g model Interaction description interactive:references{polymorphic}
# you can use any name for the polymorphic id and type, just as long as they make sense
rake db:migrate
class Person < ApplicationRecord
has_many :interactions, as: :interactive
end
class Business < ApplicationRecord
has_many :interactions, as: :interactive
end
# This should defaulted by rails
class Interaction < ApplicationRecord
belongs_to :interactive, polymorphic: true
end
rails c
and then entered Interaction.column_names
, you will see:
interaction_id
: holds the id of the model that the interaction belongs tointeraction_type
: holds the type of the model that the interaction belongs to# in terminal
rails g controller People index show new create edit update
rails g controller Businesses index show new create edit update
rails g controller Interactions new create edit update
class InteractionsController < ApplicationController
def new
@context = context
@interaction = @context.interactions.new
end
def create
@context = context
@interaction = @context.interactions.new(interaction_params)
if @interactions.save
redirect_to context_url(@context), notice: "The interaction has been successfully created."
end
end
def edit
@context = context
@interaction = @context.interactions.find(params[:id])
end
def update
@context = context
@interaction = @context.interactions.find(params[:id])
if @interaction.update_attributes(interaction_params)
redirect_to context_url(@context), notice: "The interaction has been successfully updated."
end
end
private
def interaction_params
params.require(:interaction).permit!
end
def context
if params[:person_id]
id = params[:person_id]
Person.find(params[:person_id])
else
id = params[:business_id]
Business.find(params[:business_id])
end
end
def context_url(context)
if Person === context
person_path(context)
else
business_path(context)
end
end
end
<%= form_for [obj1, obj2] do %>
#...
<% end %>
obj1
is the object returned from parsing the polymorphic association (ex. @context = context)obj2
is the object of the polymorphic class (ex. Interaction.new)rails console
:p = Person.first
p.interactions.build(description: "asdfgh asdf").save
p.interactions.first.interactive_type
# returns "Person"
p.interactions.first.interactive_id
# returns the corresponding id of the Person object
# Now that you have an interaction, you can call the method interactive on the Interaction object to retrieve
# it's parent:
i = Interaction.first
i.interactive # returns the corresponding parent object (Person in this case)