从rails中的所有子对象获取集合

时间:2014-05-14 18:20:57

标签: ruby-on-rails

我已经实现了这样的事情:

class Move < ActiveRecord::Base
  has_many :move_categories
  has_many :categories, through: :move_categories
end

class Category < ActiveRecord::Base
  has_many :move_categories
  has_many :moves, through: :move_categories
  belongs_to :parent, class_name: 'Category'
  has_many :subcategories, class_name: 'Category', foreign_key: 'parent_id'
end

因此,对于给定的类别,我需要找到获得所有移动的最佳方式,以及来自子类别的所有移动,以及来自子类别的子类别的移动,等等上。

有什么想法吗?

编辑:

这是MoveCategory模型:

class MoveCategory < ActiveRecord::Base
  belongs_to :move
  belongs_to :category

  validates_uniqueness_of :category_id, scope: :move_id
end

1 个答案:

答案 0 :(得分:1)

由于您使用的是PostreSQL,因此您应该利用WITH RECURSIVE CTE语法来执行此操作。请参阅http://hashrocket.com/blog/posts/recursive-sql-in-activerecord以获得精彩的文章。

如果您实施tree方法,那么所有缺失的内容都是移动检索:

def Category < ActiveRecord::Base
  def descendant_moves
    tree_id_sql = self.class.tree_sql_for(self)
    Move.joins(:move_categories).where("move_categories.category_id IN (#{tree_id_sql})")
  end
end

为了完整起见,请点击以上列出的页面中tree_sql_for方法的代码:

def self.tree_sql_for(instance)
  tree_sql =  <<-SQL
    WITH RECURSIVE search_tree(id, path) AS (
        SELECT id, ARRAY[id]
        FROM #{table_name}
        WHERE id = #{instance.id}
      UNION ALL
        SELECT #{table_name}.id, path || #{table_name}.id
        FROM search_tree
        JOIN #{table_name} ON #{table_name}.parent_id = search_tree.id
        WHERE NOT #{table_name}.id = ANY(path)
    )
    SELECT id FROM search_tree ORDER BY path
  SQL
end