dm-is-tree 0.9.9 → 0.9.10

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/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