-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Erik Dahlstrand
committed
Oct 9, 2009
0 parents
commit 57e4c98
Showing
8 changed files
with
453 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
README.rdoc | ||
lib/**/*.rb | ||
bin/* | ||
features/**/*.feature | ||
LICENSE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
*.sw? | ||
.DS_Store | ||
coverage | ||
rdoc | ||
pkg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
= ActsAsTree | ||
|
||
Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children | ||
association. This requires that you have a foreign key column, which by default is called +parent_id+. | ||
|
||
== Install | ||
|
||
gem install acts_as_tree --source http://gemcutter.org | ||
|
||
== Example | ||
|
||
class Category < ActiveRecord::Base | ||
acts_as_tree :order => "name" | ||
end | ||
|
||
Example: | ||
root | ||
\_ child1 | ||
\_ subchild1 | ||
\_ subchild2 | ||
|
||
root = Category.create("name" => "root") | ||
child1 = root.children.create("name" => "child1") | ||
subchild1 = child1.children.create("name" => "subchild1") | ||
|
||
root.parent # => nil | ||
child1.parent # => root | ||
root.children # => [child1] | ||
root.children.first.children.first # => subchild1 | ||
|
||
Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
require 'rubygems' | ||
require 'rake' | ||
|
||
begin | ||
require 'jeweler' | ||
Jeweler::Tasks.new do |gem| | ||
gem.name = "acts_as_tree" | ||
gem.summary = %Q{Gem version of acts_as_tree Rails plugin.} | ||
gem.description = %Q{Specify this acts_as extension if you want to model a tree structure by providing a parent association and a children association.} | ||
gem.email = "erik.dahlstrand@gmail.com" | ||
gem.homepage = "http://github.com/erdah/acts_as_tree" | ||
gem.authors = ["Erik Dahlstrand", "Rails Core"] | ||
end | ||
rescue LoadError | ||
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" | ||
end | ||
|
||
require 'rake/testtask' | ||
Rake::TestTask.new(:test) do |test| | ||
test.libs << 'lib' << 'test' | ||
test.pattern = 'test/**/*_test.rb' | ||
test.verbose = true | ||
end | ||
|
||
begin | ||
require 'rcov/rcovtask' | ||
Rcov::RcovTask.new do |test| | ||
test.libs << 'test' | ||
test.pattern = 'test/**/*_test.rb' | ||
test.verbose = true | ||
end | ||
rescue LoadError | ||
task :rcov do | ||
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov" | ||
end | ||
end | ||
|
||
task :test => :check_dependencies | ||
|
||
task :default => :test | ||
|
||
require 'rake/rdoctask' | ||
Rake::RDocTask.new do |rdoc| | ||
if File.exist?('VERSION') | ||
version = File.read('VERSION') | ||
else | ||
version = "" | ||
end | ||
|
||
rdoc.rdoc_dir = 'rdoc' | ||
rdoc.title = "acts_as_tree #{version}" | ||
rdoc.rdoc_files.include('README*') | ||
rdoc.rdoc_files.include('lib/**/*.rb') | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
0.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Generated by jeweler | ||
# DO NOT EDIT THIS FILE | ||
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec` | ||
# -*- encoding: utf-8 -*- | ||
|
||
Gem::Specification.new do |s| | ||
s.name = %q{acts_as_tree} | ||
s.version = "0.1.0" | ||
|
||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= | ||
s.authors = ["Erik Dahlstrand", "Rails Core"] | ||
s.date = %q{2009-10-09} | ||
s.description = %q{Specify this acts_as extension if you want to model a tree structure by providing a parent association and a children association.} | ||
s.email = %q{erik.dahlstrand@gmail.com} | ||
s.extra_rdoc_files = [ | ||
"README.rdoc" | ||
] | ||
s.files = [ | ||
".gitignore", | ||
"README.rdoc", | ||
"Rakefile", | ||
"VERSION", | ||
"acts_as_tree.gemspec", | ||
"lib/acts_as_tree.rb", | ||
"test/acts_as_tree_test.rb" | ||
] | ||
s.homepage = %q{http://github.com/erdah/acts_as_tree} | ||
s.rdoc_options = ["--charset=UTF-8"] | ||
s.require_paths = ["lib"] | ||
s.rubygems_version = %q{1.3.5} | ||
s.summary = %q{Gem version of acts_as_tree Rails plugin.} | ||
s.test_files = [ | ||
"test/acts_as_tree_test.rb" | ||
] | ||
|
||
if s.respond_to? :specification_version then | ||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION | ||
s.specification_version = 3 | ||
|
||
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then | ||
else | ||
end | ||
else | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
module ActsAsTree | ||
def self.included(base) | ||
base.extend(ClassMethods) | ||
end | ||
|
||
# Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children | ||
# association. This requires that you have a foreign key column, which by default is called +parent_id+. | ||
# | ||
# class Category < ActiveRecord::Base | ||
# acts_as_tree :order => "name" | ||
# end | ||
# | ||
# Example: | ||
# root | ||
# \_ child1 | ||
# \_ subchild1 | ||
# \_ subchild2 | ||
# | ||
# root = Category.create("name" => "root") | ||
# child1 = root.children.create("name" => "child1") | ||
# subchild1 = child1.children.create("name" => "subchild1") | ||
# | ||
# root.parent # => nil | ||
# child1.parent # => root | ||
# root.children # => [child1] | ||
# root.children.first.children.first # => subchild1 | ||
# | ||
# In addition to the parent and children associations, the following instance methods are added to the class | ||
# after calling <tt>acts_as_tree</tt>: | ||
# * <tt>siblings</tt> - Returns all the children of the parent, excluding the current node (<tt>[subchild2]</tt> when called on <tt>subchild1</tt>) | ||
# * <tt>self_and_siblings</tt> - Returns all the children of the parent, including the current node (<tt>[subchild1, subchild2]</tt> when called on <tt>subchild1</tt>) | ||
# * <tt>ancestors</tt> - Returns all the ancestors of the current node (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>) | ||
# * <tt>root</tt> - Returns the root of the current node (<tt>root</tt> when called on <tt>subchild2</tt>) | ||
module ClassMethods | ||
# Configuration options are: | ||
# | ||
# * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+) | ||
# * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet. | ||
# * <tt>counter_cache</tt> - keeps a count in a +children_count+ column if set to +true+ (default: +false+). | ||
def acts_as_tree(options = {}) | ||
configuration = { :foreign_key => "parent_id", :order => nil, :counter_cache => nil } | ||
configuration.update(options) if options.is_a?(Hash) | ||
|
||
belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache] | ||
has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => :destroy | ||
|
||
class_eval <<-EOV | ||
include ActsAsTree::InstanceMethods | ||
def self.roots | ||
find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}}) | ||
end | ||
def self.root | ||
find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}}) | ||
end | ||
EOV | ||
end | ||
end | ||
|
||
module InstanceMethods | ||
# Returns list of ancestors, starting from parent until root. | ||
# | ||
# subchild1.ancestors # => [child1, root] | ||
def ancestors | ||
node, nodes = self, [] | ||
nodes << node = node.parent while node.parent | ||
nodes | ||
end | ||
|
||
# Returns the root node of the tree. | ||
def root | ||
node = self | ||
node = node.parent while node.parent | ||
node | ||
end | ||
|
||
# Returns all siblings of the current node. | ||
# | ||
# subchild1.siblings # => [subchild2] | ||
def siblings | ||
self_and_siblings - [self] | ||
end | ||
|
||
# Returns all siblings and a reference to the current node. | ||
# | ||
# subchild1.self_and_siblings # => [subchild1, subchild2] | ||
def self_and_siblings | ||
parent ? parent.children : self.class.roots | ||
end | ||
end | ||
end | ||
|
||
ActiveRecord::Base.class_eval { include ActsAsTree } |
Oops, something went wrong.