basic_tree 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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.1.1)
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
- rspec (2.3.0)
11
- rspec-core (~> 2.3.0)
12
- rspec-expectations (~> 2.3.0)
13
- rspec-mocks (~> 2.3.0)
14
- rspec-core (2.3.1)
15
- rspec-expectations (2.3.0)
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.3.0)
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 (>= 2)
28
+ rspec (~> 2.5.0)
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Austin Schneider
1
+ Copyright (c) 2010 Austin Schneider
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
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.children[1]
22
- banana.object
23
- # "Banana"
21
+ banana = fruit.get(2) # get the 2nd fruit
22
+ banana.object # "Banana"
24
23
 
25
- plantain = banana.children[1]
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
- Copyright (c) 2010 Austin Schneider. See LICENSE for details.
68
+ See LICENSE for details.
data/Rakefile CHANGED
@@ -1,3 +1,8 @@
1
1
  require 'bundler'
2
2
 
3
- Bundler::GemHelper.install_tasks
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ desc "Run tests"
6
+ task :test do
7
+ system 'rspec spec'
8
+ end
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', ">= 2"
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
@@ -0,0 +1,5 @@
1
+ class BasicTree
2
+
3
+ VERSION = "1.0.1"
4
+
5
+ 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
- VERSION = "1.0.0"
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
- if parent
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
- attr_accessor :object, :parent
17
-
22
+ # TODO: test
18
23
  def add(object, &block)
19
- self.class.new(object, self, &block)
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
- children.map { |c| [c] + c.descendants }.flatten
73
+ d = []
74
+ kids.each { |k| d += k.descendants.unshift(k) }
75
+ d
32
76
  end
33
77
 
34
78
  def subtree
35
- [self] + descendants
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? ? [] : parent.children.select { |child| child != self }
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
- children.empty?
114
+ kids.empty?
56
115
  end
57
116
 
58
- def children
59
- @children ||= []
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'
@@ -16,74 +16,137 @@ describe BasicTree do
16
16
  @a12 = @a1.children[1]
17
17
  end
18
18
 
19
- it "path" do
20
- @a.path.should == [@a]
21
- @a1.path.should == [@a, @a1]
22
- @a11.path.should == [@a, @a1, @a11]
23
- @a12.path.should == [@a, @a1, @a12]
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
- it "ancestors" do
28
- @a.ancestors.should == []
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
- it "descendants" do
36
- @a.descendants.should == [@a1, @a11, @a12, @a2]
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
- it "subtree" do
44
- @a.subtree.should == [@a, @a1, @a11, @a12, @a2]
45
- @a1.subtree.should == [@a1, @a11, @a12]
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
- it "siblings" do
52
- @a.siblings.should == []
53
- @a1.siblings.should == [@a2]
54
- @a11.siblings.should == [@a12]
55
- @a12.siblings.should == [@a11]
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
- it "root" do
60
- [@a, @a1, @a11, @a12, @a2].each do |m|
61
- m.root.should == @a
41
+ it { @bt.should_not be_root }
42
+ end
62
43
  end
63
- end
64
44
 
65
- it "level" do
66
- @a.level.should == 1
67
- @a1.level.should == 2
68
- @a11.level.should == 3
69
- @a12.level.should == 3
70
- @a2.level.should == 2
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
- it "root?" do
74
- @a.root?.should be_true
75
- @a1.root?.should be_false
76
- @a11.root?.should be_false
77
- @a12.root?.should be_false
78
- @a2.root?.should be_false
79
- end
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
- it "leaf?" do
82
- @a.leaf?.should be_false
83
- @a1.leaf?.should be_false
84
- @a11.leaf?.should be_true
85
- @a12.leaf?.should be_true
86
- @a2.leaf?.should be_true
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
- - 0
9
- version: 1.0.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: 2010-12-21 00:00:00 -05:00
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
- version: "2"
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