how to make a Recursive function in rails,that will return all CHILDREN of a parent,and children of all CHILDREN AND SO ON....TO N-LEVELS
On modern RDBs, recursive CTE can be used to handle recursive structure.
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">]
As far as I know, mysql, postgres, sqlite3 supports recursive CTE.
EDIT@2020/12/17
On postgresql, you need to have following:
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")
(Thanks to @Dan for pointing out)
Here is some sample (it is not tested! But it will give you some clue):
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
So this is recursion that will try to find all children (nested too) from parent. I know that it is very ugly and unefficient, but I hope ii will give you a clue about finding nested elements.