我有一个Location
模型,它可以有许多子位置,或者一个父位置。假设location-A是父位置,具有location-B和location-C作为子位置。但是位置-B也具有子位置位置-D。
如何获取父位置A的所有子位置(包括位置D)?
我的型号:
has_many :sub_locations, class_name: "Location", foreign_key: "parent_location_id", inverse_of: :parent_location
belongs_to :parent_location, optional: true, class_name: "Location", foreign_key: "parent_location_id", inverse_of: :sub_locations
目前我是这样获取它们的:
def all_sub_location_ids
[id] + sub_locations.map(&:all_sub_location_ids).flatten
end
但我需要一个有效的方法。因为它抛出stack level too deep
编辑:我最终在子位置上使用了.reload
,并保持现有的方法不变。这样就成功了。
2条答案
按热度按时间relj7zay1#
您可以使用gem
ancestry
。请看官方文档here
在您的
gemfile
中添加宝石创建迁移
在您的
Location
模型中添加如下:现在你可以使用如下:
这里,子位置将是位置为
Location B
、Location C
、Location D
的数组。f5emj3cl2#
如果您愿意对数据模型进行更改并且正在使用Postgres,那么您可以快速浏览一下pg_ltree
有了这个gem,你可以使用locations表上的ltree列来组织你的位置,并发出如下查询:
如果您需要更高级的查询,那么您来对地方了:ltree还支持正则表达式匹配,这意味着你可以编写一些非常高级的查询对象。
这也将是相当快的,因为它将所有的工作卸载到数据库。这并不是说您不能在查询前抛出一个缓存,只是为了让您的PM惊叹,并让DBA脸上露出笑容。
处理长字符串作为叶子名称有一些明显的缺点,但如果树很高,您总是可以使用某种形式的主键或辅键。