Skip to content

Instantly share code, notes, and snippets.

@tpinto
Created March 10, 2011 19:13
Show Gist options
  • Save tpinto/864699 to your computer and use it in GitHub Desktop.
Save tpinto/864699 to your computer and use it in GitHub Desktop.
awesome nested set, .rebuild! method fully commented (WIP)
# Rebuilds the left & rights if unset or invalid. Also very useful for converting from acts_as_tree.
def rebuild!
# Don't rebuild a valid tree.
return true if valid?
# defines the method _scope_ to return _nil_
scope = lambda{|node|}
# if the _:scope_ option was set, we must use it
if acts_as_nested_set_options[:scope]
# redefine the _scope_ method
scope = lambda{|node|
# scope_column_names is an Array of scopes
scope_column_names.inject(""){|str, column_name|
# we go through all scopes and add them to a string that will be used on _:conditions_
# example: if _:scope_ was defined as _:company_, _:company_id_ will be used and this will return the following string:
# "AND company_id = 5"
# (ignoring db quoting stuff and assuming the passed node's company_id is _5_)
str << "AND #{connection.quote_column_name(column_name)} = #{connection.quote(node.send(column_name.to_sym))} "
}
}
end
indices = {}
# define the +set_left_and_rights+ method (returns true if the +node.save!+ succeeds)
set_left_and_rights = lambda do |node|
# set left
node[left_column_name] = indices[scope.call(node)] += 1
# find sub-nodes and set left/right for them
find(
:all,
:conditions => ["#{quoted_parent_column_name} = ? #{scope.call(node)}", node],
:order => "#{quoted_left_column_name}, #{quoted_right_column_name}, id"
).each{|n| set_left_and_rights.call(n) }
# set right
node[right_column_name] = indices[scope.call(node)] += 1
# save node
node.save!
end
# Find root node(s)
root_nodes = find(
:all,
:conditions => "#{quoted_parent_column_name} IS NULL",
:order => "#{quoted_left_column_name}, #{quoted_right_column_name}, id"
).each do |root_node|
# setup index for this scope
indices[scope.call(root_node)] ||= 0
set_left_and_rights.call(root_node)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment