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
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 76 77 |
# File 'lib/edge/forest.rb', line 49 def find_forest manager = recursive_manager.project(Arel.star) manager.order(forest_order) if forest_order bind_values = current_scope ? current_scope.bind_values : [] records = find_by_sql manager.to_sql, bind_values 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.
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/edge/forest.rb', line 83 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
97 98 99 100 101 102 |
# File 'lib/edge/forest.rb', line 97 def with_descendants manager = recursive_manager.project(arel_table[:id]) scope = unscoped.where(arel_table[:id].in manager) scope.bind_values = current_scope.bind_values if current_scope scope end |