hierarchy 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,23 +1,20 @@
1
1
  h1. Hierarchy -- Use PostgreSQL @LTREE@ columns in ActiveRecord
2
2
 
3
3
  | *Author* | Tim Morgan |
4
- | *Version* | 1.0.5 (Nov 27, 2010) |
4
+ | *Version* | 1.0.6 (Nov 27, 2010) |
5
5
  | *License* | Released under the MIT license. |
6
6
 
7
7
  h2. About
8
8
 
9
- The @LTREE@ column type is a PostgreSQL-specific type (installation script is
10
- available in the @contrib@ directory in your PostgreSQL installation) for
11
- representing hierarchies. It is more efficient than the typical way of
12
- accomplishing hierarchal structures in SQL, the @parent_id@ column (or similar).
9
+ The @LTREE@ column type is a PostgreSQL-specific type (available from the ltree
10
+ extension) for representing hierarchies. It is more efficient than the typical
11
+ way of accomplishing hierarchical structures in SQL, the @parent_id@ column (or
12
+ similar).
13
13
 
14
14
  This gem lets you use an @LTREE@-utilizing hierarchy in ActiveRecord. Including
15
- this gem in your project gets you a) monkey-patches* to Arel to support @LTREE@
16
- columns, and b) a module you can include in your models, providing an abundance
17
- of methods to help you navigate and manipulate the hierarchy.
18
-
19
- *Though I don't know for sure, I suspect when Arel 2.0 is supported in Rails, I
20
- will be able to remove this monkey-patching ugliness.
15
+ this gem in your project gets you a module you can include in your models,
16
+ providing an abundance of methods to help you navigate and manipulate the
17
+ hierarchy.
21
18
 
22
19
  h2. Installation
23
20
 
@@ -69,7 +66,7 @@ You also have access to a wealth of ways to traverse the hierarchy:
69
66
  <pre><code>
70
67
  person.children.where(gender: :male)
71
68
  person.top_level?
72
- Person.treeified #=> returns a traversable tree of all people
69
+ Person.treeified #=> returns a traversible tree of all people
73
70
  </code></pre>
74
71
 
75
72
  For more information on what you can do, see the {Hierarchy} module
@@ -4,73 +4,58 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{hierarchy}
8
- s.version = "1.0.5"
7
+ s.name = "hierarchy"
8
+ s.version = "1.0.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tim Morgan"]
12
- s.date = %q{2010-11-27}
13
- s.description = %q{Adds ActiveRecord support for hierarchial data structures using PostgreSQL's LTREE column type.}
14
- s.email = %q{git@timothymorgan.info}
12
+ s.date = "2011-12-02"
13
+ s.description = "Adds ActiveRecord support for hierarchical data structures using PostgreSQL's LTREE column type."
14
+ s.email = "git@timothymorgan.info"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
17
  "README.textile"
18
18
  ]
19
19
  s.files = [
20
- ".document",
21
- ".rspec",
22
- "Gemfile",
23
- "Gemfile.lock",
24
20
  "LICENSE",
25
21
  "README.textile",
26
- "Rakefile",
27
- "VERSION",
28
22
  "hierarchy.gemspec",
29
23
  "lib/hierarchy.rb",
30
24
  "lib/hierarchy/index_path.rb",
31
25
  "lib/hierarchy/node.rb",
32
26
  "lib/hierarchy_generator.rb",
33
- "spec/hierarchy_spec.rb",
34
- "spec/index_path_spec.rb",
35
- "spec/spec_helper.rb",
36
27
  "templates/add_ltree_type.rb"
37
28
  ]
