Rails has_many через псевдонимы с источником и source_type для нескольких типов
Итак, вот пример класса
class Company < ActiveRecord::Base
has_many :investments
has_many :vc_firms, through: :investments, source: :investor, source_type: 'VentureFirm'
has_many :angels, through: :investments, source: :investor, source_type: 'Person'
end
@company.angels и @company.vc_firms работают должным образом. Но как я буду иметь @company.investors, которые состоят из обоих типов источников? Это будет работать для всех полиморфизмов в столбце инвестора таблицы "Инвестиции"? или, возможно, способ использования области слияния всех source_type?
Инвестиционная модель выглядит следующим образом:
class Investment < ActiveRecord::Base
belongs_to :investor, polymorphic: true
belongs_to :company
validates :funding_series, presence: true #, uniqueness: {scope: :company}
validates :funded_year, presence: true, numericality: true
end
Ангелы связаны через модель Person
class Person < ActiveRecord::Base
has_many :investments, as: :investor
end
Соответствующие ассоциации моделей финансовой организации:
class FinancialOrganization < ActiveRecord::Base
has_many :investments, as: :investor
has_many :companies, through: :investments
end
Ответы
Ответ 1
Предыдущее решение было неправильным, я неправильно понял одно из отношений.
Rails не может предоставить вам метод has_many, пересекающий полиморфное отношение. Причина в том, что экземпляры распространяются через разные таблицы (потому что они могут принадлежать к различным моделям, которые могут быть или не быть в одной таблице). Таким образом, вы должны предоставить source_type, если вы перейдете к полиморфному отношению belongs_to.
Сказав это, предположим, что вы можете использовать наследование у Инвестора следующим образом:
class Investor < ActiveRecord::Base
has_many :investments
end
class VcFirm < Investor
end
class Angel < Investor
end
Вы могли бы удалить полиморфную опцию из инвестиций:
class Investment < ActiveRecord::Base
belongs_to :investor
belongs_to :company
.........
end
И вы сможете пересечь отношение и охватить его условиями:
class Company < ActiveRecord::Base
has_many :investments
has_many :investors, through :investments
has_many :vc_firms, through: :investments, source: :investor, conditions: => { :investors => { :type => 'VcFirm'} }
has_many :angels, through: :investments, source: :investor, conditions: => { :investors => { :type => 'Angel'} }
end
Ответ 2
Я добавил метод в класс Company
, который выбирает всех инвесторов для компании, присоединившись к таблице инвестиций:
class Company < ActiveRecord::Base
has_many :investments
has_many :vc_firms, :through => :investments, :source => :investor, :source_type => 'VcFirm'
has_many :angels, :through => :investments, :source => :investor, :source_type => 'Angel'
def investors
Investor.joins(:investments).where(:investments => {:company_id => id})
end
end
http://www.brentmc79.com/posts/polymorphic-many-to-many-associations-in-rails выглядел довольно полезным для чтения на :source
vs. :source_type
.
Надеюсь, что это поможет!