Rails:通过多对多关系模型的嵌套项目列表

问题描述 投票:0回答:1

我是 Rails 的新手,有些东西我不完全理解。

我有以下4个模型

class Unit
  belongs_to :compound
  belongs_to :unit_type
end
class UnitType
  has_many :units
  has_many :unit_type_compounds
  has_many :compounds, through: :unit_type_compounds
end
class Compound
  has_many :units
  has_many :unit_type_compounds
  has_many :unit_types, through: :unit_type_compounds
end
class UnitTypeCompound
  belongs_to :unit_type
  belongs_to :compound
end

我想通过一个

units
获得所有
unit_type_compound

[with active status]

我尝试了以下方法,但是当我检查查询时,我发现它是错误的

第一:

class UnitTypeCompound
  belongs_to :unit_type
  belongs_to :compound

  has_many :units, through: :unit_type
end

query [for a single item

UnitTypeCompound.all.first.units
] 是这样的:

SELECT `units`.*
FROM `units`
  INNER JOIN `unit_types` ON `units`.`unit_type_id` = `unit_types`.`id`
WHERE `unit_types`.`id` = 31
  /* loading for inspect */
LIMIT 11

第二个:

class UnitTypeCompound
  belongs_to :unit_type
  belongs_to :compound
  has_many :units, through: :unit_type, source: :unit_type_compounds

  has_many :active_units, ->{ where(status: :active) }, class_name: Unit.to_s,
           through: :unit_type, source: :unit_type_compounds
end

query [for a single item

UnitTypeCompound.all.first.units
] 是这样的:

SELECT `units`.*
FROM `units`
  /* Note: the following condition is units.id not compounds.id */
  INNER JOIN `unit_type_compounds` ON `units`.`id` = `unit_type_compounds`.`compound_id`
  INNER JOIN `unit_types` ON `unit_type_compounds`.`unit_type_id` = `unit_types`.`id`
WHERE `unit_types`.`id` = 31
  /* loading for inspect */
LIMIT 11

和查询 [for a single item

UnitTypeCompound.all.first.active_units
] 是这样的:

SELECT `units`.*
FROM `units`
  /* Note: the same condition */
  INNER JOIN `unit_type_compounds` ON `units`.`id` = `unit_type_compounds`.`compound_id`
  INNER JOIN `unit_types` ON `unit_type_compounds`.`unit_type_id` = `unit_types`.`id`
WHERE `unit_types`.`id` = 31
  AND `units`.`status` = 0
  /* loading for inspect */
LIMIT 11

第三:

使用方法有效

class UnitTypeCompound
  belongs_to :unit_type
  belongs_to :compound

  def vacant_units
    Unit.where(status: :vacant)
        .where(compound: compound)
        .where(unit_type: unit_type)
  end
end

但是,如果有办法通过

has_many
之类的,我会徘徊吗?

ruby-on-rails ruby-on-rails-6 has-many-through has-many
1个回答
0
投票

出于某些原因,您的场景不适合

has_many
。您处于
UnitTypeCompound
通过两个不同的关联有很多
units
的情况,并且您想要这两个关联的
units
的交集。

这不应该与

has_many
一起工作的第一个原因是,使用自然语言,您会期望如果
UnitTypeCompound
有很多单位,它将是这两个关联的联合,而不是交集。

第二个原因是

has_many
应该是可逆的。如果您调用
unit.unit_type_compounds
,您会期望它是
unit.unit_type.unit_type_compounds
unit.compound.unit_type_compounds
,这两者的结合或它们的交集吗?

第三是您应该能够在关联上调用

collection<<
方法。如果你打电话给
unit_type_compound.units << Unit.last
它应该通过
UnitType
Compound
创建那个关联吗?

你的场景有很多歧义,不能用简单的

has_many :units, through:
来表达,因此如果
vacant_units
方法对你有用,我会坚持下去。

© www.soinside.com 2019 - 2024. All rights reserved.