【问题标题】:writing associations for a recursive relationship为递归关系编写关联
【发布时间】:2011-11-23 02:57:42
【问题描述】:

如果您愿意,请提供一点帮助。

我想与我的“产品”类创建一个递归关系。我可以让一种产品成为其他产品的父产品。我的问题是如何在我的模型中创建这种关系?

这样合适吗?

has_many :products
belongs_to :product

【问题讨论】:

    标签: ruby-on-rails-3 activerecord ruby-on-rails-3.1 associations


    【解决方案1】:

    逻辑上您提出的解决方案没有任何问题。但是,您可能需要执行以下操作:

    belongs_to :parent, class_name: "Product", foreign_key: "parent_id"
    has_many :children, class_name: "Product", foreign_key: "parent_id"
    

    您基本上是在存储一棵“树”,顶部有一个产品,下面是子产品的分支,可能有很多层次。

    您示例中的策略称为Adjacency List。很容易找到任何给定记录的直系父代和直系后代。但是,获取所有后代(包括后代的后代)可能会很困难,而且树越深越难。

    另一种常用的方法是Nested Set,其中每条记录都将有关对象的信息存储在其“左侧”和“右侧”。这使您可以非常快速地(或至少有效地,在单个查询中)构建一棵树,无论它有多大。但是,它更复杂,插入记录通常意味着必须重新计算并更新插入记录右侧的所有记录。

    第三种选择(可以说是一种中间立场)是使用Path Enumeration,其中对象将其整个路径存储在树中。所以,给定一棵这样的树:

      A
     / \
    B   C
        |
        D
    

    A 将具有空白路径(无父路径),BC 将具有路径 AD 将具有路径 A/C。使用此解决方案,大多数插入操作相对便宜,并且查询非常容易。然而,它仍然相当复杂,并且在树中移动对象可能会变得很昂贵。

    还有其他选项,例如Closure Tables

    如果一个简单的邻接列表可以满足您的需求,那么就使用它。它绝对是最简单和最容易理解的。有一些 gem 实现了嵌套集合,也许还有其他一些树模式,所以如果你走这条路,你不必自己做所有繁重的工作。

    【讨论】:

    • 哇!很棒的答案,像您这样的人使这样的网站很棒。谢谢!
    • This answer 在实现闭包表模式时非常方便。
    • 很好的答案,谢谢!这对于使用一个模型在帖子上执行 cmets 之类的操作很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 1970-01-01
    • 2018-07-30
    • 2020-11-09
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多