Module: ActsAsSaneTree::SingletonMethods
- Defined in:
- lib/acts_as_sane_tree/singleton_methods.rb
Instance Method Summary collapse
-
#nodes_and_descendants(*args) ⇒ Object
(also: #nodes_and_descendents)
- args
- ActiveRecord models or IDs - Symbols: :raw, :no_self - Hash: => n, :at_depth => n Returns provided nodes plus all descendants of provided nodes in nested Hash where keys are nodes and values are children :raw
- return value will be flat array :no_self
- Do not include provided nodes in result Hash: :to_depth
- Only retrieve values to given depth :at_depth
-
Only retrieve values from given depth.
-
#nodes_within(src, chk) ⇒ Object
- src
- Array of nodes chk
-
Array of nodes Return all nodes that are within both chk and src.
-
#nodes_within?(src, chk) ⇒ Boolean
- src
- Array of nodes chk
-
Array of nodes Return true if any nodes within chk are found within src.
-
#rails_3? ⇒ Boolean
Check if we are in rails 3.
-
#root ⇒ Object
Return first root node.
-
#roots ⇒ Object
Return all root nodes.
Instance Method Details
#nodes_and_descendants(*args) ⇒ Object Also known as: nodes_and_descendents
- args
-
ActiveRecord models or IDs - Symbols: :raw, :no_self - Hash: => n, :at_depth => n
Returns provided nodes plus all descendants of provided nodes in nested Hash where keys are nodes and values are children
- :raw
-
return value will be flat array
- :no_self
-
Do not include provided nodes in result
Hash:
:to_depth:: Only retrieve values to given depth
:at_depth:: Only retrieve values from given depth
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/acts_as_sane_tree/singleton_methods.rb', line 87 def nodes_and_descendants(*args) raw = args.delete(:raw) no_self = args.delete(:no_self) at_depth = nil depth = nil hash = args.detect{|x|x.is_a?(Hash)} if(hash) args.delete(hash) depth = hash[:depth] || hash[:to_depth] at_depth = hash[:at_depth] end depth ||= configuration[:max_depth].to_i depth_restriction = "WHERE crumbs.depth + 1 < #{depth}" if depth depth_clause = nil if(at_depth) depth_clause = "#{configuration[:class].table_name}.depth + 1 = #{at_depth.to_i + 1}" elsif(depth) depth_clause = "#{configuration[:class].table_name}.depth + 1 < #{depth.to_i + 2}" end base_ids = args.map{|x| x.is_a?(ActiveRecord::Base) ? x.id : x.to_i} query = "(WITH RECURSIVE crumbs AS ( SELECT #{configuration[:class].table_name}.*, #{no_self ? -1 : 0} AS depth FROM #{configuration[:class].table_name} WHERE #{base_ids.empty? ? 'parent_id IS NULL' : "id in (#{base_ids.join(', ')})"} UNION ALL SELECT alias1.*, crumbs.depth + 1 FROM crumbs JOIN #{configuration[:class].table_name} alias1 on alias1.parent_id = crumbs.id #{depth_restriction} ) SELECT * FROM crumbs) as #{configuration[:class].table_name}" q = nil if(rails_3?) q = configuration[:class].from( query ).where( "#{configuration[:class].table_name}.depth >= 0" ) if(depth_clause) q = q.where(depth_clause) end if(configuration[:order].present?) q = q.order(configuration[:order]) end else q = configuration[:class].scoped( :from => query, :conditions => "#{configuration[:class].table_name}.depth >= 0" ) if(configuration[:order].present?) q = q.scoped(:order => configuration[:order]) end if(depth_clause) q = q.scoped(:conditions => depth_clause) end end unless(rails_3?) q = q.scoped(scope(:find)) end unless(raw) res = ActiveSupport::OrderedHash.new cache = ActiveSupport::OrderedHash.new q.all.each do |item| res[item] = ActiveSupport::OrderedHash.new cache[item] = res[item] end cache.each_pair do |item, values| if(cache[item.parent]) cache[item.parent][item] = values res.delete(item) end end res else q end end |
#nodes_within(src, chk) ⇒ Object
- src
-
Array of nodes
- chk
-
Array of nodes
Return all nodes that are within both chk and src
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/acts_as_sane_tree/singleton_methods.rb', line 59 def nodes_within(src, chk) s = (src.is_a?(Array) ? src : [src]).map{|x|x.is_a?(ActiveRecord::Base) ? x.id : x.to_i} c = (chk.is_a?(Array) ? chk : [chk]).map{|x|x.is_a?(ActiveRecord::Base) ? x.id : x.to_i} if(s.empty? || c.empty?) nil else query = "(WITH RECURSIVE crumbs AS ( SELECT #{configuration[:class].table_name}.*, 0 AS depth FROM #{configuration[:class].table_name} WHERE id in (#{s.join(', ')}) UNION ALL SELECT alias1.*, crumbs.depth + 1 FROM crumbs JOIN #{configuration[:class].table_name} alias1 on alias1.parent_id = crumbs.id #{configuration[:max_depth] ? "WHERE crumbs.depth + 1 < #{configuration[:max_depth].to_i}" : ''} ) SELECT * FROM crumbs WHERE id in (#{c.join(', ')})) as #{configuration[:class].table_name}" if(rails_3?) configuration[:class].from(query) else configuration[:class].scoped(:from => query) end end end |
#nodes_within?(src, chk) ⇒ Boolean
- src
-
Array of nodes
- chk
-
Array of nodes
Return true if any nodes within chk are found within src
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/acts_as_sane_tree/singleton_methods.rb', line 39 def nodes_within?(src, chk) s = (src.is_a?(Array) ? src : [src]).map{|x|x.is_a?(ActiveRecord::Base) ? x.id : x.to_i} c = (chk.is_a?(Array) ? chk : [chk]).map{|x|x.is_a?(ActiveRecord::Base) ? x.id : x.to_i} if(s.empty? || c.empty?) false else q = configuration[:class].connection.select_all( "WITH RECURSIVE crumbs AS ( SELECT #{configuration[:class].table_name}.*, 0 AS level FROM #{configuration[:class].table_name} WHERE id in (#{s.join(', ')}) UNION ALL SELECT alias1.*, crumbs.level + 1 FROM crumbs JOIN #{configuration[:class].table_name} alias1 on alias1.parent_id = crumbs.id ) SELECT count(*) as count FROM crumbs WHERE id in (#{c.join(', ')})" ) q.first['count'].to_i > 0 end end |
#rails_3? ⇒ Boolean
Check if we are in rails 3
5 6 7 |
# File 'lib/acts_as_sane_tree/singleton_methods.rb', line 5 def rails_3? @is_3 ||= !defined?(Arel).nil? end |
#root ⇒ Object
Return first root node
24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/acts_as_sane_tree/singleton_methods.rb', line 24 def root if(rails_3?) configuration[:class].where("#{configuration[:foreign_key]} IS NULL").order(configuration[:order]).first else configuration[:class].find( :first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => configuration[:order] ) end end |
#roots ⇒ Object
Return all root nodes
10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/acts_as_sane_tree/singleton_methods.rb', line 10 def roots if(rails_3?) configuration[:class].where( "#{configuration[:foreign_key]} IS NULL" ).order(configuration[:order]) else configuration[:class].scoped( :conditions => "#{configuration[:foreign_key]} IS NULL", :order => configuration[:order] ) end end |