dm-is-tree 0.9.9 → 0.9.10

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.9.10 / 2009-01-19
2
+
3
+ * No changes this version
4
+
1
5
  === 0.9.9 / 2009-01-04
2
6
 
3
7
  * 1 minor enhancement:
data/Manifest.txt CHANGED
@@ -7,6 +7,9 @@ TODO
7
7
  lib/dm-is-tree.rb
8
8
  lib/dm-is-tree/is/tree.rb
9
9
  lib/dm-is-tree/is/version.rb
10
+ spec/integration/tree_spec.rb
10
11
  spec/spec.opts
12
+ spec/spec_helper.rb
13
+ spec/unit/tree_spec.rb
11
14
  tasks/install.rb
12
15
  tasks/spec.rb
data/README.txt CHANGED
@@ -1,3 +1,35 @@
1
1
  = dm-is-tree
2
2
 
3
3
  DataMapper plugin allowing the creation of tree structures from data models.
4
+
5
+ Example:
6
+
7
+ class Category
8
+ include DataMapper::Resource
9
+
10
+ property :id, Serial
11
+ property :parent_id, Integer
12
+ property :name, String
13
+
14
+ is :tree, :order => :name
15
+ end
16
+
17
+ root
18
+ +- child
19
+ +- grandchild1
20
+ +- grandchild2
21
+
22
+ root = Category.create(:name => "root")
23
+ child = root.children.create(:name => "child")
24
+ grandchild1 = child1.children.create(:name => "grandchild1")
25
+ grandchild2 = child2.children.create(:name => "grandchild2")
26
+
27
+ root.parent # => nil
28
+ child.parent # => root
29
+ root.children # => [child]
30
+ root.children.first.children.first # => grandchild1
31
+ Category.first_root # => root
32
+ Category.roots # => [root]
33
+
34
+ Original Author:: Timothy Bennett (http://lanaer.com)
35
+ Current Maintainer:: Garrett Heaver (http://www.linkedin.com/pub/dir/garrett/heaver)
data/TODO CHANGED
@@ -1,4 +1,4 @@
1
1
  TODO
2
2
  ====
3
3
 
4
- * dm-is-tree requires specs
4
+ * dm-is-tree requires more specs
data/lib/dm-is-tree.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'pathname'
3
3
 
4
- gem 'dm-core', '~>0.9.9'
4
+ gem 'dm-core', '~>0.9.10'
5
5
  require 'dm-core'
6
6
 
7
7
  require Pathname(__FILE__).dirname.expand_path / 'dm-is-tree' / 'is' / 'tree.rb'
@@ -19,25 +19,25 @@ module DataMapper
19
19
  # property :parent_id, Integer
20
20
  # property :name, String
21
21
  #
22
- # is :tree :order => "name"
22
+ # is :tree, :order => :name
23
23
  # end
24
24
  #
25
- # root
26
- # +- child
25
+ # root
26
+ # +- child
27
27
  # +- grandchild1
28
28
  # +- grandchild2
29
29
  #
30
- # root = Category.create("name" => "root")
31
- # child = root.children.create("name" => "child")
32
- # grandchild1 = child1.children.create("name" => "grandchild1")
33
- # grandchild2 = child2.children.create("name" => "grandchild2")
30
+ # root = Category.create(:name => "root")
31
+ # child = root.children.create(:name => "child")
32
+ # grandchild1 = child1.children.create(:name => "grandchild1")
33
+ # grandchild2 = child2.children.create(:name => "grandchild2")
34
34
  #
35
- # root.parent # => nil
35
+ # root.parent # => nil
36
36
  # child.parent # => root
37
- # root.children # => [child]
38
- # root.children.first.children.first # => grandchild1
37
+ # root.children # => [child]
38
+ # root.children.first.children.first # => grandchild1
39
39
  # Category.first_root # => root
40
- # Category.roots # => [root]
40
+ # Category.roots # => [root]
41
41
  #
42
42
  # The following instance methods are added:
43
43
  # * <tt>children</tt> - Returns all nodes with the current node as their parent, in the order specified by
@@ -52,30 +52,24 @@ module DataMapper
52
52
  # when called on <tt>grandchild2</tt>)
53
53
  # * <tt>root</tt> - Returns the root of the current node (<tt>root</tt> when called on <tt>grandchild2</tt>)
54
54
  #
55
- # Author:: Timothy Bennett (http://lanaer.com)
55
+ # Original Author:: Timothy Bennett (http://lanaer.com)
56
+ # Current Maintainer:: Garrett Heaver (http://www.linkedin.com/pub/dir/garrett/heaver)
56
57
 
57
58
  # Configuration options are:
58
59
  #
59
60
  # * <tt>child_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+)
60
61
  def is_tree(options = {})
61
- configuration = { :child_key => :parent_id }
62
- configuration.update(options) if Hash === options
63
-
64
- belongs_to :parent, :class_name => name, :child_key => [ configuration[:child_key] ]
65
- has n, :children, :class_name => name, :child_key => [ configuration[:child_key] ]
62
+ options = { :class_name => name, :child_key => :parent_id }.merge(options) if Hash === options
63
+ @tree_options = options
66
64
 
67
65
  include DataMapper::Is::Tree::InstanceMethods
68
66
  extend DataMapper::Is::Tree::ClassMethods
69
67
 
70
- class_eval <<-CLASS, __FILE__, __LINE__
71
- def self.roots
72
- all :#{configuration[:child_key]} => nil, :order => [#{configuration[:order].inspect}]
73
- end
68
+ assc_options = { :class_name => options[:class_name], :child_key => Array(options[:child_key]) }
69
+ has_n_options = options[:order] ? { :order => Array(options[:order]) }.merge(assc_options) : assc_options
74
70
 
75
- def self.first_root
76
- first :#{configuration[:child_key]} => nil, :order => [#{configuration[:order].inspect}]
77
- end
78
- CLASS
71
+ belongs_to :parent, assc_options
72
+ has n, :children, has_n_options
79
73
 
80
74
  class << self
81
75
  alias_method :root, :first_root # for people used to the ActiveRecord acts_as_tree
@@ -89,9 +83,23 @@ module DataMapper
89
83
  alias_method :can_has_tree, :is_tree # just for fun ;)
90
84
 
91
85
  module ClassMethods
86
+ attr_reader :tree_options
87
+
88
+ def roots
89
+ options = { tree_options[:child_key] => nil }
90
+ options = { :order => Array(tree_options[:order]) }.merge(options) if tree_options[:order]
91
+ all options
92
+ end
93
+
94
+ def first_root
95
+ options = { tree_options[:child_key] => nil }
96
+ options = { :order => Array(tree_options[:order]) }.merge(options) if tree_options[:order]
97
+ first options
98
+ end
92
99
  end
93
100
 
94
101
  module InstanceMethods
102
+
95
103
  # Returns list of ancestors, starting with the root.
96
104
  #
97
105
  # grandchild1.ancestors # => [root, child]
@@ -1,7 +1,7 @@
1
1
  module DataMapper
2
2
  module Is
3
3
  module Tree
4
- VERSION = '0.9.9'
4
+ VERSION = '0.9.10'
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,93 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
4
+
5
+ describe DataMapper::Is::Tree do
6
+
7
+ class Category
8
+ include DataMapper::Resource
9
+
10
+ property :id, Serial
11
+ property :parent_id, Integer
12
+ property :name, String
13
+ end
14
+
15
+ before(:all) do
16
+ Category.auto_migrate!
17
+
18
+ @root_a = Category.create(:name => 'a root')
19
+ @root_b = Category.create(:name => 'b root')
20
+
21
+ @child_a = Category.create(:name => 'a child', :parent_id => @root_a.id)
22
+ @child_b = Category.create(:name => 'b child', :parent_id => @root_a.id)
23
+
24
+ @grandchild_a = Category.create(:name => 'a grandchild', :parent_id => @child_a.id)
25
+ @grandchild_b = Category.create(:name => 'b grandchild', :parent_id => @child_a.id)
26
+ end
27
+
28
+ describe "roots class method" do
29
+
30
+ it "should return all instances where the child_key is nil" do
31
+ Category.is :tree
32
+ Category.roots.should == [@root_a, @root_b]
33
+ end
34
+
35
+ it "should use the order from the options if it is supplied" do
36
+ Category.is :tree, :order => :name.desc
37
+ Category.roots.should == [@root_b, @root_a]
38
+ end
39
+
40
+ end
41
+
42
+ describe "first_root class method" do
43
+
44
+ it "should return the first instance where the child_key is nil" do
45
+ Category.is :tree
46
+ Category.first_root.should == @root_a
47
+ end
48
+
49
+ it "should use the order from the options if it is supplied" do
50
+ Category.is :tree, :order => :name.desc
51
+ Category.first_root.should == @root_b
52
+ end
53
+
54
+ end
55
+
56
+ describe "ancestors instance method" do
57
+
58
+ it "should return the list of ancestors for the current node up to its root" do
59
+ Category.is :tree
60
+ @grandchild_a.ancestors.should == [@root_a, @child_a]
61
+ end
62
+
63
+ end
64
+
65
+ describe "root instance method" do
66
+
67
+ it "should return the root node for the current instance" do
68
+ Category.is :tree
69
+ @child_a.root.should == @root_a
70
+ end
71
+ end
72
+
73
+ describe "siblings instance method" do
74
+
75
+ it "should return all nodes which have the same parent as this node (excluding this node)" do
76
+ Category.is :tree
77
+ @child_a.siblings.should == [@child_b]
78
+ end
79
+
80
+ end
81
+
82
+ describe "generation instance method" do
83
+
84
+ it "should return all nodes which have the same parent as this node (including this node)" do
85
+ Category.is :tree
86
+ @child_a.generation.should == [@child_a, @child_b]
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,26 @@
1
+ require 'pathname'
2
+ require 'rubygems'
3
+
4
+ gem 'rspec', '~>1.1.11'
5
+ require 'spec'
6
+
7
+ require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-is-tree'
8
+
9
+ def load_driver(name, default_uri)
10
+ return false if ENV['ADAPTER'] != name.to_s
11
+
12
+ begin
13
+ DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
14
+ DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
15
+ true
16
+ rescue LoadError => e
17
+ warn "Could not load do_#{name}: #{e}"
18
+ false
19
+ end
20
+ end
21
+
22
+ ENV['ADAPTER'] ||= 'sqlite3'
23
+
24
+ HAS_SQLITE3 = load_driver(:sqlite3, 'sqlite3::memory:')
25
+ HAS_MYSQL = load_driver(:mysql, 'mysql://localhost/dm_core_test')
26
+ HAS_POSTGRES = load_driver(:postgres, 'postgres://postgres@localhost/dm_core_test')
@@ -0,0 +1,113 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe DataMapper::Is::Tree do
4
+
5
+ before do
6
+ class Category
7
+ include DataMapper::Resource
8
+
9
+ property :id, Serial
10
+ property :parent_id, Integer
11
+ property :name, String
12
+ end
13
+ end
14
+
15
+ it "should create a parent relationship" do
16
+ Category.is :tree
17
+ Category.relationships.should have_key(:parent)
18
+ end
19
+
20
+ it "should create a children relationship" do
21
+ Category.is :tree
22
+ Category.relationships.should have_key(:children)
23
+ end
24
+
25
+ it "should create a class method called roots" do
26
+ Category.is :tree
27
+ Category.should respond_to(:roots)
28
+ end
29
+
30
+ it "should create a class method called first_root" do
31
+ Category.is :tree
32
+ Category.should respond_to(:first_root)
33
+ end
34
+
35
+ it "should create an alias of class method first_root called root (ActiveRecord compatability)" do
36
+ Category.is :tree
37
+ Category.method(:first_root).should == Category.method(:root)
38
+ end
39
+
40
+ it "should create an instance method called ancestors" do
41
+ Category.is :tree
42
+ Category.new.should respond_to(:ancestors)
43
+ end
44
+
45
+ it "should create an instance method called root" do
46
+ Category.is :tree
47
+ Category.new.should respond_to(:root)
48
+ end
49
+
50
+ it "should create an instance method called siblings" do
51
+ Category.is :tree
52
+ Category.new.should respond_to(:siblings)
53
+ end
54
+
55
+ it "should create an instance method called generation" do
56
+ Category.is :tree
57
+ Category.new.should respond_to(:generation)
58
+ end
59
+
60
+ describe "parent relationship" do
61
+
62
+ it "should set the class_name from the current class" do
63
+ Category.is :tree
64
+ Category.relationships[:parent].options[:class_name].should == Category.name
65
+ end
66
+
67
+ it "should use the default child_key of :parent_id if none is supplied in the options" do
68
+ Category.is :tree
69
+ Category.relationships[:parent].options[:child_key].should == Array(:parent_id)
70
+ end
71
+
72
+ it "should use the child_key from the options if it is supplied" do
73
+ Category.is :tree, :child_key => :other_id
74
+ Category.relationships[:parent].options[:child_key].should == Array(:other_id)
75
+ end
76
+
77
+ it "should not set any order" do
78
+ Category.is :tree, :order => :name
79
+ Category.relationships[:parent].options.should_not have_key(:order)
80
+ end
81
+
82
+ end
83
+
84
+ describe "children relationship" do
85
+
86
+ it "should set the class_name from the current class" do
87
+ Category.is :tree
88
+ Category.relationships[:children].options[:class_name].should == Category.name
89
+ end
90
+
91
+ it "should use the default child_key of :parent_id if none is supplied in the options" do
92
+ Category.is :tree
93
+ Category.relationships[:children].options[:child_key].should == Array(:parent_id)
94
+ end
95
+
96
+ it "should use the child_key from the options if it is supplied" do
97
+ Category.is :tree, :child_key => :other_id
98
+ Category.relationships[:children].options[:child_key].should == Array(:other_id)
99
+ end
100
+
101
+ it "should not set any order if none is supplied in the options" do
102
+ Category.is :tree
103
+ Category.relationships[:children].options.should_not have_key(:order)
104
+ end
105
+
106
+ it "should use the order from the options if it is supplied" do
107
+ Category.is :tree, :order => :name
108
+ Category.relationships[:children].options[:order].should == Array(:name)
109
+ end
110
+
111
+ end
112
+
113
+ end
data/tasks/spec.rb CHANGED
@@ -8,7 +8,7 @@ begin
8
8
  desc 'Run specifications'
9
9
  Spec::Rake::SpecTask.new(:spec) do |t|
10
10
  t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
11
- t.spec_files = Pathname.glob((ROOT + 'spec/**/*_spec.rb').to_s)
11
+ t.spec_files = Pathname.glob((ROOT + 'spec/**/*_spec.rb').to_s).map { |f| f.to_s }
12
12
 
13
13
  begin
14
14
  gem 'rcov', '~>0.8'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-is-tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.9
4
+ version: 0.9.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Timothy Bennett
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-04 00:00:00 -08:00
12
+ date: 2009-01-19 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ~>
22
22
  - !ruby/object:Gem::Version
23
- version: 0.9.9
23
+ version: 0.9.10
24
24
  version:
25
25
  description: DataMapper plugin allowing the creation of tree structures from data models
26
26
  email:
@@ -44,7 +44,10 @@ files:
44
44
  - lib/dm-is-tree.rb
45
45
  - lib/dm-is-tree/is/tree.rb
46
46
  - lib/dm-is-tree/is/version.rb
47
+ - spec/integration/tree_spec.rb
47
48
  - spec/spec.opts
49
+ - spec/spec_helper.rb
50
+ - spec/unit/tree_spec.rb
48
51
  - tasks/install.rb
49
52
  - tasks/spec.rb
50
53
  has_rdoc: true