I am working on an application to track warranty registrations for my employers product line. The product line includes the following products:
spreaders snow_plows skid_steers
Each of these products have different information that I have to track. The tables would look something line this:
create_table :spreaders do |t| t.integer :registration_id t.string :spreader_sn t.string :spreader_model_number
create_table :snow_plows do |t| t.integer :registration_id t.string :power_pack_sn t.string :control_package_sn t.string :blade_sn
create_table :skid_steers do |t| t.integer :registration_id t.string :plow_sn t.string :plow_control_sn t.string :blade_sn
Notice how each of these products need to collect different information. They are all registrations so I can create table to hold these registrations with information that is common to them all.
create_table :registrations do |t| t.integer :customer_id t.integer :dealer_id t.date :date_purchased t.integer :vehicle_id t.text :comment t.integer :registerable_id t.string :registerable_type
I have the models defined like so:
class Registration < ActiveRecord::Base belongs_to :customer belongs_to :dealer belongs_to :vehicle belongs_to :registerable, :polymorphic => true end
class Spreader < ActiveRecord::Base has_many :registrations, :as => :registerable end
class SnowPlow < ActiveRecord::Base has_many :registrations, :as => :registerable end
class SkidSteer < ActiveRecord::Base has_many :registrations, :as => :registerable end
At this point I am trying to simply display a record on the registration view and can't seem to understand how I would access this. Here's my registration view:
1 <h1>Listing registrations</h1> 2 3 <table> 4 <tr> 5 <th>Customer Name</th> 6 <th>Dealer Name</th> 7 <th>Date purchased</th> 8 <th>Product</th> 9 <th>Product SN</th> 10 <th>Vehicle</th> 11 <th>Comment</th> 12 </tr> 13 14 <% for registration in @registrations %> 15 <tr> 16 <td><%=h registration.customer.full_name %></td> 17 <td><%=h registration.dealer.dealer_name %></td> 18 <td><%=h registration.date_purchased %></td> 19 <td><%=h registration.registerable_type %> 20 <td><%= registration.registerable_type.id %> 21 <td><%=h registration.vehicle.model %></td> 22 <td><%=h registration.comment %></td> 23 </tr> 24 <% end %> 25 </table> 26 27 <%= link_to 'New Registration', new_registration_path %>
On lines 16, 17 and 21, I am able to display the full_name of the Customer, likely because my Registration belongs_to the Customer. I am also able to see the dealer_name of the Dealer, similarly because my Registration belongs_to the Dealer. And finally the model of the Vehicle, again because of the magical belongs_to declaration. Wonderful. On line 20 is where I loose my mind.
I'm thinking there should be some similar magic going on behind the scenes to view the product (Spreader, SnowPlow, or SkidSteer) of the type listed in the registerable_type field because of my nifty: belongs_to :registerable, :polymorphic => true declaration in the Registration model. How would I access this record? It seems to me this functionality needs to be customized in the RegistrationsController because unlike the simple foreign key relationship Customers and Dealers enjoy with Registrations Rails does not know how to handle this polymorphic relationship by default. Or, which is probably more likely, I have no idea what I'm talking about and Rails DOES magically pull in the correct table because of that association. Ideas?
I can understand how to do this if I were to do this entirely differently by changing my design. For instance creating three new models called SpreaderRegistration, SnowPlowRegistration and SkidSteerRegistration and just throwing the whole idea of polymorphic relationships out the window. But it introduces duplication and I would have to maintain three separate MVC's for each. Seems silly and not at all extensible. What if I have to add a new product that needs to be registered? Not I good idea I think.
There are other considerations I need to think about as well; such as how would I tell the Registration it is registerable_type Spreader so it can create a new registration form that loads in the fields I need for the Spreader as well as the fields for all registrations. I am getting ahead of myself.
This MUST be a common problem. Can someone point me to a good tutorial that deals with this? I've found others that talk about polymorphic types and give migration and model examples, but nothing for the view or controller.
Thanks for your thoughts and time.