acts_as_tree 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +0 -1
- data/README.md +12 -6
- data/Rakefile +1 -1
- data/acts_as_tree.gemspec +1 -1
- data/lib/acts_as_tree.rb +149 -3
- data/lib/acts_as_tree/active_record/acts/tree.rb +7 -140
- data/lib/acts_as_tree/version.rb +2 -6
- data/test/acts_as_tree_test.rb +1 -1
- metadata +8 -8
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,15 @@
|
|
1
|
-
[](
|
1
|
+
# ActsAsTree [][travis] [][gemnasium]
|
2
|
+
[travis]: (http://travis-ci.org/amerine/acts_as_tree)
|
3
|
+
[gemnasium]: (https://gemnasium.com/amerine/acts_as_tree)
|
2
4
|
|
3
|
-
# ActsAsTree
|
4
5
|
|
5
|
-
|
6
|
+
ActsAsTree extends ActiveRecord to add simple support for organizing items into
|
6
7
|
parent–children relationships.
|
7
8
|
|
8
9
|
## Example
|
9
10
|
|
10
11
|
class Category < ActiveRecord::Base
|
11
|
-
include
|
12
|
+
include ActsAsTree
|
12
13
|
|
13
14
|
acts_as_tree order: "name"
|
14
15
|
end
|
@@ -29,9 +30,14 @@ We no longer support Ruby 1.8 or versions if Rails/ActiveRecord older than 3.0.
|
|
29
30
|
Moving forward we will do our best to support the latest versions of ActiveRecord and Ruby.
|
30
31
|
|
31
32
|
## Change Log
|
32
|
-
|
33
|
+
* 1.1.0 - April 24th, 2012
|
34
|
+
* Deprecate the ActiveRecord::Acts::Tree module in favor of ActsAsTree
|
35
|
+
* 1.0.1 - April 18th, 2012
|
36
|
+
* Include the Railtie for easier loading in Rails. Will reassess the forced module inclusion in the future.
|
37
|
+
* 1.0.0 - April 14th, 2012
|
38
|
+
* Official 1.0 release. Force users to include the ActiveRecord::Acts::Tree module.
|
33
39
|
* 0.2.0 - April 9, 2012
|
34
|
-
*
|
40
|
+
* Rails 3 Support
|
35
41
|
* 0.1.1 - February 3, 2010
|
36
42
|
* Bug Fixes
|
37
43
|
* 0.1.0 - October 9th, 2009
|
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ task :default => :test
|
|
12
12
|
require 'rdoc/task'
|
13
13
|
RDoc::Task.new do |rdoc|
|
14
14
|
require "acts_as_tree/version"
|
15
|
-
version =
|
15
|
+
version = ActsAsTree::VERSION
|
16
16
|
|
17
17
|
rdoc.rdoc_dir = 'rdoc'
|
18
18
|
rdoc.title = "acts_as_tree-rails3 #{version}"
|
data/acts_as_tree.gemspec
CHANGED
@@ -4,7 +4,7 @@ require 'acts_as_tree/version'
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'acts_as_tree'
|
7
|
-
s.version =
|
7
|
+
s.version = ActsAsTree::VERSION
|
8
8
|
s.authors = ['Erik Dahlstrand', 'Rails Core', 'Mark Turner', 'Swanand Pagnis']
|
9
9
|
s.email = ['erik.dahlstrand@gmail.com', 'mark@amerine.net', 'swanand.pagnis@gmail.com']
|
10
10
|
s.homepage = 'https://github.com/amerine/acts_as_tree'
|
data/lib/acts_as_tree.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'acts_as_tree/active_record/acts/tree'
|
2
1
|
require 'acts_as_tree/version'
|
3
2
|
|
4
3
|
module ActsAsTree
|
4
|
+
|
5
5
|
if defined? Rails::Railtie
|
6
6
|
require 'rails'
|
7
7
|
class Railtie < Rails::Railtie
|
@@ -16,8 +16,154 @@ module ActsAsTree
|
|
16
16
|
class Railtie
|
17
17
|
def self.insert
|
18
18
|
if defined?(ActiveRecord)
|
19
|
-
ActiveRecord::Base.send(:include,
|
19
|
+
ActiveRecord::Base.send(:include, ActsAsTree)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
|
+
def self.included(base)
|
25
|
+
base.extend(ClassMethods)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Specify this +acts_as+ extension if you want to model a tree structure
|
29
|
+
# by providing a parent association and a children association. This
|
30
|
+
# requires that you have a foreign key column, which by default is called
|
31
|
+
# +parent_id+.
|
32
|
+
#
|
33
|
+
# class Category < ActiveRecord::Base
|
34
|
+
# include ActiveRecord::Acts:Tree
|
35
|
+
#
|
36
|
+
# acts_as_tree :order => "name"
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# Example:
|
40
|
+
# root
|
41
|
+
# \_ child1
|
42
|
+
# \_ subchild1
|
43
|
+
# \_ subchild2
|
44
|
+
#
|
45
|
+
# root = Category.create("name" => "root")
|
46
|
+
# child1 = root.children.create("name" => "child1")
|
47
|
+
# subchild1 = child1.children.create("name" => "subchild1")
|
48
|
+
#
|
49
|
+
# root.parent # => nil
|
50
|
+
# child1.parent # => root
|
51
|
+
# root.children # => [child1]
|
52
|
+
# root.children.first.children.first # => subchild1
|
53
|
+
#
|
54
|
+
# In addition to the parent and children associations, the following
|
55
|
+
# instance methods are added to the class after calling
|
56
|
+
# <tt>acts_as_tree</tt>:
|
57
|
+
# * <tt>siblings</tt> - Returns all the children of the parent, excluding
|
58
|
+
# the current node (<tt>[subchild2]</tt> when called
|
59
|
+
# on <tt>subchild1</tt>)
|
60
|
+
# * <tt>self_and_siblings</tt> - Returns all the children of the parent,
|
61
|
+
# including the current node (<tt>[subchild1, subchild2]</tt>
|
62
|
+
# when called on <tt>subchild1</tt>)
|
63
|
+
# * <tt>ancestors</tt> - Returns all the ancestors of the current node
|
64
|
+
# (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>)
|
65
|
+
# * <tt>root</tt> - Returns the root of the current node (<tt>root</tt>
|
66
|
+
# when called on <tt>subchild2</tt>)
|
67
|
+
module ClassMethods
|
68
|
+
# Configuration options are:
|
69
|
+
#
|
70
|
+
# * <tt>foreign_key</tt> - specifies the column name to use for tracking
|
71
|
+
# of the tree (default: +parent_id+)
|
72
|
+
# * <tt>order</tt> - makes it possible to sort the children according to
|
73
|
+
# this SQL snippet.
|
74
|
+
# * <tt>counter_cache</tt> - keeps a count in a +children_count+ column
|
75
|
+
# if set to +true+ (default: +false+).
|
76
|
+
def acts_as_tree(options = {})
|
77
|
+
configuration = {
|
78
|
+
foreign_key: "parent_id",
|
79
|
+
order: nil,
|
80
|
+
counter_cache: nil,
|
81
|
+
dependent: :destroy
|
82
|
+
}
|
83
|
+
|
84
|
+
configuration.update(options) if options.is_a?(Hash)
|
85
|
+
|
86
|
+
belongs_to :parent, class_name: name,
|
87
|
+
foreign_key: configuration[:foreign_key],
|
88
|
+
counter_cache: configuration[:counter_cache],
|
89
|
+
inverse_of: :children
|
90
|
+
|
91
|
+
has_many :children, class_name: name,
|
92
|
+
foreign_key: configuration[:foreign_key],
|
93
|
+
order: configuration[:order],
|
94
|
+
dependent: configuration[:dependent],
|
95
|
+
inverse_of: :parent
|
96
|
+
|
97
|
+
class_eval <<-EOV
|
98
|
+
include ActsAsTree::InstanceMethods
|
99
|
+
|
100
|
+
after_update :update_parents_counter_cache
|
101
|
+
|
102
|
+
def self.roots
|
103
|
+
order_option = %Q{#{configuration.fetch :order, "nil"}}
|
104
|
+
|
105
|
+
find(:all, conditions: "#{configuration[:foreign_key]} IS NULL",
|
106
|
+
order: order_option)
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.root
|
110
|
+
order_option = %Q{#{configuration.fetch :order, "nil"}}
|
111
|
+
|
112
|
+
find(:first, conditions: "#{configuration[:foreign_key]} IS NULL",
|
113
|
+
order: order_option)
|
114
|
+
end
|
115
|
+
EOV
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
module InstanceMethods
|
120
|
+
# Returns list of ancestors, starting from parent until root.
|
121
|
+
#
|
122
|
+
# subchild1.ancestors # => [child1, root]
|
123
|
+
def ancestors
|
124
|
+
node, nodes = self, []
|
125
|
+
nodes << node = node.parent while node.parent
|
126
|
+
nodes
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns the root node of the tree.
|
130
|
+
def root
|
131
|
+
node = self
|
132
|
+
node = node.parent while node.parent
|
133
|
+
node
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns all siblings of the current node.
|
137
|
+
#
|
138
|
+
# subchild1.siblings # => [subchild2]
|
139
|
+
def siblings
|
140
|
+
self_and_siblings - [self]
|
141
|
+
end
|
142
|
+
|
143
|
+
# Returns all siblings and a reference to the current node.
|
144
|
+
#
|
145
|
+
# subchild1.self_and_siblings # => [subchild1, subchild2]
|
146
|
+
def self_and_siblings
|
147
|
+
parent ? parent.children : self.class.roots
|
148
|
+
end
|
149
|
+
|
150
|
+
# Returns children (without subchildren) and current node itself.
|
151
|
+
#
|
152
|
+
# root.self_and_children # => [root, child1]
|
153
|
+
def self_and_children
|
154
|
+
[self] + self.children
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def update_parents_counter_cache
|
160
|
+
if self.respond_to?(:children_count) && parent_id_changed?
|
161
|
+
self.class.decrement_counter(:children_count, parent_id_was)
|
162
|
+
self.class.increment_counter(:children_count, parent_id)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Deprecating the following code in the future.
|
169
|
+
require 'acts_as_tree/active_record/acts/tree'
|
@@ -1,147 +1,14 @@
|
|
1
|
+
require 'acts_as_tree'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Acts #:nodoc:
|
3
|
-
module Tree
|
4
|
-
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
end
|
7
|
-
|
8
|
-
# Specify this +acts_as+ extension if you want to model a tree structure
|
9
|
-
# by providing a parent association and a children association. This
|
10
|
-
# requires that you have a foreign key column, which by default is called
|
11
|
-
# +parent_id+.
|
12
|
-
#
|
13
|
-
# class Category < ActiveRecord::Base
|
14
|
-
# include ActiveRecord::Acts:Tree
|
15
|
-
#
|
16
|
-
# acts_as_tree :order => "name"
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# Example:
|
20
|
-
# root
|
21
|
-
# \_ child1
|
22
|
-
# \_ subchild1
|
23
|
-
# \_ subchild2
|
24
|
-
#
|
25
|
-
# root = Category.create("name" => "root")
|
26
|
-
# child1 = root.children.create("name" => "child1")
|
27
|
-
# subchild1 = child1.children.create("name" => "subchild1")
|
28
|
-
#
|
29
|
-
# root.parent # => nil
|
30
|
-
# child1.parent # => root
|
31
|
-
# root.children # => [child1]
|
32
|
-
# root.children.first.children.first # => subchild1
|
33
|
-
#
|
34
|
-
# In addition to the parent and children associations, the following
|
35
|
-
# instance methods are added to the class after calling
|
36
|
-
# <tt>acts_as_tree</tt>:
|
37
|
-
# * <tt>siblings</tt> - Returns all the children of the parent, excluding
|
38
|
-
# the current node (<tt>[subchild2]</tt> when called
|
39
|
-
# on <tt>subchild1</tt>)
|
40
|
-
# * <tt>self_and_siblings</tt> - Returns all the children of the parent,
|
41
|
-
# including the current node (<tt>[subchild1, subchild2]</tt>
|
42
|
-
# when called on <tt>subchild1</tt>)
|
43
|
-
# * <tt>ancestors</tt> - Returns all the ancestors of the current node
|
44
|
-
# (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>)
|
45
|
-
# * <tt>root</tt> - Returns the root of the current node (<tt>root</tt>
|
46
|
-
# when called on <tt>subchild2</tt>)
|
47
|
-
module ClassMethods
|
48
|
-
# Configuration options are:
|
49
|
-
#
|
50
|
-
# * <tt>foreign_key</tt> - specifies the column name to use for tracking
|
51
|
-
# of the tree (default: +parent_id+)
|
52
|
-
# * <tt>order</tt> - makes it possible to sort the children according to
|
53
|
-
# this SQL snippet.
|
54
|
-
# * <tt>counter_cache</tt> - keeps a count in a +children_count+ column
|
55
|
-
# if set to +true+ (default: +false+).
|
56
|
-
def acts_as_tree(options = {})
|
57
|
-
configuration = {
|
58
|
-
foreign_key: "parent_id",
|
59
|
-
order: nil,
|
60
|
-
counter_cache: nil,
|
61
|
-
dependent: :destroy
|
62
|
-
}
|
63
|
-
|
64
|
-
configuration.update(options) if options.is_a?(Hash)
|
65
|
-
|
66
|
-
belongs_to :parent, class_name: name,
|
67
|
-
foreign_key: configuration[:foreign_key],
|
68
|
-
counter_cache: configuration[:counter_cache],
|
69
|
-
inverse_of: :children
|
70
|
-
|
71
|
-
has_many :children, class_name: name,
|
72
|
-
foreign_key: configuration[:foreign_key],
|
73
|
-
order: configuration[:order],
|
74
|
-
dependent: configuration[:dependent],
|
75
|
-
inverse_of: :parent
|
76
|
-
|
77
|
-
class_eval <<-EOV
|
78
|
-
include ActiveRecord::Acts::Tree::InstanceMethods
|
79
|
-
|
80
|
-
after_update :update_parents_counter_cache
|
81
|
-
|
82
|
-
def self.roots
|
83
|
-
order_option = %Q{#{configuration.fetch :order, "nil"}}
|
5
|
+
module Tree
|
6
|
+
include ::ActsAsTree
|
84
7
|
|
85
|
-
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
def self.root
|
90
|
-
order_option = %Q{#{configuration.fetch :order, "nil"}}
|
91
|
-
|
92
|
-
find(:first, conditions: "#{configuration[:foreign_key]} IS NULL",
|
93
|
-
order: order_option)
|
94
|
-
end
|
95
|
-
EOV
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
module InstanceMethods
|
100
|
-
# Returns list of ancestors, starting from parent until root.
|
101
|
-
#
|
102
|
-
# subchild1.ancestors # => [child1, root]
|
103
|
-
def ancestors
|
104
|
-
node, nodes = self, []
|
105
|
-
nodes << node = node.parent while node.parent
|
106
|
-
nodes
|
107
|
-
end
|
108
|
-
|
109
|
-
# Returns the root node of the tree.
|
110
|
-
def root
|
111
|
-
node = self
|
112
|
-
node = node.parent while node.parent
|
113
|
-
node
|
114
|
-
end
|
115
|
-
|
116
|
-
# Returns all siblings of the current node.
|
117
|
-
#
|
118
|
-
# subchild1.siblings # => [subchild2]
|
119
|
-
def siblings
|
120
|
-
self_and_siblings - [self]
|
121
|
-
end
|
122
|
-
|
123
|
-
# Returns all siblings and a reference to the current node.
|
124
|
-
#
|
125
|
-
# subchild1.self_and_siblings # => [subchild1, subchild2]
|
126
|
-
def self_and_siblings
|
127
|
-
parent ? parent.children : self.class.roots
|
128
|
-
end
|
129
|
-
|
130
|
-
# Returns children (without subchildren) and current node itself.
|
131
|
-
#
|
132
|
-
# root.self_and_children # => [root, child1]
|
133
|
-
def self_and_children
|
134
|
-
[self] + self.children
|
135
|
-
end
|
136
|
-
|
137
|
-
private
|
8
|
+
def self.included(base)
|
9
|
+
Kernel.warn "[DEPRECATION] The module ActiveRecord::Acts::Tree has moved to ActsAsTree"
|
138
10
|
|
139
|
-
|
140
|
-
if self.respond_to?(:children_count) && parent_id_changed?
|
141
|
-
self.class.decrement_counter(:children_count, parent_id_was)
|
142
|
-
self.class.increment_counter(:children_count, parent_id)
|
143
|
-
end
|
144
|
-
end
|
11
|
+
base.extend ::ActsAsTree::ClassMethods
|
145
12
|
end
|
146
13
|
end
|
147
14
|
end
|
data/lib/acts_as_tree/version.rb
CHANGED
data/test/acts_as_tree_test.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,11 +12,11 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2012-04-
|
15
|
+
date: 2012-04-25 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activerecord
|
19
|
-
requirement: &
|
19
|
+
requirement: &70112110455280 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
22
|
- - ! '>='
|
@@ -24,10 +24,10 @@ dependencies:
|
|
24
24
|
version: 3.0.0
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *70112110455280
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: sqlite3
|
30
|
-
requirement: &
|
30
|
+
requirement: &70112110454840 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
33
|
- - ! '>='
|
@@ -35,10 +35,10 @@ dependencies:
|
|
35
35
|
version: '0'
|
36
36
|
type: :development
|
37
37
|
prerelease: false
|
38
|
-
version_requirements: *
|
38
|
+
version_requirements: *70112110454840
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: rdoc
|
41
|
-
requirement: &
|
41
|
+
requirement: &70112110454380 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
44
|
- - ! '>='
|
@@ -46,7 +46,7 @@ dependencies:
|
|
46
46
|
version: '0'
|
47
47
|
type: :development
|
48
48
|
prerelease: false
|
49
|
-
version_requirements: *
|
49
|
+
version_requirements: *70112110454380
|
50
50
|
description: A gem that adds simple support for organizing ActiveRecord models into
|
51
51
|
parent–children relationships.
|
52
52
|
email:
|