Reputation: 71
I have been trying to wrap my mind on a polymorphic structure for my app for a while now, but I can't get it, and I don't know how to solve it.
I have a Supplier model, and a supplier's profile can by a Company OR a Person as listed below.
Supplier Model
class Supplier < ActiveRecord::Base
belongs_to :profile, :polymorphic => true
accepts_nested_attributes_for :personable, :allow_destroy => true, :reject_if => :all_blank
end
Company Model
class Company < ActiveRecord::Base
has_one :supplier, as: :profile
end
Person Model
class Person < ActiveRecord::Base
has_one :supplier, as: :profile
end
On the Model level (on console) my associations works fine, but I have to those between the two model up front (supplier.profile = Company.new
, for example).
What I want is, when a user get to the NEW Supplier action he can select on the form if the Supplier is a Person or a Company, and then something must be done to show the correct fields for. And back on the Create action, handle everything.
I have read many stackoverflow questions and watch Ryan Bates cast #197 and #394.
I'm a Rails enthusiastic, not a programmer.
If someone can point me out to the right direction, I would be thankful.
Regards, David
Upvotes: 3
Views: 249
Reputation: 13621
This largely depends on the variety of fields you need, and how much data is shared. But if they are very different, I would actually have two separate divs or section on the page that a radio button toggles showing one & hiding the other with javascript. Can do this pretty easily with jquery at the bottom of the view, given it's a default in rails:
<input type="radio" name="supplier_type" value="person" />
<input type="radio" name="supplier_type" value="company" />
<script>
$('input[name="supplier_type"]').on('change', function () {
if ($(this).val() === "person") {
$('.person-form').show();
$('.company-form').hide();
}
else {
$('.person-form').hide();
$('.company-form').show();
}
});
</script>
Then inside each of those divs have an entirely separate form that post to different actions. If the data is different enough to require two forms, then it's worth having two different controllers for this.
Now if it's just a couple fields different, or an additional field for one or something. I would have the radio button same as above inside the form_for. Again attach some javascript to show or hide the values. In the controller, use a check against the radio button value to get the params you need:
supplier_params = params.slice :list, :of, :generic, :params
if params[:supplier_type] == "company"
supplier_params.merge! params.slice :company_name
elsif params[:supplier_type] == "person"
supplier_params.merge! params.slice :person_name
end
Supplier.new supplier_params
Upvotes: 2