我是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
我希望通过unit_type_compound
获取所有units
[具有活动状态]
我尝试了以下方法,但是当我检查查询时,我发现它是错误的
第一:
class UnitTypeCompound
belongs_to :unit_type
belongs_to :compound
has_many :units, through: :unit_type
end
查询[针对单个项目UnitTypeCompound.all.first.units
]类似于:
SELECT `units`.*
FROM `units`
INNER JOIN `unit_types` ON `units`.`unit_type_id` = `unit_types`.`id`
WHERE `unit_types`.`id` = ?
/* 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 :vacant_units, ->{ where(status: :vacant) }, class_name: Unit.to_s,
through: :unit_type, source: :unit_type_compounds
end
查询[针对单个项目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` = ?
/* loading for inspect */
LIMIT 11
查询[对于单个项目UnitTypeCompound.all.first.vacant_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` = ?
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
查询[对于单个项目UnitTypeCompound.all.first.vacant_units
]如下所示:
SELECT `units`.*
FROM `units`
WHERE `units`.`sellable` = FALSE
AND `units`.`compound_id` = ?
AND `units`.`unit_type_id` = ?
AND `units`.`status` = 0
/* loading for inspect */
LIMIT 11
但是,我想知道是否有一种方法通过has_many
或其他东西?
1条答案
按热度按时间hjzp0vay1#
您的场景不适用于
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
方法对您有效,我将坚持使用它。如果你想尝试用一个关联来做它,我最好的猜测是它应该看起来像这样: