Tuesday 18 August 2009

Polymorphic associations make my head hurt

Oh man.
I have an organisation class which has a number of "sub" classes - clients, printers, prospects, suppliers etc. An organisation can have many sub classes (ie an organisation could be simultaneously a client and a supplier for example).
Because clients, printers and prospects are quite different beasts they have to be different classes - not just different instances of the same class - hence the need to have a polymorphic relationship.
Tried to follow Ryan Bates's railscast but it wasn't really working for me.
After playing around with the console to get my head around what is really going on I came up with another way of sorting them out.
Have got the create method to work.
The way I came up with works on the basis that having denoted two classes to have a polymorphic relationship with each other, you can assign an instance of one to the other through the join (and that makes perfect sense ...)
What do I mean by that? Here are the models
class Organisation < ActiveRecord::Base
belongs_to :resource, :polymorphic => true

class Client < ActiveRecord::Base
has_one :organisation, :as => :resource

class Printer < ActiveRecord::Base
has_one :organisation, :as => :resource
if I instantiate an organisation object, o, and a client object, c, then by doing o.resource = c, I get the join I am looking for (sets the resource_id and resource_type) correctly.

My rather kludgy create model uses this:
params[:orgtypes].each do |ot|
@organisation = Organisation.new(params[:organisation])
resource = create_class(OrganisationType.find(ot).name)
resource.save!
@organisation.resource = resource


The create_class method takes a string and returns an instance of that class:
def create_class var
Object.const_get(var).new
end

I have a table of classes in the OrganisationType class - which allows me to add new ones dynamically which was my concern with doing everything hardwired - if I want a new sort of polymorphic thing, I can add one quite easily.
Now to sort out the update method, and to write some proper tests to make sure this sucker works in the way I hope it does.

No comments:

Post a Comment