提问人:cnn 提问时间:6/16/2023 最后编辑:cnn 更新时间:6/19/2023 访问量:48
获取属于模型的所有嵌套对象
Getting all nested objects belongs to a model
问:
我有一个模型,该模型可以具有多个子位置或一个父位置。
假设位置 A 是父位置,位置 B 和位置 C 是子位置。但位置 B 也有一个子位置 D。Location
如何获取父位置 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赞
Amol Mohite
6/16/2023
#1
您可以使用 gem 。ancestry
请看一下这里的官方文档
将 Gem 添加到您的gemfile
gem 'ancestry'
创建迁移
rails g migration add_Add_ancestry_to_location ancestry:string:index
在您的模型中添加它,如下所示:Location
class Location < ApplicationRecord
has_ancestry
end
现在您可以使用如下:
location_a = Location.create(name: 'Location A')
location_b = Location.create(name: 'Location B', parent: location_a)
location_c = Location.create(name: 'Location C', parent: location_a)
location_d = Location.create(name: 'Location D', parent: location_b)
parent_location = Location.find_by(name: 'Location A')
sublocations = parent_location.descendants
这里的子位置将是一个数组,其位置为 , , .Location B
Location C
Location D
0赞
Nick M
6/18/2023
#2
如果您愿意对数据模型进行更改并且正在使用 Postgres,也许您可以快速浏览一下pg_ltree
使用此 Gem,您可以使用位置表上的 ltree 列来组织您的位置,并发出如下查询:
Location.find_by(path: "Earth.Europe")
Location.find_by(path: "Earth.Europe.France").root
Location.find_by(path: "Earth.Europe.France.Paris").children
如果您需要更高级的查询,那么您来对地方了:ltree 还支持正则表达式匹配,这意味着您可以编写一些非常高级的查询对象。
此外,这将非常快,因为它将所有工作卸载到数据库。并不是说你不能在查询前面抛出缓存,只是为了让你的 PM 惊叹不已,让你的 DBA 脸上露出灿烂的笑容。
显然有一些缺点与处理长字符串作为叶子名称有关,但如果你的树很高,你总是可以使用某种形式的主键或辅助键。
评论
祖先
是最受欢迎的功能之一。