Module: Edge::Forest::ClassMethods
- Defined in:
- lib/edge/forest.rb
Instance Method Summary collapse
-
#find_forest ⇒ Object
Finds entire forest and preloads all associations.
-
#find_tree(id_or_ids) ⇒ Object
Finds an a tree or trees by id.
-
#with_descendants ⇒ Object
Returns a new scope that includes previously scoped records and their descendants by subsuming the previous scope into a subquery.
Instance Method Details
#find_forest ⇒ Object
Finds entire forest and preloads all associations. It can be used at the end of an ActiveRecord finder chain.
Example:
# loads all locations
Location.find_forest
# loads all nodes with matching names and all there descendants
Category.where(:name => %w{clothing books electronics}).find_forest
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/edge/forest.rb', line 48 def find_forest manager = recursive_manager.project(Arel.star) manager.order(forest_order) if forest_order records = find_by_sql manager.to_sql records_by_id = records.each_with_object({}) { |r, h| h[r.id] = r } # Set all children associations to an empty array records.each do |r| children_association = r.association(:children) children_association.target = [] end top_level_records = [] records.each do |r| parent = records_by_id[r[forest_foreign_key]] if parent r.association(:parent).target = parent parent.association(:children).target.push(r) else top_level_records.push(r) end end top_level_records end |
#find_tree(id_or_ids) ⇒ Object
Finds an a tree or trees by id.
If any requested ids are not found it raises ActiveRecord::RecordNotFound.
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/edge/forest.rb', line 81 def find_tree(id_or_ids) trees = where(:id => id_or_ids).find_forest if id_or_ids.kind_of?(Array) raise ActiveRecord::RecordNotFound unless trees.size == id_or_ids.size trees else raise ActiveRecord::RecordNotFound if trees.empty? trees.first end end |
#with_descendants ⇒ Object
Returns a new scope that includes previously scoped records and their descendants by subsuming the previous scope into a subquery
Only where scopes can precede this in a scope chain
95 96 97 98 |
# File 'lib/edge/forest.rb', line 95 def with_descendants manager = recursive_manager.project(arel_table[:id]) unscoped.where("#{table_name}.id in (#{manager.to_sql})") end |