Вы можете решить свою проблему с помощью ИППП и регулярной ассоциации:
class HostPest < ActiveRecord::Base
belongs_to :host
belongs_to :pest
end
Сохраните все хосты в таблице с именем hosts
. Добавьте в таблицу строковый столбец с именем type
.
class Host < ActiveRecord::Base
has_many :host_pests
has_many :pests, :through => :host_pests
end
Унаследуйте класс Host
для создания новых хостов.
class Dog < Host ; end
class Cat < Host ; end
Храните все вредные организмы в таблице под названием pests
. Добавьте в таблицу строковый столбец с именем type
.
class Pest < ActiveRecord::Base
has_one :host_pest
has_one :host, :through => :host_pest
end
Унаследуйте класс Pest
для создания новых вредных организмов.
class Flea < Pest ; end
class Tick < Pest ; end
Теперь, когда вы можете запустить следующие команды:
dog.pests (returns a list of pests associated with this dog)
flea.host (return the host associated with this flea)
cat.pests << Tick.create (creates a HostPest record)
tick.host = Cat.create (creates a HostPest record)
Примечание
Rails поддерживает has_many :through
на полиморфных классах. Вам нужно указать source_type
, чтобы это работало.
Рассмотрим модели для пометки:
class Tag
has_many :tag_links
end
class TagLink
belongs_to :tag
belongs_to :tagger, :polymorphic => true
end
Допустим, товары и компании могут быть помечены.
class Product
has_many :tag_links, :as => :tagger
has_many :tags, :through => :tag_links
end
class Company
has_many :tag_links, :as => :tagger
has_many :tags, :through => :tag_links
end
Мы можем добавить ассоциацию к модели Tag, чтобы получить все помеченные продукты следующим образом:
class Tag
has_many :tag_links
has_many :products, :through => :tag_links,
:source => :tagger, :source_type => 'Product'
end