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をサポートしています。


EDIT @ 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

したがって、これは、親からすべての子(ネストされている)を見つけようとする再帰です。非常に醜く非効率的であることは知っていますが、ネストされた要素を見つけるための手がかりが得られることを願っています。

于 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

そこに戻るの2つの使用法に注意してください。内側のものを見逃すと、1レベルの深い木になってしまいます。

乾杯!

于 2015-03-29T14:30:04.363 に答える