module PostgresTree::ActiveRecordConcern
Public Instance Methods
ancestors()
click to toggle source
Get all ancestors
Example:
> parent.ancestors => [#<Role id: 1, name: "Grandparent", parent_id: nil>]
# File lib/postgres_tree/concerns/model/active_record.rb, line 17 def ancestors self_and_ancestors - [self] end
descendents()
click to toggle source
Get all descendents
Example:
> parent.descendents => [#<Role id: 3, name: "Child", parent_id: 2>]
# File lib/postgres_tree/concerns/model/active_record.rb, line 37 def descendents self_and_descendents - [self] end
self_and_ancestors()
click to toggle source
Get all ancestors and include self in the returned result
Example:
> parent.self_and_ancestors => #<ActiveRecord::Relation [#<Role id: 1, name: "Grandparent", parent_id: nil>, #<Role id: 2, name: "Parent", parent_id: 1>]>
# File lib/postgres_tree/concerns/model/active_record.rb, line 27 def self_and_ancestors self_and_ancestors_for(self) end
self_and_descendents()
click to toggle source
Get all descendents and include self in the returned result
Example:
> parent.self_and_descendents => #<ActiveRecord::Relation [#<Role id: 2, name: "Parent", parent_id: 1>, #<Role id: 3, name: "Child", parent_id: 2>]>
# File lib/postgres_tree/concerns/model/active_record.rb, line 47 def self_and_descendents self_and_descendents_for(self) end
Private Instance Methods
method_missing(method, *args, &block)
click to toggle source
Calls superclass method
# File lib/postgres_tree/concerns/model/active_record.rb, line 53 def method_missing(method, *args, &block) if method.to_s =~ /\A(.+)_include\?\z/ self.send($1.to_sym).include? *args.first else super end end
respond_to_missing?(method, include_private_methods = false)
click to toggle source
Calls superclass method
# File lib/postgres_tree/concerns/model/active_record.rb, line 61 def respond_to_missing?(method, include_private_methods = false) method.to_s =~ /\A(.+)_include\?\z/ || super end
self_and_ancestors_for(instance)
click to toggle source
Ancestors
# File lib/postgres_tree/concerns/model/active_record.rb, line 66 def self_and_ancestors_for(instance) self.class.where("#{self.class.table_name}.id IN (#{self_and_ancestors_sql_for(instance)})") end
self_and_ancestors_sql_for(instance)
click to toggle source
# File lib/postgres_tree/concerns/model/active_record.rb, line 69 def self_and_ancestors_sql_for(instance) tree_sql = <<-SQL WITH RECURSIVE search_tree(id, parent_id, path) AS ( SELECT id, parent_id, ARRAY[id] FROM #{self.class.table_name} WHERE id = #{instance.id} UNION ALL SELECT #{self.class.table_name}.id, #{self.class.table_name}.parent_id, path || #{self.class.table_name}.id FROM search_tree JOIN #{self.class.table_name} ON #{self.class.table_name}.id = search_tree.parent_id WHERE NOT #{self.class.table_name}.id = ANY(path) ) SELECT id FROM search_tree ORDER BY path DESC SQL end
self_and_descendents_for(instance)
click to toggle source
Descendents
# File lib/postgres_tree/concerns/model/active_record.rb, line 86 def self_and_descendents_for(instance) self.class.where("#{self.class.table_name}.id IN (#{self_and_descendents_sql_for(instance)})") end
self_and_descendents_sql_for(instance)
click to toggle source
# File lib/postgres_tree/concerns/model/active_record.rb, line 89 def self_and_descendents_sql_for(instance) tree_sql = <<-SQL WITH RECURSIVE search_tree(id, path) AS ( SELECT id, ARRAY[id] FROM #{self.class.table_name} WHERE id = #{instance.id} UNION ALL SELECT #{self.class.table_name}.id, path || #{self.class.table_name}.id FROM search_tree JOIN #{self.class.table_name} ON #{self.class.table_name}.parent_id = search_tree.id WHERE NOT #{self.class.table_name}.id = ANY(path) ) SELECT id FROM search_tree ORDER BY path SQL end