basic_tree 1.0.0 → 1.0.1
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/.gemtest +0 -0
- data/Gemfile.lock +13 -9
- data/LICENSE +1 -1
- data/README.rdoc +12 -21
- data/Rakefile +6 -1
- data/basic_tree.gemspec +5 -2
- data/lib/basic_tree/version.rb +5 -0
- data/lib/basic_tree.rb +89 -15
- data/spec/lib/basic_tree_spec.rb +122 -59
- metadata +42 -7
data/.gemtest
ADDED
File without changes
|
data/Gemfile.lock
CHANGED
@@ -1,24 +1,28 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
basic_tree (0.
|
4
|
+
basic_tree (1.0.0)
|
5
|
+
activesupport (~> 3.0.5)
|
6
|
+
i18n (~> 0.5.0)
|
5
7
|
|
6
8
|
GEM
|
7
9
|
remote: http://rubygems.org/
|
8
10
|
specs:
|
11
|
+
activesupport (3.0.5)
|
9
12
|
diff-lcs (1.1.2)
|
10
|
-
|
11
|
-
|
12
|
-
rspec-
|
13
|
-
rspec-
|
14
|
-
|
15
|
-
rspec-
|
13
|
+
i18n (0.5.0)
|
14
|
+
rspec (2.5.0)
|
15
|
+
rspec-core (~> 2.5.0)
|
16
|
+
rspec-expectations (~> 2.5.0)
|
17
|
+
rspec-mocks (~> 2.5.0)
|
18
|
+
rspec-core (2.5.1)
|
19
|
+
rspec-expectations (2.5.0)
|
16
20
|
diff-lcs (~> 1.1.2)
|
17
|
-
rspec-mocks (2.
|
21
|
+
rspec-mocks (2.5.0)
|
18
22
|
|
19
23
|
PLATFORMS
|
20
24
|
ruby
|
21
25
|
|
22
26
|
DEPENDENCIES
|
23
27
|
basic_tree!
|
24
|
-
rspec (
|
28
|
+
rspec (~> 2.5.0)
|
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -18,16 +18,13 @@ A basic Ruby tree structure with nice syntax.
|
|
18
18
|
fruit.object
|
19
19
|
# "Fruit"
|
20
20
|
|
21
|
-
banana = fruit.
|
22
|
-
banana.object
|
23
|
-
# "Banana"
|
21
|
+
banana = fruit.get(2) # get the 2nd fruit
|
22
|
+
banana.object # "Banana"
|
24
23
|
|
25
|
-
plantain = banana.
|
26
|
-
plantain.object
|
27
|
-
# "Plantain"
|
24
|
+
plantain = banana.get(2) # get the 2nd banana
|
25
|
+
plantain.object # "Plantain"
|
28
26
|
|
29
|
-
plantain.parent.object
|
30
|
-
# "Banana""
|
27
|
+
plantain.parent.object # "Banana"
|
31
28
|
|
32
29
|
plantain.path.map(&:object)
|
33
30
|
# ["Fruit", "Banana", "Plantain"]
|
@@ -44,23 +41,17 @@ A basic Ruby tree structure with nice syntax.
|
|
44
41
|
banana.siblings.map(&:object)
|
45
42
|
# ["Apple", "Orange"]
|
46
43
|
|
47
|
-
plantain.root.object
|
48
|
-
# "Fruit"
|
44
|
+
plantain.root.object # "Fruit"
|
49
45
|
|
50
|
-
plantain.level
|
51
|
-
# 3
|
46
|
+
plantain.level # 3
|
52
47
|
|
53
|
-
banana.root?
|
54
|
-
# false
|
48
|
+
banana.root? # false
|
55
49
|
|
56
|
-
fruit.root?
|
57
|
-
# true
|
50
|
+
fruit.root? # true
|
58
51
|
|
59
|
-
banana.leaf?
|
60
|
-
# false
|
52
|
+
banana.leaf? # false
|
61
53
|
|
62
|
-
plantain.leaf?
|
63
|
-
# true
|
54
|
+
plantain.leaf? # true
|
64
55
|
|
65
56
|
== Note on Patches/Pull Requests
|
66
57
|
|
@@ -74,4 +65,4 @@ A basic Ruby tree structure with nice syntax.
|
|
74
65
|
|
75
66
|
== Copyright
|
76
67
|
|
77
|
-
|
68
|
+
See LICENSE for details.
|
data/Rakefile
CHANGED
data/basic_tree.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "basic_tree"
|
3
|
+
require "basic_tree/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "basic_tree"
|
@@ -19,5 +19,8 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_development_dependency 'rspec', "
|
22
|
+
s.add_development_dependency 'rspec', "~> 2.5.0"
|
23
|
+
|
24
|
+
s.add_dependency 'i18n', "~> 0.5.0"
|
25
|
+
s.add_dependency 'activesupport', "~> 3.0.5"
|
23
26
|
end
|
data/lib/basic_tree.rb
CHANGED
@@ -1,22 +1,64 @@
|
|
1
|
+
require 'active_support/core_ext/object'
|
2
|
+
|
1
3
|
class BasicTree
|
2
4
|
|
3
5
|
include Enumerable
|
4
6
|
|
5
|
-
|
7
|
+
class Kids < Array
|
8
|
+
def swap!(p1, p2)
|
9
|
+
self[p1], self[p2] = self[p2], self[p1]
|
10
|
+
end
|
11
|
+
end
|
6
12
|
|
13
|
+
##################################################
|
14
|
+
|
15
|
+
# TODO: test
|
7
16
|
def initialize(object, parent = nil, &block)
|
8
17
|
self.object = object
|
9
|
-
|
10
|
-
self.parent = parent
|
11
|
-
parent.children << self
|
12
|
-
end
|
18
|
+
parent.try(:insert!, self)
|
13
19
|
instance_eval(&block) if block_given?
|
14
20
|
end
|
15
21
|
|
16
|
-
|
17
|
-
|
22
|
+
# TODO: test
|
18
23
|
def add(object, &block)
|
19
|
-
self.class
|
24
|
+
if object.is_a?(self.class)
|
25
|
+
insert!(object)
|
26
|
+
else
|
27
|
+
self.class.new(object, self, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# TODO: test
|
32
|
+
def insert!(basic_tree)
|
33
|
+
raise ArgumentError, "Must be a #{self.class}" unless basic_tree.is_a?(self.class)
|
34
|
+
basic_tree.send(:parent=, self)
|
35
|
+
kids << basic_tree
|
36
|
+
end
|
37
|
+
|
38
|
+
# TODO: self
|
39
|
+
def remove!(basic_tree)
|
40
|
+
raise ArgumentError, "Must be a #{self.class}" unless basic_tree.is_a?(self.class)
|
41
|
+
raise StandardError, "Can't remove root" if root?
|
42
|
+
parent.send(:kids).delete(self)
|
43
|
+
basic_tree.send(:parent=, nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
# TODO: test
|
47
|
+
def move_up!
|
48
|
+
raise "Already first" if first?
|
49
|
+
parent.send(:kids).swap!(position, position - 1)
|
50
|
+
end
|
51
|
+
|
52
|
+
# TODO: test
|
53
|
+
def move_down!
|
54
|
+
raise "Already last" if last?
|
55
|
+
parent.send(:kids).swap!(position, position + 1)
|
56
|
+
end
|
57
|
+
|
58
|
+
##################################################
|
59
|
+
|
60
|
+
def children
|
61
|
+
kids.dup
|
20
62
|
end
|
21
63
|
|
22
64
|
def path
|
@@ -28,17 +70,28 @@ class BasicTree
|
|
28
70
|
end
|
29
71
|
|
30
72
|
def descendants
|
31
|
-
|
73
|
+
d = []
|
74
|
+
kids.each { |k| d += k.descendants.unshift(k) }
|
75
|
+
d
|
32
76
|
end
|
33
77
|
|
34
78
|
def subtree
|
35
|
-
|
79
|
+
descendants.unshift(self)
|
80
|
+
end
|
81
|
+
|
82
|
+
def siblings_and_self
|
83
|
+
root? ? [self] : parent.children
|
36
84
|
end
|
37
85
|
|
38
86
|
def siblings
|
39
|
-
root? ? [] :
|
87
|
+
root? ? [] : siblings_and_self.delete_if { |s| s == self }
|
40
88
|
end
|
41
89
|
|
90
|
+
##################################################
|
91
|
+
|
92
|
+
attr_reader :parent
|
93
|
+
attr_accessor :object
|
94
|
+
|
42
95
|
def root
|
43
96
|
path.first
|
44
97
|
end
|
@@ -47,16 +100,37 @@ class BasicTree
|
|
47
100
|
path.size
|
48
101
|
end
|
49
102
|
|
103
|
+
def position
|
104
|
+
siblings_and_self.index(self)
|
105
|
+
end
|
106
|
+
|
107
|
+
##################################################
|
108
|
+
|
50
109
|
def root?
|
51
110
|
!parent
|
52
111
|
end
|
53
112
|
|
54
113
|
def leaf?
|
55
|
-
|
114
|
+
kids.empty?
|
56
115
|
end
|
57
116
|
|
58
|
-
def
|
59
|
-
|
117
|
+
def first?
|
118
|
+
root? || siblings_and_self[0] == self
|
119
|
+
end
|
120
|
+
|
121
|
+
def last?
|
122
|
+
root? || siblings_and_self.last == self
|
123
|
+
end
|
124
|
+
|
125
|
+
##################################################
|
126
|
+
private
|
127
|
+
|
128
|
+
attr_writer :parent
|
129
|
+
|
130
|
+
def kids
|
131
|
+
@kids ||= Kids.new
|
60
132
|
end
|
61
133
|
|
62
|
-
end
|
134
|
+
end
|
135
|
+
|
136
|
+
require 'basic_tree/version'
|
data/spec/lib/basic_tree_spec.rb
CHANGED
@@ -16,74 +16,137 @@ describe BasicTree do
|
|
16
16
|
@a12 = @a1.children[1]
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@a2.path.should == [@a, @a2]
|
25
|
-
end
|
19
|
+
describe "instance methods" do
|
20
|
+
before do
|
21
|
+
@object = "soccer"
|
22
|
+
@bt = BasicTree.new(@object)
|
23
|
+
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
@a1.ancestors.should == [@a]
|
30
|
-
@a11.ancestors.should == [@a, @a1]
|
31
|
-
@a12.ancestors.should == [@a, @a1]
|
32
|
-
@a2.ancestors.should == [@a]
|
33
|
-
end
|
25
|
+
describe "#leaf?" do
|
26
|
+
context("with no children") { it { @bt.should be_leaf } }
|
34
27
|
|
35
|
-
|
36
|
-
|
37
|
-
@a1.descendants.should == [@a11, @a12]
|
38
|
-
@a11.descendants.should == []
|
39
|
-
@a12.descendants.should == []
|
40
|
-
@a2.descendants.should == []
|
41
|
-
end
|
28
|
+
context("with children") do
|
29
|
+
before { @bt.add("ball") }
|
42
30
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@a11.subtree.should == [@a11]
|
47
|
-
@a12.subtree.should == [@a12]
|
48
|
-
@a2.subtree.should == [@a2]
|
49
|
-
end
|
31
|
+
it { @bt.should_not be_leaf }
|
32
|
+
end
|
33
|
+
end
|
50
34
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
@a2.siblings.should == [@a1]
|
57
|
-
end
|
35
|
+
describe "#root?" do
|
36
|
+
context("with no parent") { it { @bt.should be_root } }
|
37
|
+
|
38
|
+
context("as a child") do
|
39
|
+
before { BasicTree.new("sport").add(@bt) }
|
58
40
|
|
59
|
-
|
60
|
-
|
61
|
-
m.root.should == @a
|
41
|
+
it { @bt.should_not be_root }
|
42
|
+
end
|
62
43
|
end
|
63
|
-
end
|
64
44
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
45
|
+
describe "#level" do
|
46
|
+
it "returns the size of the path" do
|
47
|
+
@bt.stub!(:path => 13.times.map(&:to_i))
|
48
|
+
@bt.level.should eq(13)
|
49
|
+
end
|
50
|
+
end
|
72
51
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
52
|
+
describe "#root" do
|
53
|
+
it "returns the first item in the path" do
|
54
|
+
@bt.stub!(:path => [3, 2])
|
55
|
+
@bt.root.should eq(3)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#path" do
|
60
|
+
it "returns the ancestors and itself" do
|
61
|
+
@bt.stub!(:ancestors => [3, 4])
|
62
|
+
@bt.path.should eq([3, 4, @bt])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#ancestors" do
|
67
|
+
context("when root") do
|
68
|
+
it("returns empty array") { @bt.ancestors.should eq([]) }
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when not root" do
|
72
|
+
before { BasicTree.new("Fun Stuff").add("Sports").add(@bt) }
|
73
|
+
|
74
|
+
it "returns parent's path" do
|
75
|
+
@bt.ancestors.should eq(@bt.parent.path)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#children" do
|
81
|
+
context "with none" do
|
82
|
+
it "returns empty array" do
|
83
|
+
@bt.children.should eq([])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "with some" do
|
88
|
+
before do
|
89
|
+
@c1 = @bt.add("c1")
|
90
|
+
@c2 = @bt.add("c2")
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns them" do
|
94
|
+
@bt.children.should eq([@c1, @c2])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#descendants" do
|
100
|
+
context "with no children" do
|
101
|
+
it { @bt.descendants.should eq([]) }
|
102
|
+
end
|
103
|
+
|
104
|
+
context "when children exist, and some of them have children" do
|
105
|
+
before do
|
106
|
+
@ball = @bt.add("ball")
|
107
|
+
@size = @ball.add("size")
|
108
|
+
@four = @size.add("4")
|
109
|
+
@goal = @bt.add("goal")
|
110
|
+
end
|
111
|
+
|
112
|
+
it "returns array" do
|
113
|
+
@bt.descendants.should eq([@ball, @size, @four, @goal])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
80
117
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
118
|
+
describe "#subtree" do
|
119
|
+
before do
|
120
|
+
@result = [1, 2, 3]
|
121
|
+
@bt.stub!(:descendants => @result)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should add itself to the front of descendants" do
|
125
|
+
@bt.descendants.should_receive(:unshift).with(@bt)
|
126
|
+
@bt.subtree
|
127
|
+
end
|
128
|
+
|
129
|
+
it { @bt.subtree.should eq(@result) }
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#siblings" do
|
133
|
+
context "when root" do
|
134
|
+
it { @bt.siblings.should eq([]) }
|
135
|
+
end
|
136
|
+
|
137
|
+
context "when not root" do
|
138
|
+
before do
|
139
|
+
@k1 = mock(BasicTree)
|
140
|
+
@k2 = mock(BasicTree)
|
141
|
+
|
142
|
+
@bt.stub!(:parent => mock(BasicTree, :children => [@k1, @bt, @k2]))
|
143
|
+
end
|
144
|
+
|
145
|
+
it "returns parent's children (without itself)" do
|
146
|
+
@bt.siblings.should eq([@k1, @k2])
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
87
150
|
end
|
88
151
|
|
89
152
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 1.0.
|
8
|
+
- 1
|
9
|
+
version: 1.0.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Austin Schneider
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-03-09 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -23,13 +23,45 @@ dependencies:
|
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
none: false
|
25
25
|
requirements:
|
26
|
-
- -
|
26
|
+
- - ~>
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
segments:
|
29
29
|
- 2
|
30
|
-
|
30
|
+
- 5
|
31
|
+
- 0
|
32
|
+
version: 2.5.0
|
31
33
|
type: :development
|
32
34
|
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: i18n
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
- 5
|
46
|
+
- 0
|
47
|
+
version: 0.5.0
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: activesupport
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ~>
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 3
|
60
|
+
- 0
|
61
|
+
- 5
|
62
|
+
version: 3.0.5
|
63
|
+
type: :runtime
|
64
|
+
version_requirements: *id003
|
33
65
|
description: A basic tree structure.
|
34
66
|
email:
|
35
67
|
- soccer022483@gmail.com
|
@@ -40,6 +72,7 @@ extensions: []
|
|
40
72
|
extra_rdoc_files: []
|
41
73
|
|
42
74
|
files:
|
75
|
+
- .gemtest
|
43
76
|
- .gitignore
|
44
77
|
- .rspec
|
45
78
|
- .rvmrc
|
@@ -50,6 +83,7 @@ files:
|
|
50
83
|
- Rakefile
|
51
84
|
- basic_tree.gemspec
|
52
85
|
- lib/basic_tree.rb
|
86
|
+
- lib/basic_tree/version.rb
|
53
87
|
- spec/lib/basic_tree_spec.rb
|
54
88
|
- spec/spec_helper.rb
|
55
89
|
has_rdoc: true
|
@@ -84,5 +118,6 @@ rubygems_version: 1.3.7
|
|
84
118
|
signing_key:
|
85
119
|
specification_version: 3
|
86
120
|
summary: A basic tree structure.
|
87
|
-
test_files:
|
88
|
-
|
121
|
+
test_files:
|
122
|
+
- spec/lib/basic_tree_spec.rb
|
123
|
+
- spec/spec_helper.rb
|