7

我有一个如图所示的方法:

def all_pages_and_its_n_level_child

     @parent_pages = Page.where(:parent_id => params[:page_id])
     #this will give me all child of this page
     for page in @parent_pages
          child_exists=Page.where(:parent_id=>page.id)
          #this will give all children of that page
          #*I want to make this loop further so that i can check to N-levels,
          #this is only for two levels*
     end


end  
4

3 回答 3

8

在现代 RDB 上,递归 CTE 可用于处理递归结构。

class Page < ApplicationRecord; end

Page.find_by_sql(
  "WITH RECURSIVE r AS (
     #{Page.where(id: 2).to_sql}
     UNION ALL
     #{Page.joins('JOIN r').where('r.id = pages.parent_id').to_sql})
   SELECT * FROM r")

#  Page Load (0.7ms)  WITH RECURSIVE r AS (
#     SELECT `pages`.* FROM `pages` WHERE `pages`.`id` = 2
#     UNION ALL
#     SELECT `pages`.* FROM `pages` JOIN r WHERE (r.id = pages.parent_id))                                                              
#   SELECT * FROM r
#    => [#<Page id: 2, parent_id: 1, created_at: "2018-08-21 15:00:43", updated_at: "2018-08-21 15:00:43">, #<Page id: 3, parent_id: 2, created_at: "2018-08-21 15:00:50", updated_at: "2018-08-21 15:00:50">]

据我所知,mysql、postgres、sqlite3都支持递归CTE。


编辑@2020/12/17

在 postgresql 上,您需要具备以下条件:

Page.find_by_sql(
  "WITH RECURSIVE r AS (
     #{Page.where(id: 2).to_sql}
   UNION ALL
     #{Page.joins('JOIN r ON r.id = pages.parent_id').to_sql})
   SELECT * FROM r")

(感谢@Dan 指出)

于 2018-08-21T15:04:05.827 回答
3

这是一些示例(未经测试!但它会给你一些线索):

def all_children(children_array = [])
  children = Page.where(parent_id: self.id)
  children_array += children.all
  children.each do |child|
    child.all_children(children_array)
  end
  children_array
end

所以这是递归,它将尝试从父级中找到所有子级(也嵌套)。我知道它非常丑陋且效率低下,但我希望 ii 能给您提供有关查找嵌套元素的线索。

于 2012-07-26T08:04:07.623 回答
1

这是一个恰当的例子。我用谷歌搜索了这个因为我懒得去想它,但是因为我在这里找到了这个,所以我决定正确地做。下面是一个代码,您可以使用默认方式进行 Rails 关联。

def all_children(children_array = [])
    children_array += self.children
    children.each do |child|
        return child.all_children(children_array)
    end
    return children_array
end

请注意 there return的两种用途。如果你错过了内部的,你最终只会得到一层深的树。

干杯!

于 2015-03-29T14:30:04.363 回答