Rails 在 Collection 中查找所有嵌套相册或 Collection

Rails Find all nested Albums or Collections in a Collection

这是我的两个模型:

Collection:

class Collection < ActiveRecord::Base

  has_many :children, class_name: "Collection", foreign_key: "parent_id"
  belongs_to :parent, class_name: "Collection", foreign_key: "parent_id", optional: true
  has_many :albums, dependent: :nullify

end

专辑:

class Album < ActiveRecord::Base

  belongs_to :collection, optional: true
  has_many :photos, dependent: :destroy

end

我需要一种方法来找到 parent Collection.

内的所有专辑 and/or Collection

关于如何完成此操作有什么想法吗?

这将允许我访问 parent Collection 等

中所有照片的列表

access a list of all the photos within a parent Collection

第一种方法,递归调用 get_photos 从 parent Collection 到它的 children 然后它的 grand-children 等等......直到有没有更多 child Collection.

class Collection < ActiveRecord::Base
 # ...
 def get_photos
   albums.map(&:photos).flatten.tap |photos|
     photos << children.map(&:get_photos).flatten
   end
 end
end

这可能会调用很多查询。

第二种方法,迁移 Collection table 以添加 collection path 列,因此如果 parent Collection c1 id 是1,它的路径是/1,它的children,比如,c2(id:2)和c3(id:3)那么c2的路径是/1/2 和 c3 路径是 /1/3,依此类推...每次在 parent Collection 下创建 child Collection 时,您设置它的路径#{parent_path}/#{id}.

现在您可以使用查询 where('path LIKE ?', "#{parent_path}/%") 来获取 parent Collection.

的所有 children collections
class Collection < ActiveRecord::Base
 # ...
 def get_photos
   collection_ids = where('path LIKE ?', "#{self.path}/%").pluck(&:id)
   album_ids = Album.where(collection_id: collection_ids).pluck(&:id)
   Photo.where(album_id: album_ids).all
 end
end

如果您只想调用一个查询,您可以直接将 collection-path 添加到照片 table。

根据书SQL Anti-pattern,你的问题是Naive Trees(Always Depend on One's Parent)。第二种方法是它的一种解决方案 - Path Enumeration,其他方法是 Nested SetsClosure Table.