Rails has_many通过使用source和source_type别名来处理多种类型

Mic*_*son 11 activerecord ruby-on-rails associations has-many has-many-through

所以这是一个示例类

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
Run Code Online (Sandbox Code Playgroud)

@ 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
Run Code Online (Sandbox Code Playgroud)

天使通过人物模型联系在一起

class Person < ActiveRecord::Base
    has_many :investments, as: :investor
end
Run Code Online (Sandbox Code Playgroud)

相关金融机构模型协会:

class FinancialOrganization < ActiveRecord::Base
    has_many :investments, as: :investor
    has_many :companies, through: :investments
end
Run Code Online (Sandbox Code Playgroud)

pol*_*iro 14

以前的解决方案是错误的,我误解了其中一个关系.

Rails无法为您提供跨越多态关系的has_many方法.原因是实例通过不同的表分布(因为它们可以属于可能或不在同一个表中的不同模型).因此,如果您跨越belongs_to多态关系,则必须提供source_type.

话虽如此,假设您可以在投资者中使用继承,如下所示:

class Investor < ActiveRecord::Base
  has_many :investments
end

class VcFirm < Investor
end

class Angel < Investor
end
Run Code Online (Sandbox Code Playgroud)

您可以从投资中删除多态选项:

class Investment < ActiveRecord::Base
  belongs_to :investor
  belongs_to :company

  .........
end
Run Code Online (Sandbox Code Playgroud)

并且您将能够跨越关系并将其与条件进行范围调整:

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
Run Code Online (Sandbox Code Playgroud)