# File lib/awesome_nested_set/model.rb, line 109 def primary_id(target = self) target[primary_column_name] end
module CollectiveIdea::Acts::NestedSet::Model
Public Instance Methods
Returns true is this is a child node
# File lib/awesome_nested_set/model.rb, line 129 def child? !root? end
Returns true if this is the end of a branch.
# File lib/awesome_nested_set/model.rb, line 134 def leaf? persisted? && right.to_i - left.to_i == 1 end
Value of the left column
# File lib/awesome_nested_set/model.rb, line 114 def left(target = self) target[left_column_name] 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, line 141 def nested_set_scope(options = {}) if (scopes = Array(acts_as_nested_set_options[:scope])).any? options[:conditions] = scopes.inject({}) do |conditions,attr| conditions.merge attr => self[attr] end end self.class.base_class.unscoped.nested_set_scope options 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, line 156 def nested_set_scope_without_default_scope(*args) self.class.unscoped do nested_set_scope(*args) end 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, line 105 def parent_id(target = self) target[parent_column_name] end
Value of the right column
# File lib/awesome_nested_set/model.rb, line 119 def right(target = self) target[right_column_name] end
Returns true if this is a root node.
# File lib/awesome_nested_set/model.rb, line 124 def root? parent_id.nil? end
# File lib/awesome_nested_set/model.rb, line 162 def to_text self_and_descendants.map do |node| "#{'*'*(node.level+1)} #{node.primary_id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})" end.join("\n") end
Protected Instance Methods
# File lib/awesome_nested_set/model.rb, line 228 def change_descendants_depth!(diff) if !leaf? && diff != 0 sign = "++-"[diff <=> 0] descendants.update_all("#{quoted_depth_column_name} = #{quoted_depth_column_name} #{sign} #{diff.abs}") end end
# File lib/awesome_nested_set/model.rb, line 180 def has_depth_column? nested_set_scope.column_names.map(&:to_s).include?(depth_column_name.to_s) end
reload left, right, and parent
# File lib/awesome_nested_set/model.rb, line 242 def reload_nested_set reload( :select => "#{quoted_left_column_full_name}, #{quoted_right_column_full_name}, #{quoted_parent_column_full_name}", :lock => true ) end
# File lib/awesome_nested_set/model.rb, line 249 def reload_target(target, position) if target.is_a? self.class.base_class target.reload elsif position != :root nested_set_scope.where(primary_column_name => target).first! end end
# File lib/awesome_nested_set/model.rb, line 190 def right_most_bound @right_most_bound ||= begin return 0 if right_most_node.nil? right_most_node.lock! right_most_node[right_column_name] || 0 end end
# File lib/awesome_nested_set/model.rb, line 184 def right_most_node @right_most_node ||= nested_set_scope( :order => "#{quoted_right_column_full_name} desc" ).first end
# File lib/awesome_nested_set/model.rb, line 235 def set_default_left_and_right # adds the new node to the right of all existing nodes self[left_column_name] = right_most_bound + 1 self[right_column_name] = right_most_bound + 2 end
# File lib/awesome_nested_set/model.rb, line 199 def set_depth! return unless has_depth_column? in_tenacious_transaction do reload update_depth(level) end end
# File lib/awesome_nested_set/model.rb, line 208 def set_depth_for_self_and_descendants! return unless has_depth_column? in_tenacious_transaction do reload self_and_descendants.select(primary_column_name).lock(true) old_depth = self[depth_column_name] || 0 new_depth = level update_depth(new_depth) change_descendants_depth!(new_depth - old_depth) new_depth end end
# File lib/awesome_nested_set/model.rb, line 175 def store_new_parent @move_to_new_parent_id = send("#{parent_column_name}_changed?") ? parent_id : false true # force callback to return true end
# File lib/awesome_nested_set/model.rb, line 222 def update_depth(depth) nested_set_scope.primary_key_scope(primary_id). update_all(["#{quoted_depth_column_name} = ?", depth]) self[depth_column_name] = depth end
# File lib/awesome_nested_set/model.rb, line 170 def without_self(scope) return scope if new_record? scope.where(["#{self.class.quoted_table_name}.#{self.class.quoted_primary_column_name} != ?", self.primary_id]) end