Rails single table inheritance with polymorphic association

Lets say, you wanted to store contact information such as emails, phone numbers, and websites. These contact information can be associated with an employee of a business or the business itself. A business can have multiple emails and multiple phone numbers. Similarly, an employee can have multiple emails and multiple phone numbers. In Rails, we can store all these contact information in a single table using both the polymorphic association and single-table inheritance. First, lets see how we can use polymorphic association to deal with the contact information.

We have the following active record models for a “Business” and an “Employee”:

class Business < ActiveRecord::Base; end
class Employee < ActiveRecord::Base; end

For the contact information, we have the following active record models:

 

class Email < ActiveRecord::Base; end
class PhoneNumber < ActiveRecord::Base; end
class Website < ActiveRecord::Base; end

Now, for the associations, Business and Employee models can have many emails, phone numbers and websites. And conversely, Email/Phone Number/Website can belong to either a Business model or an Employee model. How do we make up the association?

Rails ActiveRecord provides an association called “Polymorphic” association. Using polymorphic association, a model can belong to more than one other model, on a single association. Here is how this can be implemented:

class Business < ActiveRecord::Base
has_many :emails, :as => :emailable
has_many :phone_numbers, :as => phonable
has_many :websites, :as => webable
end

class Employee < ActiveRecord::Base
has_many :emails, :as => :emailable
has_many :phone_numbers, :as => phonable
has_many :websites, :as => webable
end

class Email < ActiveRecord::Base
belongs_to :emailable, :polymorphic => true
end
class PhoneNumber < ActiveRecord::Base
belongs_to :phonable, :polymorphic => true
end
class Website < ActiveRecord::Base
belongs_to :webable, :polymorphic => true
end

Having the above setup, you can get a collection of emails for a business instance via the call “@business.emails”. Similarly, you can get a collection of emails for an employee instance via “@employee.emails”.

Now, if you really think about what a contact information is? It basically contains a label and an information. I.e. Personal Email: test@gmail.com, Business Phone Number: 1-800-999-9999, Business Website: www.google.com, etc.

So, we can say that an email, a phone number, or a website is an instance of a contact information class with two attributes: a label and an information. Thus, we can store any type of contact information in a single table.

In rails, if you name a column “type”, by default ActiveRecord allows inheritance by storing the name of the class in the column type. You can overwrite the Base.inheritance_column to change the name of the column where the class name is stored. Now, changing our polymorphic associations as “contactable”, we can have the following setup:

class Business < ActiveRecord::Base
has_many :emails, :as => :contactable, :class_name => "Email"
has_many :phone_numbers, :as => :contactable, :class_name => "PhoneNumber"
has_many :websites, :as => :contactable, :class_name => "Website"
end
class Employee < ActiveRecord::Base
has_many :emails, :as => :contactable, :class_name => "Email"
has_many :phone_numbers, :as => :contactable, :class_name => "PhoneNumber"
has_many :websites, :as => :contactable, :class_name => "Website"
end

class ContactInformation < ActiveRecord::Base
belongs_to :contactable, :polymorphic => true
end
class Email < ContactInformation
# any validation for email can go here
end
class PhoneNumber < ContactInformation
# any validation for phone numbers can go here
end
class Website < ContactInformation
# any validation for website urls can go here
end

All the emails, phone numbers and websites will now be stored in the table associated with the model “ContactInformation” and will have the following setup:

create_table :contact_informations, :force => true do |t|
t.string "contactable_type"
t.integer "contactable_id"
t.string "type"
t.string "label"
t.string "info"
t.timestamps
end

Now, when you create a business email:

@email = @business.build.emails(:label => "Personal", :info => "test@gmail.com");
@email.save!

the record will be saved in the table “contact_informations” with the values “Business” for the “contactable_type”, @business.id for the “contactable_id”, and “Email” for the column “type”.

Similarly, for employee phone number:

@phone = @employee.build.phone_numbers(:label => "Work", :info => "1-800-123-4567");
@phone.save!