38
- s.homepage = %q{http://github.com/riscfuture/hierarchy}
29
+ s.homepage = "http://github.com/riscfuture/hierarchy"
39
30
  s.require_paths = ["lib"]
40
31
  s.required_ruby_version = Gem::Requirement.new(">= 1.9")
41
- s.rubygems_version = %q{1.3.7}
42
- s.summary = %q{Use PostgreSQL LTREE type with ActiveRecord}
43
- s.test_files = [
44
- "spec/hierarchy_spec.rb",
45
- "spec/index_path_spec.rb",
46
- "spec/spec_helper.rb"
47
- ]
32
+ s.rubygems_version = "1.8.11"
33
+ s.summary = "Use PostgreSQL LTREE type with ActiveRecord"
48
34
 
49
35
  if s.respond_to? :specification_version then
50
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
51
36
  s.specification_version = 3
52
37
 
53
38
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
39
  s.add_runtime_dependency(%q<rails>, [">= 3.0.2"])
40
+ s.add_runtime_dependency(%q<pg>, [">= 0"])
55
41
  s.add_development_dependency(%q<jeweler>, [">= 0"])
56
42
  s.add_development_dependency(%q<yard>, [">= 0"])
57
43
  s.add_development_dependency(%q<RedCloth>, [">= 0"])
58
- s.add_development_dependency(%q<pg>, [">= 0"])
59
44
  s.add_development_dependency(%q<rspec>, [">= 0"])
60
45
  else
61
46
  s.add_dependency(%q<rails>, [">= 3.0.2"])
47
+ s.add_dependency(%q<pg>, [">= 0"])
62
48
  s.add_dependency(%q<jeweler>, [">= 0"])
63
49
  s.add_dependency(%q<yard>, [">= 0"])
64
50
  s.add_dependency(%q<RedCloth>, [">= 0"])
65
- s.add_dependency(%q<pg>, [">= 0"])
66
51
  s.add_dependency(%q<rspec>, [">= 0"])
67
52
  end
68
53
  else
69
54
  s.add_dependency(%q<rails>, [">= 3.0.2"])
55
+ s.add_dependency(%q<pg>, [">= 0"])
70
56
  s.add_dependency(%q<jeweler>, [">= 0"])
71
57
  s.add_dependency(%q<yard>, [">= 0"])
72
58
  s.add_dependency(%q<RedCloth>, [">= 0"])
73
- s.add_dependency(%q<pg>, [">= 0"])
74
59
  s.add_dependency(%q<rspec>, [">= 0"])
75
60
  end
76
61
  end
@@ -1,21 +1,3 @@
1
- # @private
2
- module Arel
3
- # @private
4
- module Attributes
5
- # @private
6
- def self.for_with_psql(column)
7
- case column.sql_type
8
- when 'ltree' then String
9
- else for_without_psql(column)
10
- end
11
- end
12
- unless singleton_class.method_defined?(:for_without_psql)
13
- singleton_class.send :alias_method, :for_without_psql, :for
14
- singleton_class.send :alias_method, :for, :for_with_psql
15
- end
16
- end
17
- end
18
-
19
1
  require 'hierarchy_generator'
20
2
  require 'hierarchy/index_path'
21
3
  require 'hierarchy/node'
@@ -44,19 +26,20 @@ module Hierarchy
44
26
  extend ActiveSupport::Concern
45
27
 
46
28
  # @private
47
- included do |base|
48
- base.extend ActiveSupport::Memoizable
49
- base.memoize :index_path, :ancestors
50
-
51
- base.scope :parent_of, ->(obj) { obj.top_level? ? base.where('false') : base.where(id: obj.index_path.last) }
52
- base.scope :children_of, ->(obj) { base.where(path: obj.my_path) }
53
- base.scope :ancestors_of, ->(obj) { obj.top_level? ? base.where('false') : base.where(id: obj.index_path.to_a) }
54
- base.scope :descendants_of, ->(obj) { base.where([ "path <@ ?", obj.my_path ]) }
55
- base.scope :siblings_of, ->(obj) { base.where(path: obj.path) }
56
- base.scope :priority_order, base.order("NLEVEL(path) ASC")
57
- base.scope :top_level, base.where([ "path IS NULL or path = ?", '' ])
29
+ included do
30
+ extend ActiveSupport::Memoizable
31
+ memoize :index_path, :ancestors
58
32
 
59
- base.before_save { |obj| obj.path ||= '' }
33
+ scope :parent_of, ->(obj) { obj.top_level? ? where('false') : where(id: obj.index_path.last) }
34
+ scope :children_of, ->(obj) { where(path: obj.my_path) }
35
+ scope :ancestors_of, ->(obj) { obj.top_level? ? where('false') : where(id: obj.index_path.to_a) }
36
+ scope :descendants_of, ->(obj) { where("path <@ ?", obj.my_path) }
37
+ scope :siblings_of, ->(obj) { where(path: obj.path) }
38
+ scope :priority_order, order("NLEVEL(path) ASC")
39
+ scope :top_level, where("path IS NULL or path = ?", '')
40
+
41
+ before_save { |obj| obj.path ||= '' }
42
+ before_save :update_children_with_new_parent
60
43
  end
61
44
 
62
45
  module ClassMethods
@@ -161,5 +144,15 @@ module Hierarchy
161
144
  def index_path
162
145
  IndexPath.from_ltree path.to_s
163
146
  end
147
+
148
+ private
149
+
150
+ # if our parent has changed, update our children's paths
151
+ def update_children_with_new_parent
152
+ if path_changed? and not new_record? then
153
+ old_path = (path_was.blank? ? id.to_s : "#{path_was}.#{id}")
154
+ self.class.where("path <@ ?", old_path).update_all([ "path = TEXT2LTREE(REPLACE(LTREE2TEXT(path), ?, ?))", old_path, my_path ])
155
+ end
156
+ end
164
157
  end
165
158
  end
@@ -1,15 +1,9 @@
1
1
  class AddLtreeType < ActiveRecord::Migration
2
- def self.up
3
- cmd = "psql -f `pg_config --sharedir`/contrib/ltree.sql #{ActiveRecord::Base.connection.instance_variable_get(:@config)[:database]}"
4
- puts cmd
5
- result = system(cmd)
6
- raise "Bad exit" unless result
2
+ def up
3
+ execute "CREATE EXTENSION ltree"
7
4
  end
8
5
 
9
- def self.down
10
- cmd = "psql -f `pg_config --sharedir`/contrib/uninstall_ltree.sql #{ActiveRecord::Base.connection.instance_variable_get(:@config)[:database]}"
11
- puts cmd
12
- result = system(cmd)
13
- raise "Bad exit" unless result
6
+ def down
7
+ execute "DROP EXTENSION ltree"
14
8
  end
15
9
  end
metadata CHANGED
@@ -1,163 +1,121 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: hierarchy
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 1
7
- - 0
8
- - 5
9
- version: 1.0.5
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.6
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Tim Morgan
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2010-11-27 00:00:00 -08:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2011-12-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rails
22
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70260260128220 !ruby/object:Gem::Requirement
23
17
  none: false
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 3
29
- - 0
30
- - 2
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
31
21
  version: 3.0.2
32
22
  type: :runtime
33
23
  prerelease: false
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
24
+ version_requirements: *70260260128220
25
+ - !ruby/object:Gem::Dependency
26
+ name: pg
27
+ requirement: &70260260127240 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70260260127240
36
+ - !ruby/object:Gem::Dependency
36
37
  name: jeweler
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirement: &70260260126200 !ruby/object:Gem::Requirement
38
39
  none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- segments:
43
- - 0
44
- version: "0"
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
45
44
  type: :development
46
45
  prerelease: false
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
46
+ version_requirements: *70260260126200
47
+ - !ruby/object:Gem::Dependency
49
48
  name: yard
50
- requirement: &id003 !ruby/object:Gem::Requirement
49
+ requirement: &70260260125260 !ruby/object:Gem::Requirement
51
50
  none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- segments:
56
- - 0
57
- version: "0"
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
58
55
  type: :development
59
56
  prerelease: false
60
- version_requirements: *id003
61
- - !ruby/object:Gem::Dependency
57
+ version_requirements: *70260260125260
58
+ - !ruby/object:Gem::Dependency
62
59
  name: RedCloth
63
- requirement: &id004 !ruby/object:Gem::Requirement
64
- none: false
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- segments:
69
- - 0
70
- version: "0"
71
- type: :development
72
- prerelease: false
73
- version_requirements: *id004
74
- - !ruby/object:Gem::Dependency
75
- name: pg
76
- requirement: &id005 !ruby/object:Gem::Requirement
60
+ requirement: &70260260124220 !ruby/object:Gem::Requirement
77
61
  none: false
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- segments:
82
- - 0
83
- version: "0"
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
84
66
  type: :development
85
67
  prerelease: false
86
- version_requirements: *id005
87
- - !ruby/object:Gem::Dependency
68
+ version_requirements: *70260260124220
69
+ - !ruby/object:Gem::Dependency
88
70
  name: rspec
89
- requirement: &id006 !ruby/object:Gem::Requirement
71
+ requirement: &70260260123540 !ruby/object:Gem::Requirement
90
72
  none: false
91
- requirements:
92
- - - ">="
93
- - !ruby/object:Gem::Version
94
- segments:
95
- - 0
96
- version: "0"
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
97
77
  type: :development
98
78
  prerelease: false
99
- version_requirements: *id006
100
- description: Adds ActiveRecord support for hierarchial data structures using PostgreSQL's LTREE column type.
79
+ version_requirements: *70260260123540
80
+ description: Adds ActiveRecord support for hierarchical data structures using PostgreSQL's
81
+ LTREE column type.
101
82
  email: git@timothymorgan.info
102
83
  executables: []
103
-
104
84
  extensions: []
105
-
106
- extra_rdoc_files:
85
+ extra_rdoc_files:
107
86
  - LICENSE
108
87
  - README.textile
109
- files:
110
- - .document
111
- - .rspec
112
- - Gemfile
113
- - Gemfile.lock
88
+ files:
114
89
  - LICENSE
115
90
  - README.textile
116
- - Rakefile
117
- - VERSION
118
91
  - hierarchy.gemspec
119
92
  - lib/hierarchy.rb
120
93
  - lib/hierarchy/index_path.rb
121
94
  - lib/hierarchy/node.rb
122
95
  - lib/hierarchy_generator.rb
123
- - spec/hierarchy_spec.rb
124
- - spec/index_path_spec.rb
125
- - spec/spec_helper.rb
126
96
  - templates/add_ltree_type.rb
127
- has_rdoc: true
128
97
  homepage: http://github.com/riscfuture/hierarchy
129
98
  licenses: []
130
-
131
99
  post_install_message:
132
100
  rdoc_options: []
133
-
134
- require_paths:
101
+ require_paths:
135
102
  - lib
136
- required_ruby_version: !ruby/object:Gem::Requirement
103
+ required_ruby_version: !ruby/object:Gem::Requirement
137
104
  none: false
138
- requirements:
139
- - - ">="
140
- - !ruby/object:Gem::Version
141
- segments:
142
- - 1
143
- - 9
144
- version: "1.9"
145
- required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '1.9'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
110
  none: false
147
- requirements:
148
- - - ">="
149
- - !ruby/object:Gem::Version
150
- segments:
151
- - 0
152
- version: "0"
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
153
115
  requirements: []
154
-
155
116
  rubyforge_project:
156
- rubygems_version: 1.3.7
117
+ rubygems_version: 1.8.11
157
118
  signing_key:
158
119
  specification_version: 3
159
120
  summary: Use PostgreSQL LTREE type with ActiveRecord
160
- test_files:
161
- - spec/hierarchy_spec.rb
162
- - spec/index_path_spec.rb
163
- - spec/spec_helper.rb
121
+ test_files: []
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
data/.rspec DELETED
@@ -1 +0,0 @@
1
- -cfs
data/Gemfile DELETED
@@ -1,11 +0,0 @@
1
- source :rubygems
2
-
3
- gem 'rails', '>= 3.0.2'
4
-
5
- group :development do
6
- gem 'jeweler'
7
- gem 'yard'
8
- gem 'RedCloth', require: 'redcloth'
9
- gem 'pg'
10
- gem 'rspec'
11
- end
@@ -1,93 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- RedCloth (4.2.3)
5
- abstract (1.0.0)
6
- actionmailer (3.0.3)
7
- actionpack (= 3.0.3)
8
- mail (~> 2.2.9)
9
- actionpack (3.0.3)
10
- activemodel (= 3.0.3)
11
- activesupport (= 3.0.3)
12
- builder (~> 2.1.2)
13
- erubis (~> 2.6.6)
14
- i18n (~> 0.4)
15
- rack (~> 1.2.1)
16
- rack-mount (~> 0.6.13)
17
- rack-test (~> 0.5.6)
18
- tzinfo (~> 0.3.23)
19
- activemodel (3.0.3)
20
- activesupport (= 3.0.3)
21
- builder (~> 2.1.2)
22
- i18n (~> 0.4)
23
- activerecord (3.0.3)
24
- activemodel (= 3.0.3)
25
- activesupport (= 3.0.3)
26
- arel (~> 2.0.2)
27
- tzinfo (~> 0.3.23)
28
- activeresource (3.0.3)
29
- activemodel (= 3.0.3)
30
- activesupport (= 3.0.3)
31
- activesupport (3.0.3)
32
- arel (2.0.4)
33
- builder (2.1.2)
34
- diff-lcs (1.1.2)
35
- erubis (2.6.6)
36
- abstract (>= 1.0.0)
37
- git (1.2.5)
38
- i18n (0.4.2)
39
- jeweler (1.5.1)
40
- bundler (~> 1.0.0)
41
- git (>= 1.2.5)
42
- rake
43
- mail (2.2.10)
44
- activesupport (>= 2.3.6)
45
- i18n (~> 0.4.1)
46
- mime-types (~> 1.16)
47
- treetop (~> 1.4.8)
48
- mime-types (1.16)
49
- pg (0.9.0)
50
- polyglot (0.3.1)
51
- rack (1.2.1)
52
- rack-mount (0.6.13)
53
- rack (>= 1.0.0)
54
- rack-test (0.5.6)
55
- rack (>= 1.0)
56
- rails (3.0.3)
57
- actionmailer (= 3.0.3)
58
- actionpack (= 3.0.3)
59
- activerecord (= 3.0.3)
60
- activeresource (= 3.0.3)
61
- activesupport (= 3.0.3)
62
- bundler (~> 1.0)
63
- railties (= 3.0.3)
64
- railties (3.0.3)
65
- actionpack (= 3.0.3)
66
- activesupport (= 3.0.3)
67
- rake (>= 0.8.7)
68
- thor (~> 0.14.4)
69
- rake (0.8.7)
70
- rspec (2.1.0)
71
- rspec-core (~> 2.1.0)
72
- rspec-expectations (~> 2.1.0)
73
- rspec-mocks (~> 2.1.0)
74
- rspec-core (2.1.0)
75
- rspec-expectations (2.1.0)
76
- diff-lcs (~> 1.1.2)
77
- rspec-mocks (2.1.0)
78
- thor (0.14.6)
79
- treetop (1.4.9)
80
- polyglot (>= 0.3.1)
81
- tzinfo (0.3.23)
82
- yard (0.6.3)
83
-
84
- PLATFORMS
85
- ruby
86
-
87
- DEPENDENCIES
88
- RedCloth
89
- jeweler
90
- pg
91
- rails (>= 3.0.2)
92
- rspec
93
- yard
data/Rakefile DELETED
@@ -1,39 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler'
3
- begin
4
- Bundler.setup(:default, :development)
5
- rescue Bundler::BundlerError => e
6
- $stderr.puts e.message
7
- $stderr.puts "Run `bundle install` to install missing gems"
8
- exit e.status_code
9
- end
10
- require 'rake'
11
-
12
- require 'jeweler'
13
- Jeweler::Tasks.new do |gem|
14
- gem.name = "hierarchy"
15
- gem.summary = %Q{Use PostgreSQL LTREE type with ActiveRecord}
16
- gem.description = %Q{Adds ActiveRecord support for hierarchial data structures using PostgreSQL's LTREE column type.}
17
- gem.email = "git@timothymorgan.info"
18
- gem.homepage = "http://github.com/riscfuture/hierarchy"
19
- gem.authors = [ "Tim Morgan" ]
20
- gem.required_ruby_version = '>= 1.9'
21
- end
22
- Jeweler::RubygemsDotOrgTasks.new
23
-
24
- require 'rspec/core/rake_task'
25
- RSpec::Core::RakeTask.new
26
-
27
- require 'yard'
28
- YARD::Rake::YardocTask.new('doc') do |doc|
29
- doc.options << "-m" << "textile"
30
- doc.options << "--protected"
31
- doc.options << "--no-private"
32
- doc.options << "-r" << "README.textile"
33
- doc.options << "-o" << "doc"
34
- doc.options << "--title" << "Hierarchy Documentation".inspect
35
-
36
- doc.files = [ 'lib/**/*', 'README.textile' ]
37
- end
38
-
39
- task(default: :spec)
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.0.5
@@ -1,116 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hierarchy do
4
- before :each do
5
- @objects = Hash.new
6
- 2.times { |i| @objects[:"grandparent_#{i + 1}"] = Model.create! }
7
- 2.times do |gp_num|
8
- 2.times { |i| @objects[:"parent_#{gp_num + 1}_#{i + 1}"] = Model.create!(parent: @objects[:"grandparent_#{gp_num + 1}"]) }
9
- end
10
- 2.times do |gp_num|
11
- 2.times do |p_num|
12
- 2.times { |i| @objects[:"child_#{gp_num + 1}_#{p_num + 1}_#{i + 1}"] = Model.create!(parent: @objects[:"parent_#{gp_num + 1}_#{p_num + 1}"]) }
13
- end
14
- end
15
- end
16
-
17
- describe ".parent_of" do
18
- it "should return the parent object" do
19
- Model.parent_of(@objects[:parent_1_1]).should == [ @objects[:grandparent_1] ]
20
- Model.parent_of(@objects[:parent_2_2]).should == [ @objects[:grandparent_2] ]
21
- end
22
-
23
- it "should return an empty relation for top-level objects" do
24
- Model.parent_of(@objects[:grandparent_1]).should be_empty
25
- Model.parent_of(@objects[:grandparent_2]).should be_empty
26
- end
27
- end
28
-
29
- describe ".children_of" do
30
- it "should return the direct children of an object" do
31
- Model.children_of(@objects[:grandparent_1]).should == [ :parent_1_1, :parent_1_2 ].map { |name| @objects[name] }
32
- Model.children_of(@objects[:parent_2_1]).should == [ :child_2_1_1, :child_2_1_2 ].map { |name| @objects[name] }
33
- end
34
-
35
- it "should return an empty relation for leaf objects" do
36
- Model.children_of(@objects[:child_1_1_1]).should be_empty
37
- Model.children_of(@objects[:child_2_2_2]).should be_empty
38
- end
39
- end
40
-
41
- describe ".ancestors_of" do
42
- it "should return all ancestors of an object" do
43
- Model.ancestors_of(@objects[:child_1_2_1]).should == [ :grandparent_1, :parent_1_2 ].map { |name| @objects[name] }
44
- Model.ancestors_of(@objects[:parent_2_1]).should == [ @objects[:grandparent_2] ]
45
- end
46
-
47
- it "should return an empty relation for top-level objects" do
48
- Model.ancestors_of(@objects[:grandparent_1]).should be_empty
49
- end
50
- end
51
-
52
- describe ".descendants_of" do
53
- it "should return all descendants of an object" do
54
- Model.descendants_of(@objects[:grandparent_2]).should == [ :parent_2_1, :parent_2_2, :child_2_1_1, :child_2_1_2, :child_2_2_1, :child_2_2_2 ].map { |name| @objects[name] }
55
- Model.descendants_of(@objects[:parent_2_1]).should == [ :child_2_1_1, :child_2_1_2 ].map { |name| @objects[name] }
56
- end
57
-
58
- it "should return an empty relation for leaf objects" do
59
- Model.children_of(@objects[:child_1_1_1]).should be_empty
60
- Model.children_of(@objects[:child_2_2_2]).should be_empty
61
- end
62
- end
63
-
64
- describe ".siblings_of" do
65
- it "should return all sibling objects" do
66
- Model.siblings_of(@objects[:parent_1_1]).should == [ :parent_1_1, :parent_1_2 ].map { |name| @objects[name] }
67
- end
68
- end
69
-
70
- describe "#parent=" do
71
- it "should raise an error if parent is unsaved" do
72
- expect { Model.create!.parent = Model.new }.to raise_error(ArgumentError)
73
- end
74
-
75
- it "should set the path ltree appropriately" do
76
- ggp = Model.create!
77
- gp = Model.create!(path: ggp.id.to_s)
78
- pa = Model.create!(path: "#{ggp.id}.#{gp.id}")
79
- path = [ ggp.id, gp.id, pa.id ].join('.')
80
-
81
- object = Model.new
82
- parent = Model.create!(path: path)
83
- object.parent = parent
84
- object.save!
85
- object.path.should eql("#{path}.#{parent.id}")
86
- end
87
- end
88
-
89
- describe "#top_level?" do
90
- it "should return true for a top-level object" do
91
- Model.create!.should be_top_level
92
- end
93
-
94
- it "should return false for an object with a parent" do
95
- parent = Model.create!
96
- Model.create!(parent: parent).should_not be_top_level
97
- end
98
- end
99
-
100
- describe "#bottom_level?" do
101
- it "should return true for an object with no children" do
102
- Model.create!.should be_bottom_level
103
- end
104
- it "should return false for an object with children" do
105
- parent = Model.create!
106
- Model.create!(parent: parent)
107
- parent.should_not be_bottom_level
108
- end
109
- end
110
-
111
- describe "#ancestors" do
112
- it "should return an empty array for a top-level object" do
113
- Model.create!.ancestors.should eql([])
114
- end
115
- end
116
- end
@@ -1,31 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe Hierarchy::IndexPath do
4
- describe ".<=>" do
5
- def compare(ip1, ip2)
6
- Hierarchy::IndexPath.new(*ip1) <=> Hierarchy::IndexPath.new(*ip2)
7
- end
8
-
9
- it "should return -1 if this index path comes before the given index path" do
10
- # all except last digit equal
11
- compare([ 1,2,3 ], [ 1,2,4 ]).should eql(-1)
12
- # unequal in higher precedence
13
- compare([ 1,2,3 ], [ 1,3,2 ]).should eql(-1)
14
- # other is longer
15
- compare([ 1,2,3 ], [ 1,2,3,4 ]).should eql(-1)
16
- end
17
-
18
- it "should return 1 if this index path comes after the given index path" do
19
- # all except last digit equal
20
- compare([ 1,2,4 ], [ 1,2,3 ]).should eql(1)
21
- # unequal in higher precedence
22
- compare([ 1,3,2 ], [ 1,2,3 ]).should eql(1)
23
- # this is longer
24
- compare([ 1,2,3,4 ], [ 1,2,3, ]).should eql(1)
25
- end
26
-
27
- it "should return 0 if the index paths are equal" do
28
- compare([ 1,2,3 ], [ 1,2,3 ]).should eql(0)
29
- end
30
- end
31
- end
@@ -1,26 +0,0 @@
1
- Bundler.require :default, :test
2
- require 'active_support'
3
- require 'active_record'
4
-
5
- $LOAD_PATH.unshift(File.dirname(__FILE__))
6
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
-
8
- require 'hierarchy'
9
-
10
- ActiveRecord::Base.establish_connection(
11
- adapter: 'postgresql',
12
- database: 'hierarchy_test',
13
- username: 'hierarchy_tester'
14
- )
15
- system "psql -f `pg_config --sharedir`/contrib/ltree.sql hierarchy_test &>/dev/null"
16
-
17
- class Model < ActiveRecord::Base
18
- include Hierarchy
19
- end
20
-
21
- RSpec.configure do |config|
22
- config.before(:each) do
23
- Model.connection.execute "DROP TABLE IF EXISTS models"
24
- Model.connection.execute "CREATE TABLE models (id SERIAL PRIMARY KEY, path LTREE NOT NULL DEFAULT '')"
25
- end
26
- end