Class: RecursiveTreeScopes::Scopes

Inherits:
Object
  • Object
show all
Defined in:
lib/activerecord-recursive_tree_scopes.rb

Class Method Summary collapse

Class Method Details

.ancestors_for(instance, key) ⇒ Object



34
35
36
# File 'lib/activerecord-recursive_tree_scopes.rb', line 34

def ancestors_for(instance, key)
  instance.class.where("#{instance.class.table_name}.id IN (#{ancestors_sql_for instance, key})").order("#{instance.class.table_name}.id")
end

.ancestors_sql_for(instance, key) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/activerecord-recursive_tree_scopes.rb', line 38

def ancestors_sql_for(instance, key)
  keys = [ key ].flatten
  tree_sql =  <<-SQL
    WITH RECURSIVE ancestor_search(id, #{keys.join ', '}, path) AS (
        SELECT id, #{keys.join ', '}, ARRAY[id]
          FROM #{instance.class.table_name}
          WHERE id = #{instance.id}
      UNION ALL
        SELECT #{instance.class.table_name}.id, #{keys.collect{|key| "#{instance.class.table_name}.#{key}" }.join ', '}, path || #{instance.class.table_name}.id
          FROM #{instance.class.table_name}, ancestor_search
          WHERE #{keys.collect{ |key| "ancestor_search.#{key} = #{instance.class.table_name}.id" }.join ' OR '}
      )
    SELECT id
      FROM ancestor_search
      WHERE id != #{instance.id}
      ORDER BY array_length(path, 1), path
  SQL
  tree_sql.gsub(/\s{2,}/, ' ')
end

.descendants_for(instance, key) ⇒ Object



58
59
60
# File 'lib/activerecord-recursive_tree_scopes.rb', line 58

def descendants_for(instance, key)
  instance.class.where("#{instance.class.table_name}.id IN (#{descendants_sql_for instance, key})").order("#{instance.class.table_name}.id")
end

.descendants_sql_for(instance, key) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/activerecord-recursive_tree_scopes.rb', line 62

def descendants_sql_for(instance, key)
  keys = [ key ].flatten
  tree_sql =  <<-SQL
    WITH RECURSIVE descendants_search(id, path) AS (
        SELECT id, ARRAY[id]
        FROM #{instance.class.table_name}
        WHERE id = #{instance.id}
      UNION ALL
        SELECT #{instance.class.table_name}.id, path || #{instance.class.table_name}.id
        FROM descendants_search
        JOIN #{instance.class.table_name}
        ON #{keys.collect{ |key| "descendants_search.id = #{instance.class.table_name}.#{key}" }.join ' OR '}
        WHERE NOT #{instance.class.table_name}.id = ANY(path)
    )
    SELECT id
      FROM descendants_search
      WHERE id != #{instance.id}
      ORDER BY array_length(path, 1), path
  SQL
  tree_sql.gsub(/\s{2,}/, ' ')
end