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.

Надеюсь, что это поможет!