the record will be saved in the table “contact_informations” with the values “Employee” for the “contactable_type”, @employee.id for the “contactable_id”, and “PhoneNumber” for the column “type”.

Rails makes it really easy to do a single table inheritance with polymorphic association.

Leave a comment

A better installer

So about a month and a half ago, I was driving home from work one day after working on some NSIS installer code (which in my humble opinion is very ugly and hard to work with), when I had the thought “How come no one uses managed code to write installers?”. Managed code is so much cleaner to read, and the .NET framework is so powerful. Most of the time we’re just copying files, writing registries, and running some msiexec anyways right? nothing managed code can’t handle.

So I did a little bit of googling and then found this amazing new beta release of WiX 3.6. In the beta release there is a new bootstrapper/downloader module named Burn which allows you to chain multiple MSIs together (something WiX was lacking for a very long time), download packages online, and use managed code to create the bootstrapper interface. After reading about the features here and trying out the Visual Studios 11 Preview installer, I was pretty convinced to give it a shot.

After using Burn for a while, I can say that there are some clear advantages with using managed code to write a bootstrapper. The first advantage is that it allows you to streamline your interface in so many different ways… for example, you don’t have to create a page where you “accept the license agreements” anymore, since most people don’t read that anyways. It also lets you create an experience where the novice users can simply click an install button, without having to select all the customization options.

Another advantage is that you can use all the features of Windows Forms and WPF to create your interface. So this allows you to use all types of different controls and animations to create a much better looking user interface.

There are disadvantages of using a managed bootstrapper though, because it requires that the user has the .NET framework installed on their computer. Thankfully, Burn also handles that for you. When Burn fails to run the managed bootstrapper, it will run a separate bootstrapper to install the .NET framework first. Following that, it will run your own installer.

Some more disadvantages of using Burn right now, is that there is almost no documentation, and that there are still some bugs in the framework. In terms of the documentation, you really have to be prepared to do a lot of googling to find the answers that you’re looking for. Sometimes, I had to dig through the open source C++ code to get a better understanding of how the Burn engine works.

For those that want to give the toolset a try, here are some tips that I think will be helpful:
1) Read http://blogs.msdn.com/b/heaths/archive/2011/10/28/introducing-managed-bootstrapper-applications.aspx
2) Download the WiX source and take a look at the project stored in “wix36-sources\src\Setup\UX”. It contains the managed code that was used to create the WiX installer
3) Dig through http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/ when you need to find answers

Leave a comment

TextMate 2 Tips

tl:dr:To celebrate the long-awaited releaset of TextMate 2 this week, my friend Kevin and I have started a new tumblelog called Text Mate 2 Tips to offer simple visual tips on how to use the new features of our favourite text editor.

Way back in 2005, watching screencasts of Rails developers working in TextMate and the almost telekinetic way they could manipulate code with it was a big reason I finally switched to a mac.

As time wore on, and the release of TextMate 2 slipped further and further, the update became a canonical example of vapourware, right along side Duke Nukem. People started abandoning TextMate looking for something new that could replace it. And, though I dallied with several of these contenders, none of them fit as transparently with the way I work and think in code.

So, I was excited earlier this week to learn that an alpha version of TextMate 2 has finally been released to the public, and it’s nowhere near as horrible as Duke Nukem Forever.

There was one problem; though there were many new features in the long-awaited release, documentation was scant. It was a challenge to hunt for bits of intel through trial and error and Github commits. So I decided to start a tumblelog to capture the tips and tricks I discovered and to solicit tips to share from others. The TextMate 2 Tips blog was born. The response has been overwhelming with core TextMate developers contributing tips. And I am honoured that we even got a nice link from the Macromates blog!

If you are a TextMate user and want to take advantage of all the features of the new release, then check out the blog or follow tm2tips on twitter, and if you’ve got a tip submit it and we’ll share it on the blog.

1 Comment

Building tomorrow

Conventional wisdom says you should listen to your customers. Most people will agree to that without questions.

