# File lib/awesome_nested_set/model.rb 114 def primary_id(target = self) 115 target[primary_column_name] 116 end
module CollectiveIdea::Acts::NestedSet::Model
Public Instance Methods
Returns true is this is a child node
# File lib/awesome_nested_set/model.rb 134 def child? 135 !root? 136 end
Returns true if this is the end of a branch.
# File lib/awesome_nested_set/model.rb 139 def leaf? 140 persisted? && right.to_i - left.to_i == 1 141 end
Value of the left column
# File lib/awesome_nested_set/model.rb 119 def left(target = self) 120 target[left_column_name] 121 end
All nested set queries should use this nested_set_scope
, which performs finds on the base ActiveRecord class, using the :scope declared in the acts_as_nested_set declaration.
# File lib/awesome_nested_set/model.rb 146 def nested_set_scope(options = {}) 147 add_scope_conditions_to_options(options) 148 149 self.class.base_class.default_scoped.nested_set_scope options 150 end
Separate an other ‘nested_set_scope` for unscoped model because normal query still need activerecord `default_scope` Only activerecord callbacks need unscoped model to handle the nested set records And class level `nested_set_scope` seems just for query `root` `child` .. etc I think we don’t have to provide unscoped ‘nested_set_scope` in class level.
# File lib/awesome_nested_set/model.rb 157 def nested_set_scope_without_default_scope(options = {}) 158 add_scope_conditions_to_options(options) 159 160 self.class.base_class.unscoped.nested_set_scope options 161 end
Any instance method that returns a collection makes use of Rails 2.1’s named_scope (which is bundled for Rails 2.0), so it can be treated as a finder.
category.self_and_descendants.count category.ancestors.find(:all, :conditions => "name like '%foo%'")
Value of the parent column
# File lib/awesome_nested_set/model.rb 110 def parent_id(target = self) 111 target[parent_column_name] 112 end
Value of the right column
# File lib/awesome_nested_set/model.rb 124 def right(target = self) 125 target[right_column_name] 126 end
Returns true if this is a root node.
# File lib/awesome_nested_set/model.rb 129 def root? 130 parent_id.nil? 131 end
# File lib/awesome_nested_set/model.rb 163 def to_text 164 self_and_descendants.map do |node| 165 "#{'*'*(node.level+1)} #{node.primary_id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})" 166 end.join("\n") 167 end
Protected Instance Methods
# File lib/awesome_nested_set/model.rb 171 def add_scope_conditions_to_options(options) 172 scopes = scope_column_names 173 return if scopes.empty? 174 175 options[:conditions] = scopes.map { |attr| [attr, self[attr] ] }.to_h 176 end
# File lib/awesome_nested_set/model.rb 235 def change_descendants_depth!(diff) 236 if !leaf? && diff != 0 237 sign = "++-"[diff <=> 0] 238 descendants.update_all("#{quoted_depth_column_name} = #{quoted_depth_column_name} #{sign} #{diff.abs}") 239 end 240 end
# File lib/awesome_nested_set/model.rb 188 def has_depth_column? 189 nested_set_scope.column_names.map(&:to_s).include?(depth_column_name.to_s) 190 end
reload left, right, and parent
# File lib/awesome_nested_set/model.rb 263 def reload_nested_set 264 reload( 265 :select => "#{quoted_left_column_full_name}, #{quoted_right_column_full_name}, #{quoted_parent_column_full_name}", 266 :lock => true 267 ) 268 end
# File lib/awesome_nested_set/model.rb 270 def reload_target(target, position) 271 if target.is_a? self.class.base_class 272 target.reload 273 elsif position != :root 274 nested_set_scope_without_default_scope.where(primary_column_name => target).first! 275 end 276 end
# File lib/awesome_nested_set/model.rb 198 def right_most_bound 199 @right_most_bound ||= begin 200 return 0 if right_most_node.nil? 201 202 right_most_node.lock! 203 right_most_node[right_column_name] || 0 204 end 205 end
# File lib/awesome_nested_set/model.rb 192 def right_most_node 193 @right_most_node ||= nested_set_scope_without_default_scope( 194 :order => {right_column_name => :desc} 195 ).first 196 end
# File lib/awesome_nested_set/model.rb 256 def set_default_left_and_right 257 # adds the new node to the right of all existing nodes 258 self[left_column_name] = right_most_bound + 1 259 self[right_column_name] = right_most_bound + 2 260 end
# File lib/awesome_nested_set/model.rb 207 def set_depth! 208 return unless has_depth_column? 209 210 in_tenacious_transaction do 211 update_depth(level) 212 end 213 end
# File lib/awesome_nested_set/model.rb 215 def set_depth_for_self_and_descendants! 216 return unless has_depth_column? 217 218 in_tenacious_transaction do 219 reload 220 self_and_descendants.select(primary_column_name).lock(true) 221 old_depth = self[depth_column_name] || 0 222 new_depth = level 223 update_depth(new_depth) 224 change_descendants_depth!(new_depth - old_depth) 225 new_depth 226 end 227 end
# File lib/awesome_nested_set/model.rb 183 def store_new_parent 184 @move_to_new_parent_id = send("#{parent_column_name}_changed?") ? parent_id : false 185 true # force callback to return true 186 end
# File lib/awesome_nested_set/model.rb 242 def update_counter_cache 243 return unless acts_as_nested_set_options[:counter_cache] 244 245 # Decrease the counter for all old parents 246 if old_parent = self.parent 247 old_parent.class.decrement_counter(acts_as_nested_set_options[:counter_cache], old_parent) 248 end 249 250 # Increase the counter for all new parents 251 if new_parent = self.reload.parent 252 new_parent.class.increment_counter(acts_as_nested_set_options[:counter_cache], new_parent) 253 end 254 end
# File lib/awesome_nested_set/model.rb 229 def update_depth(depth) 230 nested_set_scope.primary_key_scope(primary_id). 231 update_all(["#{quoted_depth_column_name} = ?", depth]) 232 self[depth_column_name] = depth 233 end
# File lib/awesome_nested_set/model.rb 178 def without_self(scope) 179 return scope if new_record? 180 scope.where(["#{self.class.quoted_table_name}.#{self.class.quoted_primary_column_name} != ?", self.primary_id]) 181 end