Topic: STI: fetching two types at the time?

I have a question, which again might be against how things are made. I'm not sure if it's possible. but I really would like my model to be proper.

I have a type column in a table to enable Single Table Inheritance.

I want to have a list of companies. some companies are publishers, some are developers and some are both. but I don't want to store the same company twice for both type. at the same time, When I do a Publisher.find I wish to query the companies at are publishers only and those who are both, publishers and developers.

how could I do that?

Re: STI: fetching two types at the time?

STI doesn't allow you to specify multiple types - and you definitely don't want to be adding duplicate company entries to solve this problem.

There are two different ways you can solve this. One is to remove the single table inheritance and split it into two tables: publishers and developers. Like this:

class Company < ActiveRecord::Base
  has_one :publisher
  has_one :developer
end

class Publisher < ActiveRecord::Base
  belongs_to :company
end

class Developer < ActiveRecord::Base
  belongs_to :company
end


This may work really well if publishers and developers have their own attributes.

Another way is to move the STI into its own table - let's call it "roles".

class Company < ActiveRecord::Base
  has_many :roles
end

class Role < ActiveRecord::Base
  belongs_to :company
end

class Publisher < Role
end

class Developer < Role
end


You would then create two "role" models for a company if it acts as a developer and a publisher.

Where this really shines is if the role of the company is dependent upon some other model - like client. In that case this "roles" table can act as a join table between the two

class Company < ActiveRecord::Base
  has_many :roles
  has_many :clients, :through => :roles
end

class Role < ActiveRecord::Base
  belongs_to :company
  belongs_to :client
end

# Publisher and Developer subclasses not shown

class Client
  has_many :roles
  has_many :companies, :through => :roles
end


In this case client has_many :roles doesn't really make sense, so you may want to rename the Role model.

Railscasts - Free Ruby on Rails Screencasts