The idea of listening to the people you serve – be they customers, users, etc, becomes so prevalent that the discipline of gathering feedback and reacting to them have been codified into repeatable models. In marketing, you have survey, focus group, etc. In project management, you do requirements gathering, prototypes, inviting client feedback, etc. And now recently, even in building a company, you have the lean startup model.

The good thing about this is that it reduces risks. After all, if your target group gives you the stamp of approval, it’s hard to imagine things will go wrong later.

This is all good if we want incremental improvements on well-defined problems – logically sensible and emotionally comforting next steps.

But what about radically new ideas?

Ideas that require huge amount of effort to build. Ideas that will take time for people to understand and adopt. Ideas that ultimately change how we live and work.

If we go back in time, how do you think a focus group of random strangers will react to Twitter, before Twitter becomes so popular? How about to the internet, before internet’s time? How about a computer, before Microsoft?

As a company, not only should we listen to our customers, but we should go one step further: imagine and deliver something that makes radical improvements, and, through that, build a better tomorrow for everyone – even if everyone might not fully understand it today.

“If I had asked people what they wanted, they would have said faster horses.”
-Henry Ford, founder of Ford Motor Company

Leave a comment

A declarative way of handling property changed notifications

A calculated property is something that is calculated based on the results of some other properties. For example:

  • Subtotal = Unit Cost * Quantity
  • The finalize button should be enabled if the order status is Open
  • The unit cost is editable if the order isn’t finalized and the user has the appropriate access rights
  • Password change is valid if NewPassword.Length >= 6 && NewPassword == NewPasswordConfirmation

You’d go ahead and define something like:

        public decimal Subtotal
        {
            get { return UnitCost * Quantity; }
        }

This is all fine and dandy so far. But if you’re doing this in a Windows Forms application and you want to use DataBinding or an ErrorProvider, you need to implement INotifyPropertyChanged, i.e. raise an event called PropertyChanged whenever your calculated properties change.

The most straightforward way of doing this is whenever the UnitCost or Quantity changes, you raise PropertyChanged on Subtotal as well, so something like:

        private decimal _unitCost;
        public decimal UnitCost
        {
            get
            {
                return _unitCost;
            }
            set
            {
                _unitCost = value;
                PropertyChanged("UnitCost");
                PropertyChanged("Subtotal");
            }
        }

Or in other cases, you might update it right in the UI code, like this:

        public void OnOrderStatusChanged(Status newStatus)
        {
            buttonFinalize.Enabled = (newStatus == Status.Open);
        }

This is fine in a small application, but as things grow and evolve, it quickly becomes an unmaintainable mess. You might tweak the conditions for your calculated properties and forget to update the PropertyChanged notifications, introducing subtle bugs. You might have to dig through multiple places in your code just to figure out when a button should be enabled. This was one of the most painful parts of our codebase, and I was looking for a way to make this simpler. If Excel can figure out everything it needs to update whenever a value changes, why can’t Windows Forms?

Turns it, it is more or less possible, with some tricks and some boilerplate. We’ve got it working with something that looks like this:

public static PropertyInfo SubtotalProperty = For<Line>(l => l.Subtotal).Define(l => l.Qty * l.PriceEa);

We wrote some framework code to support this and ended up doing:

  • Define a View Model class for most of these calculated properties
  • Use DataBinding to link the View Model properties and the associated properties on the Form, e.g. buttonFinalize.Enabled
  • In the View Model, write the calculated property and the expression that defines it. This way, when you look at the FinalizeButtonEnabled property, you see its definition newStatus == Status.Open right above it.
  • Use System.Linq.Expressions to interpret the expression definition and track at the source properties it depends on.
  • Write some library code that automatically updates the calculated properties and raises PropertyChanged whenever the source properties change.

The end result is that we can just define these calculated properties and the framework code will automatically interpret when to update them, raising PropertyChanged notifications appropriately. It’s easy to debug when things go wrong (you just look at the declaration and see if it makes sense) and a pleasure to work with. I’d love to see this sort of feature get added to frameworks like CSLA .NET.

Update: I’ve now uploaded some sample code to demo this concept. Download sample code.

3 Comments