获取递归树结构中子项的属性,除非它是叶节点

时间:2014-12-15 03:24:30

标签: ruby-on-rails-4 tree override getter recursive-datastructures

我有一个用于处理我的类别的递归树结构。每个叶子类别可以有零个或多个交易。类别由

定义
class Category < ActiveRecord::Base
  has_many :sub_categories, class_name: "Category", foreign_key: "parent_category_id"
  belongs_to :parent_category, class_name: "Category"

  has_many :deal_categories
  has_many :deals, through: :deal_categories

  def leaf?
    !has_sub_categories?
  end

  def has_sub_categories?
    !sub_categories.empty?
  end
end

DealsDealCategories如下所示:

class Deal < ActiveRecord::Base
  has_many :deal_categories
  has_many :categories, through: :deal_categories
end

class DealCategory < ActiveRecord::Base
  belongs_to :deal
  belongs_to :category
end

还有一些验证可确保Deals可以作为叶子类别存在。因此,如果我在叶节点上调用category.deals,我会得到一些交易,如果我在根节点上调用它,我会得到一个空结果。一切都好。

但是现在我希望category.deals返回它的孩子的交易,如果它不是根节点的话。我的方法是在Category类中覆盖以下方法,如下所示:

  alias_method :original_deals, :deals
  def deals
    if leaf?
      self.original_deals
    else
      self.sub_categories.deals
    end
  end

这不起作用,因为我无法直接在deals上致电sub_categories,错误是

undefined method `deals' for #<Category::ActiveRecord_Associations_CollectionProxy:0x00000009243d40>

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

您不能在sub_categories上调用交易,因为它不是类别......它是类别的集合。相反,你可以做类似

的事情
sub_categories.reduce([]) { |union, sub_category| union + sub_category.deals }

使用reduce创建一个备忘录对象(由union变量表示),并且块的评估将成为新的备忘录对象。我从一个空数组开始,并在sub_categories集合中的每个sub_category上添加调用交易的结果。