Polymorphism 101. Part 2 of 3. Polymorphic Payments inside-out.
In the previous example we had a pre-defined current record and want to create a comment for it.
In this example we will:
- select a polymorphic model
- select a record to which we want to create a polymorphic child.
Example: Clients and Teachers can both create Payments.
To create a payment we:
- select a model for which we want to create a
payment(teacherorclient) - select a
teacherorclientrecord

console
rails g scaffold payments amount:integer payable:references{polymorphic} --no-helper --no-assets --no-controller-specs --no-view-specs --no-test-framework --no-jbuilder
payment.rb
belongs_to :payable, polymorphic: true
validates :amount, presence: true
def to_s
[payable_type, payable_id, amount].join(" ")
end
teacher.rb and client.rb
has_many :payments, as: :payable, dependent: :restrict_with_error
payments/index.html.erb
<%= link_to "Client Payment", new_payment_path(payable_type: "Client") %>
<%= link_to "Teacher Payment", new_payment_path(payable_type: "Teacher") %>
By pressing one of the above links we will be redirected to an url like /payments/new?payable_type=Client or /payments/new?payable_type=Teacher.
Based on ?payable_type=Teacher we give a collection of teachers to choose from:
payments/_form.html.erb
<%= simple_form_for(@payment) do |f| %>
<%= f.input :payable_type, input_html: {value: @payment.payable_type || params[:payable_type]}, as: :hidden %>
<% if @payment.payable_type.present? %>
<%= f.input :payable_id, collection: @payment.payable_type.classify.constantize.all %>
<% elsif params[:payable_type].present? %>
<%= f.input :payable_id, collection: params[:payable_type].classify.constantize.all %>
<% end %>
<%= f.input :amount %>
<%= f.button :submit %>
<% end %>
@payment.payable_type.classify.constantize.all gives us a collection of @clients or @teachers if we are EDITING a payment.
params[:payable_type].classify.constantize.all gives us a collection of @clients or @teachers if we are CREATING a payment.
This approach is good by not depending on any JS.
However it can be improved by being able to select the payable_type inside the form and than rendering the collection, rather than using params.
Did you like this article? Did it save you some time?
You might also like:
- RE-REVISED: Polymorphism 101. Part 5 of 3. Even better Polymorphic Comments
- REVISED: Polymorphism 101. Part 4 of 3. Polymorphic Comments
- Button to update status attribute of a table
- Polymorphism 101. Part 3 of 3. ActsAsTaggable without a gem. SelectizeJS
- Polymorphism 101. Part 1 of 3. Polymorphic Comments.