Hello and happy Monday!
In Friday’s Post, I was having trouble using multiple polymorphic associations on one polymorphic table,
PhoneNumber. Over the weekend, I did some digging around. I’ll get into my solution in just a second, but first lets take a peak at Friday’s polymorphic hurdle.
Here’s the view template:
The problem with the output of data on this page is that the
secondary_phone‘s number isn’t being retrieved from the database. Only the primary numbers are.
This is due to Rails/ActiveRecord not being able to differentiate between two calls on a polymorphic table with the information I provided in the association declarations on the model.
What Went Wrong
So whats the deal, you may be asking? Well, looking at the example above it makes sense to me that there really is no clear way to differentiate between a
secondary_phone. Since they are two objects from the same class, with the options defined in the example above, there is not a way for the
phoneable table to say “Hey, I’m a primary or secondary number”.
I did some hunting and found a few resources on StackOverflow that helped me understand this issue a little better. I’ll list them here in case you’d like to learn more about overcoming this sort of thing in your coding future.
I learned the most from this question.
And here are two additional resources on the topic.
- Multiple Polymorphic Association on Same Model in Rails
- Using Single Table Inheritance & Polymorphic Model for Multiple Uploads
Alas, I could not get the results I sought using STI and Rails Polymorphic. I did get our multipart form to actually return the proper primary and secondary phone numbers. And here’s how I did it.
What worked for me
Let me first say, that I feel as though my attempt at extract class wasn’t as successful as I would have liked. I ended up just building two models
SecondaryPhoneNumber as separate classes, due to an inability to implement STI in a timely fashion.
PhoneNumber class is now on the side-lines and it’s replacement models now look like so:
Yes, my code is wetter than a water park slide on Independence day. This is because I’m creating two classes with exactly the same attributes in order to gain an ability (without STI) to allow
Student to all be able to have a primary and secondary number.
I plan on working on utilizing STI in my spare time, but felt it necessary to move forward instead of allowing something like this to encumber progress.
Here is what my three main classes (teacher.rb, teacher_aid.rb and student.rb) now look like as I’ve defined associations on all of them for the primary and secondary telephone numbers.
This has only one advantage, in that the template now renders the secondary number whereas on Friday, it was returning the value stored in primary number for the variable designed to return the secondary one. The downside, besides the overt redundancy, is that if I need an additional number I’ll have to create another class. I would have had to do that anyway using STI. But with STI I could have inherited the base class’ (
PhoneNumber) methods, and in the event of an addition or some other form of change, would have needed to only make changes to the base class’ interface. As it stands now, I’ll have to go into each of the specific phone number classes and have at least 2 places to remember to make changes to.
Now that my “This isn’t the OO way to do it” disclaimer is done, lets look at the results of our original goal. Check out
accepts_nested_attributes_for in action!
Here’s what a client has entered:
And here’s the database retrieving this resource, note that primary and secondary fields are now listing their own numbers:
In closing, I hope that these past few posts have been informative for you towards understanding how to have one form template store values for multiple models. As always, if you have any comments or critiques, feel free to leave a message.