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
(teacher
orclient
) - select a
teacher
orclient
record
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.