Lets say I have a STI model called Company
. It has three sub-classes Firm
, Client
and PriorityClient
.
class Company < ActiveRecord::Base
scope :firms_n_clients, -> { where(type: %w(Firm Client)) }
end
class Firm < Company; end
class Client < Company; end
class PriorityClient < Company; end
I have another model called Country
. Now I want to create a has_and_belongs_to_many
association between Country
and firms_n_clients
(only Firm
and Client
type of Company
). How would it be?
Thanks in advance.
has_and_belongs_to_many associations accept scopes. Some of them are discussed in the Ruby on Rails documentation. Assuming the necessary join table exists, the association can be established like so:
class Country < ActiveRecord::Base
has_and_belongs_to_many :companies, -> { where(type: %w(Firm Client)) }
end
class Firm < Company
has_and_belongs_to_many :countries
end
class Client < Company
has_and_belongs_to_many :countries
end
Please note the duplicate Code in Client and Firm. This is on purpose, because it reveals explicitly that Clients and Firms have and belong to countries, and PriorityClients do not.
I have not tested the below code, but an even better way to modify the HABTM Association would be to merge the the firms_n_clients scope:
class Country < ActiveRecord::Base
has_and_belongs_to_many :companies, -> { merge(Company.firms_n_clients) }
end
This has several advantages: The Country model doesn't need to know about the different Company types, and modifying the scope will affect the association as well.