hierarchy 1.0.5 → 1.0.7

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3216ee2327673134cabc227dba69a8c0c65aea3a76de131147882a1b469e06b5
4
+ data.tar.gz: be02935315adf7c8aa28c5509524cd770fe12c0f46c35a3cf8284e8f8dc4bbb8
5
+ SHA512:
6
+ metadata.gz: 529e2c8961cde1ecf43f4eb709238e4fed99d2be60b62db09421e39261bc1023684494f9130fdd0af533dee5fd1b7261538836b7ad1fe5c4e27cc937f4170eaa
7
+ data.tar.gz: b266febc4eff1430db81651581052d326126b4717da80b293424a825c40adcbc49fbe5809f2ae85f7dd0d1506ea55514ed9e893899c82121ab7d65503057dfb6
data/README.md ADDED
@@ -0,0 +1,106 @@
1
+ > ⚠️ **DEPRECATED:** `hierarchy` is no longer maintained. Consider `ancestry`,
2
+ > `closure_tree`, or `acts_as_tree` for tree-structured ActiveRecord data. The
3
+ > final release is v1.0.7.
4
+
5
+ Hierarchy
6
+ =========
7
+
8
+ **Use PostgreSQL `LTREE` columns in ActiveRecord**
9
+
10
+ | | |
11
+ |:------------|:--------------------------------|
12
+ | **Author** | Tim Morgan |
13
+ | **Version** | 1.0.6 (Nov 27, 2010) |
14
+ | **License** | Released under the MIT license. |
15
+
16
+ About
17
+ -----
18
+
19
+ The `LTREE` column type is a PostgreSQL-specific type (available from the ltree
20
+ extension) for representing hierarchies. It is more efficient than the typical
21
+ way of accomplishing hierarchical structures in SQL, the `parent_id` column (or
22
+ similar).
23
+
24
+ This gem lets you use an `LTREE`-utilizing hierarchy in ActiveRecord. Including
25
+ this gem in your project gets you a module you can include in your models,
26
+ providing an abundance of methods to help you navigate and manipulate the
27
+ hierarchy.
28
+
29
+ Installation
30
+ ------------
31
+
32
+ **Important Note:** This gem requires Ruby 1.9+ and Rails 3.0+.
33
+
34
+ Firstly, add the gem to your Rails project's `Gemfile`:
35
+
36
+ ```` ruby
37
+ gem 'hierarchy'
38
+ ````
39
+
40
+ Then, run the generator to install the migration:
41
+
42
+ ```` sh
43
+ rails generate hierarchy
44
+ ````
45
+
46
+ Note that *this migration must precede any tables using `LTREEs`*, so reorder
47
+ the migration if you have to.
48
+
49
+ Usage
50
+ -----
51
+
52
+ Because this gem was hastily extracted from a personal project, it's a little
53
+ constraining in how it can be used. (Sorry.) Currently the gem requires that
54
+ your table schema have a column named @path@ of type `LTREE`, defined as in the
55
+ example below:
56
+
57
+ ```` sql
58
+ path LTREE NOT NULL DEFAULT ''
59
+ ````
60
+
61
+ Once you've got that column in your model, feel free to include the `Hierarchy`
62
+ module:
63
+
64
+ ```` ruby
65
+ class Person < ActiveRecord::Base
66
+ include Hierarchy
67
+ end
68
+ ````
69
+
70
+ You can now define hierarchy by setting a model's `parent`, like so:
71
+
72
+ ```` ruby
73
+ person.parent = mother #=> Sets the `path` column appropriately
74
+ ````
75
+
76
+ You also have access to a wealth of ways to traverse the hierarchy:
77
+
78
+ ```` ruby
79
+ person.children.where(gender: :male)
80
+ person.top_level?
81
+ Person.treeified #=> returns a traversible tree of all people
82
+ ````
83
+
84
+ For more information on what you can do, see the {Hierarchy} module
85
+ documentation.
86
+
87
+ Development
88
+ -----------
89
+
90
+ If you wish to develop for Hierarchy, the first thing you will want to do is get
91
+ specs up and running. This requires a call to `bundle install` (obviously) and
92
+ setting up your test database.
93
+
94
+ As you can see in the `spec/spec_helper.rb` file, the specs require that a
95
+ PostgreSQL database named `hierarchy_test` exist and be owned by a
96
+ `hierarchy_tester` user. Unfortunately I haven't written a way to configure this
97
+ (though patches are welcome). So, the following commands should suffice to get
98
+ you started:
99
+
100
+ ```` sh
101
+ createuser hierarchy_tester # answer "no" to all prompts
102
+ createdb -O hierarchy_tester hierarchy_test
103
+ ````
104
+
105
+ With those steps done you should be able to run `rake spec` and see the Glorious
106
+ Green.
data/hierarchy.gemspec CHANGED
@@ -2,75 +2,70 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: hierarchy 1.0.7 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
- s.name = %q{hierarchy}
8
- s.version = "1.0.5"
8
+ s.name = "hierarchy"
9
+ s.version = "1.0.7"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
12
  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}
13
+ s.date = "2013-12-08"
14
+ s.description = "Adds ActiveRecord support for hierarchical data structures using PostgreSQL's LTREE column type."
15
+ s.email = "git@timothymorgan.info"
15
16
  s.extra_rdoc_files = [
16
17
  "LICENSE",
17
- "README.textile"
18
+ "README.md"
18
19
  ]
19
20
  s.files = [
20
- ".document",
21
- ".rspec",
22
- "Gemfile",
23
- "Gemfile.lock",
24
21
  "LICENSE",
25
- "README.textile",
26
- "Rakefile",
27
- "VERSION",
22
+ "README.md",
28
23
  "hierarchy.gemspec",
29
24
  "lib/hierarchy.rb",
30
25
  "lib/hierarchy/index_path.rb",
31
26
  "lib/hierarchy/node.rb",
32
27
  "lib/hierarchy_generator.rb",
33
- "spec/hierarchy_spec.rb",
34
- "spec/index_path_spec.rb",
35
- "spec/spec_helper.rb",
36
28
  "templates/add_ltree_type.rb"
37
29
  ]
38
- s.homepage = %q{http://github.com/riscfuture/hierarchy}
30
+ s.homepage = "http://github.com/riscfuture/hierarchy"
39
31
  s.require_paths = ["lib"]
40
32
  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
- ]
33
+ s.rubygems_version = "2.1.11"
34
+ s.summary = "[DEPRECATED] Use PostgreSQL LTREE type with ActiveRecord"
35
+ s.post_install_message = <<~MSG
36
+
37
+ ⚠️ DEPRECATED: hierarchy is no longer maintained.
38
+
39
+ No longer maintained. Consider `ancestry`, `closure_tree`, or `acts_as_tree` for tree-structured ActiveRecord data.
40
+
41
+ This is the final release. No further updates are planned.
42
+
43
+ MSG
48
44
 
49
45
  if s.respond_to? :specification_version then
50
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
51
- s.specification_version = 3
46
+ s.specification_version = 4
52
47
 
53
48
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
49
  s.add_runtime_dependency(%q<rails>, [">= 3.0.2"])
50
+ s.add_runtime_dependency(%q<pg>, [">= 0"])
55
51
  s.add_development_dependency(%q<jeweler>, [">= 0"])
56
52
  s.add_development_dependency(%q<yard>, [">= 0"])
57
53
  s.add_development_dependency(%q<RedCloth>, [">= 0"])
58
- s.add_development_dependency(%q<pg>, [">= 0"])
59
54
  s.add_development_dependency(%q<rspec>, [">= 0"])
60
55
  else
61
56
  s.add_dependency(%q<rails>, [">= 3.0.2"])
57
+ s.add_dependency(%q<pg>, [">= 0"])
62
58
  s.add_dependency(%q<jeweler>, [">= 0"])
63
59
  s.add_dependency(%q<yard>, [">= 0"])
64
60
  s.add_dependency(%q<RedCloth>, [">= 0"])
65
- s.add_dependency(%q<pg>, [">= 0"])
66
61
  s.add_dependency(%q<rspec>, [">= 0"])
67
62
  end
68
63
  else
69
64
  s.add_dependency(%q<rails>, [">= 3.0.2"])
65
+ s.add_dependency(%q<pg>, [">= 0"])
70
66
  s.add_dependency(%q<jeweler>, [">= 0"])
71
67
  s.add_dependency(%q<yard>, [">= 0"])
72
68
  s.add_dependency(%q<RedCloth>, [">= 0"])
73
- s.add_dependency(%q<pg>, [">= 0"])
74
69
  s.add_dependency(%q<rspec>, [">= 0"])
75
70
  end
76
71
  end
@@ -1,7 +1,7 @@
1
1
  module Hierarchy
2
-
2
+
3
3
  # An array of integers representing an ordered list of IDs. Duck-types an
4
- # @Array@ in many ways.
4
+ # `Array` in many ways.
5
5
 
6
6
  class IndexPath
7
7
  include Enumerable
@@ -25,9 +25,9 @@ module Hierarchy
25
25
  @indexes = indexes
26
26
  end
27
27
 
28
- # Creates an index path from a PostgreSQL @LTREE@ column.
28
+ # Creates an index path from a PostgreSQL `LTREE` column.
29
29
  #
30
- # @param [String] string An @LTREE@ column value, such as "1.10.22".
30
+ # @param [String] string An `LTREE` column value, such as "1.10.22".
31
31
  # @return [IndexPath] A corresponding index path.
32
32
 
33
33
  def self.from_ltree(string)
@@ -1,5 +1,5 @@
1
1
  module Hierarchy
2
-
2
+
3
3
  # A node in a tree structure. A node can have zero or more {#children}, and
4
4
  # has a reverse link back to its parent.
5
5
 
@@ -7,7 +7,7 @@ module Hierarchy
7
7
  # @return [Array<Node>] This node's children.
8
8
  attr_reader :children
9
9
 
10
- # @return [Node, nil] This node's parent, or @nil@ if it is a root node.
10
+ # @return [Node, nil] This node's parent, or `nil` if it is a root node.
11
11
  attr_reader :parent
12
12
 
13
13
  # @return The object this node contains.
data/lib/hierarchy.rb CHANGED
@@ -1,38 +1,20 @@
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'
22
4
 
23
- # Adds a tree structure to a model. This is very similar to @acts_as_nested_set@
24
- # but uses the PostgreSQL-specific @ltree@ feature for schema storage.
5
+ # Adds a tree structure to a model. This is very similar to `acts_as_nested_set`
6
+ # but uses the PostgreSQL-specific `ltree` feature for schema storage.
25
7
  #
26
- # Your model must have a @path@ field of type @ltree@. This field will be a
8
+ # Your model must have a `path` field of type `ltree`. This field will be a
27
9
  # period-delimited list of IDs of records above this one in the hierarchy. In
28
10
  # addition, you should also consider the following indexes:
29
11
  #
30
- # <pre><code>
12
+ # ```` sql
31
13
  # CREATE INDEX index1 ON table USING gist(path)
32
14
  # CREATE INDEX index2 ON table USING btree(path)
33
- # </code></pre>
15
+ # ````
34
16
  #
35
- # replacing @table@ with your table and @index1@/@index2@ with appropriate names
17
+ # replacing `table` with your table and `index1`/`index2` with appropriate names
36
18
  # for these indexes.
37
19
  #
38
20
  # @example
@@ -42,21 +24,19 @@ require 'hierarchy/node'
42
24
 
43
25
  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 = ?", '' ])
58
-
59
- base.before_save { |obj| obj.path ||= '' }
29
+ included do
30
+ scope :parent_of, ->(obj) { obj.top_level? ? where('false') : where(id: obj.index_path.last) }
31
+ scope :children_of, ->(obj) { where(path: obj.my_path) }
32
+ scope :ancestors_of, ->(obj) { obj.top_level? ? where('false') : where(id: obj.index_path.to_a) }
33
+ scope :descendants_of, ->(obj) { where("path <@ ?", obj.my_path) }
34
+ scope :siblings_of, ->(obj) { where(path: obj.path) }
35
+ scope :priority_order, -> { order("NLEVEL(path) ASC") }
36
+ scope :top_level, -> { where("path IS NULL or path = ?", '') }
37
+
38
+ before_save { |obj| obj.path ||= '' }
39
+ before_save :update_children_with_new_parent
60
40
  end
61
41
 
62
42
  module ClassMethods
@@ -85,81 +65,94 @@ module Hierarchy
85
65
  end
86
66
  end
87
67
 
88
- # Methods added to instances of the class this module is included into.
89
-
90
- module InstanceMethods
91
- # Sets the object above this one in the hierarchy.
92
- #
93
- # @param [ActiveRecord::Base] parent The parent object.
94
- # @raise [ArgumentError] If @parent@ is an unsaved record with no primary key.
68
+ # Sets the object above this one in the hierarchy.
69
+ #
70
+ # @param [ActiveRecord::Base] parent The parent object.
71
+ # @raise [ArgumentError] If `parent` is an unsaved record with no primary key.
95
72
 
96
- def parent=(parent)
97
- raise ArgumentError, "Parent cannot be a new record" if parent.try(:new_record?)
98
- self.path = parent.try(:my_path)
99
- end
73
+ def parent=(parent)
74
+ raise ArgumentError, "Parent cannot be a new record" if parent.try(:new_record?)
75
+ self.path = parent.try(:my_path)
76
+ end
100
77
 
101
- # Returns an array of ancestors above this object. Note that a) this array
102
- # is ordered with the most senior ancestor at the beginning of the list, and
103
- # b) this is an _array_, not a _relation_. For that reason, you can pass
104
- # any additional scope options to the method.
105
- #
106
- # @param [Hash] options Additional finder options.
107
- # @return [Array] The objects above this one in the hierarchy.
78
+ # Returns an array of ancestors above this object. Note that a) this array
79
+ # is ordered with the most senior ancestor at the beginning of the list, and
80
+ # b) this is an _array_, not a _relation_. For that reason, you can pass
81
+ # any additional scope options to the method.
82
+ #
83
+ # @param [Hash] options Additional finder options.
84
+ # @return [Array] The objects above this one in the hierarchy.
108
85
 
109
- def ancestors(options={})
86
+ def ancestors(options={})
87
+ @ancestors ||= begin
110
88
  return [] if top_level?
111
89
  objects = self.class.ancestors_of(self).scoped(options).group_by(&:id)
112
90
  index_path.map { |id| objects[id].first }
113
91
  end
92
+ end
114
93
 
115
- # @return [ActiveRecord::Relation] The objects below this one in the
116
- # hierarchy.
94
+ # @return [ActiveRecord::Relation] The objects below this one in the
95
+ # hierarchy.
117
96
 
118
- def descendants
119
- self.class.descendants_of self
120
- end
97
+ def descendants
98
+ self.class.descendants_of self
99
+ end
121
100
 
122
- # @return [ActiveRecord::Base] The object directly above this one in the
123
- # hierarchy.
101
+ # @return [ActiveRecord::Base] The object directly above this one in the
102
+ # hierarchy.
124
103
 
125
- def parent
126
- top_level? ? nil : self.class.parent_of(self).first
127
- end
104
+ def parent
105
+ top_level? ? nil : self.class.parent_of(self).first
106
+ end
128
107
 
129
- # @return [ActiveRecord::Relation] The objects directly below this one
130
- # in the hierarchy.
108
+ # @return [ActiveRecord::Relation] The objects directly below this one
109
+ # in the hierarchy.
131
110
 
132
- def children
133
- self.class.children_of self
134
- end
111
+ def children
112
+ self.class.children_of self
113
+ end
135
114
 
136
- # @return [Array] The objects at the same hierarchical level of this one.
115
+ # @return [Array] The objects at the same hierarchical level of this one.
137
116
 
138
- def siblings
139
- self.class.siblings_of(self) - [ self ]
140
- end
117
+ def siblings
118
+ self.class.siblings_of(self) - [ self ]
119
+ end
141
120
 
142
- # @return [true, false] Whether or not this object has no parents.
121
+ # @return [true, false] Whether or not this object has no parents.
143
122
 
144
- def top_level?
145
- path.blank?
146
- end
123
+ def top_level?
124
+ path.blank?
125
+ end
147
126
 
148
- # @return [true, false] Whether or not this object has no children. Makes a
149
- # database call.
127
+ # @return root parent or nil(if current obj is top level)
128
+ def root
129
+ self.top_level? ? nil : self.class.find(self.path.split('.').first)
130
+ end
150
131
 
151
- def bottom_level?
152
- children.empty?
153
- end
132
+ # @return [true, false] Whether or not this object has no children. Makes a
133
+ # database call.
154
134
 
155
- # @private
156
- def my_path
157
- path.blank? ? id.to_s : "#{path}.#{id}"
158
- end
135
+ def bottom_level?
136
+ children.empty?
137
+ end
138
+
139
+ # @private
140
+ def my_path
141
+ path.blank? ? id.to_s : "#{path}.#{id}"
142
+ end
143
+
144
+ # @private
145
+ def index_path
146
+ @index_path ||= IndexPath.from_ltree path.to_s
147
+ end
148
+
149
+ private
159
150
 
160
- # @private
161
- def index_path
162
- IndexPath.from_ltree path.to_s
151
+ # if our parent has changed, update our children's paths
152
+ def update_children_with_new_parent
153
+ if path_changed? and not new_record? then
154
+ old_path = (path_was.blank? ? id.to_s : "#{path_was}.#{id}")
155
+ self.class.where("path <@ ?", old_path).update_all([ "path = TEXT2LTREE(REPLACE(LTREE2TEXT(path), ?, ?))", old_path, my_path ])
163
156
  end
164
157
  end
165
158
  end
@@ -5,18 +5,18 @@ require 'rails/generators/migration'
5
5
  # @private
6
6
  class HierarchyGenerator < Rails::Generators::Base
7
7
  include Rails::Generators::Migration
8
-
8
+
9
9
  source_root "#{File.dirname __FILE__}/../templates"
10
-
10
+
11
11
  def self.next_migration_number(dirname)
12
12
  if ActiveRecord::Base.timestamped_migrations then
13
- Time.now.utc.strftime "%Y%m%d%H%M%S"
13
+ Time.now.utc.strftime '%Y%m%d%H%M%S'
14
14
  else
15
- "%.3d" % (current_migration_number(dirname) + 1)
15
+ '%.3d' % (current_migration_number(dirname) + 1)
16
16
  end
17
17
  end
18
-
18
+
19
19
  def copy_files
20
- migration_template "add_ltree_type.rb", "db/migrate/add_ltree_type.rb"
20
+ migration_template 'add_ltree_type.rb', 'db/migrate/add_ltree_type.rb'
21
21
  end
22
22
  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,142 @@
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.7
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Tim Morgan
13
- autorequire:
14
8
  bindir: bin
15
9
  cert_chain: []
16
-
17
- date: 2010-11-27 00:00:00 -08:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
10
+ date: 2013-12-08 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
21
13
  name: rails
22
- requirement: &id001 !ruby/object:Gem::Requirement
23
- none: false
24
- requirements:
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
25
16
  - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 3
29
- - 0
30
- - 2
17
+ - !ruby/object:Gem::Version
31
18
  version: 3.0.2
32
19
  type: :runtime
33
20
  prerelease: false
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 3.0.2
26
+ - !ruby/object:Gem::Dependency
27
+ name: pg
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
36
41
  name: jeweler
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
40
44
  - - ">="
41
- - !ruby/object:Gem::Version
42
- segments:
43
- - 0
44
- version: "0"
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
45
47
  type: :development
46
48
  prerelease: false
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
49
55
  name: yard
50
- requirement: &id003 !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
53
58
  - - ">="
54
- - !ruby/object:Gem::Version
55
- segments:
56
- - 0
57
- version: "0"
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
58
61
  type: :development
59
62
  prerelease: false
60
- version_requirements: *id003
61
- - !ruby/object:Gem::Dependency
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
62
69
  name: RedCloth
63
- requirement: &id004 !ruby/object:Gem::Requirement
64
- none: false
65
- requirements:
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
66
72
  - - ">="
67
- - !ruby/object:Gem::Version
68
- segments:
69
- - 0
70
- version: "0"
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
71
75
  type: :development
72
76
  prerelease: false
73
- version_requirements: *id004
74
- - !ruby/object:Gem::Dependency
75
- name: pg
76
- requirement: &id005 !ruby/object:Gem::Requirement
77
- none: false
78
- requirements:
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
79
  - - ">="
80
- - !ruby/object:Gem::Version
81
- segments:
82
- - 0
83
- version: "0"
84
- type: :development
85
- prerelease: false
86
- version_requirements: *id005
87
- - !ruby/object:Gem::Dependency
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
88
83
  name: rspec
89
- requirement: &id006 !ruby/object:Gem::Requirement
90
- none: false
91
- requirements:
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
92
86
  - - ">="
93
- - !ruby/object:Gem::Version
94
- segments:
95
- - 0
96
- version: "0"
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
97
89
  type: :development
98
90
  prerelease: false
99
- version_requirements: *id006
100
- description: Adds ActiveRecord support for hierarchial data structures using PostgreSQL's LTREE column type.
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ description: Adds ActiveRecord support for hierarchical data structures using PostgreSQL's
97
+ LTREE column type.
101
98
  email: git@timothymorgan.info
102
99
  executables: []
103
-
104
100
  extensions: []
105
-
106
- extra_rdoc_files:
101
+ extra_rdoc_files:
107
102
  - LICENSE
108
- - README.textile
109
- files:
110
- - .document
111
- - .rspec
112
- - Gemfile
113
- - Gemfile.lock
103
+ - README.md
104
+ files:
114
105
  - LICENSE
115
- - README.textile
116
- - Rakefile
117
- - VERSION
106
+ - README.md
118
107
  - hierarchy.gemspec
119
108
  - lib/hierarchy.rb
120
109
  - lib/hierarchy/index_path.rb
121
110
  - lib/hierarchy/node.rb
122
111
  - lib/hierarchy_generator.rb
123
- - spec/hierarchy_spec.rb
124
- - spec/index_path_spec.rb
125
- - spec/spec_helper.rb
126
112
  - templates/add_ltree_type.rb
127
- has_rdoc: true
128
113
  homepage: http://github.com/riscfuture/hierarchy
129
114
  licenses: []
115
+ metadata: {}
116
+ post_install_message: |2+
130
117
 
131
- post_install_message:
132
- rdoc_options: []
118
+ ⚠️ DEPRECATED: hierarchy is no longer maintained.
119
+
120
+ No longer maintained. Consider `ancestry`, `closure_tree`, or `acts_as_tree` for tree-structured ActiveRecord data.
121
+
122
+ This is the final release. No further updates are planned.
133
123
 
134
- require_paths:
124
+ rdoc_options: []
125
+ require_paths:
135
126
  - lib
136
- required_ruby_version: !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
139
129
  - - ">="
140
- - !ruby/object:Gem::Version
141
- segments:
142
- - 1
143
- - 9
144
- version: "1.9"
145
- required_rubygems_version: !ruby/object:Gem::Requirement
146
- none: false
147
- requirements:
130
+ - !ruby/object:Gem::Version
131
+ version: '1.9'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
148
134
  - - ">="
149
- - !ruby/object:Gem::Version
150
- segments:
151
- - 0
152
- version: "0"
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
153
137
  requirements: []
154
-
155
- rubyforge_project:
156
- rubygems_version: 1.3.7
157
- signing_key:
158
- specification_version: 3
159
- 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
138
+ rubygems_version: 4.0.11
139
+ specification_version: 4
140
+ summary: "[DEPRECATED] Use PostgreSQL LTREE type with ActiveRecord"
141
+ test_files: []
142
+ ...
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
data/Gemfile.lock DELETED
@@ -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/README.textile DELETED
@@ -1,96 +0,0 @@
1
- h1. Hierarchy -- Use PostgreSQL @LTREE@ columns in ActiveRecord
2
-
3
- | *Author* | Tim Morgan |
4
- | *Version* | 1.0.5 (Nov 27, 2010) |
5
- | *License* | Released under the MIT license. |
6
-
7
- h2. About
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).
13
-
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.
21
-
22
- h2. Installation
23
-
24
- *Important Note:* This gem requires Ruby 1.9 and Rails 3.0.
25
-
26
- Firstly, add the gem to your Rails project's @Gemfile@:
27
-
28
- <pre><code>
29
- gem 'hierarchy'
30
- </code></pre>
31
-
32
- Then, run the generator to install the migration:
33
-
34
- <pre><code>
35
- rails generate hierarchy
36
- </code></pre>
37
-
38
- Note that *this migration must precede any tables using @LTREEs@*, so reorder
39
- the migration if you have to.
40
-
41
- h2. Usage
42
-
43
- Because this gem was hastily extracted from a personal project, it's a little
44
- constraining in how it can be used. (Sorry.) Currently the gem requires that
45
- your table schema have a column named @path@ of type @LTREE@, defined as in the
46
- example below:
47
-
48
- <pre><code>
49
- path LTREE NOT NULL DEFAULT ''
50
- </code></pre>
51
-
52
- Once you've got that column in your model, feel free to include the @Hierarchy@
53
- module:
54
-
55
- <pre><code>
56
- class Person < ActiveRecord::Base
57
- include Hierarchy
58
- end
59
- </code></pre>
60
-
61
- You can now define hierarchy by setting a model's @parent@, like so:
62
-
63
- <pre><code>
64
- person.parent = mother #=> Sets the `path` column appropriately
65
- </code></pre>
66
-
67
- You also have access to a wealth of ways to traverse the hierarchy:
68
-
69
- <pre><code>
70
- person.children.where(gender: :male)
71
- person.top_level?
72
- Person.treeified #=> returns a traversable tree of all people
73
- </code></pre>
74
-
75
- For more information on what you can do, see the {Hierarchy} module
76
- documentation.
77
-
78
- h2. Development
79
-
80
- If you wish to develop for Hierarchy, the first thing you will want to do is get
81
- specs up and running. This requires a call to @bundle install@ (obviously) and
82
- setting up your test database.
83
-
84
- As you can see in the @spec/spec_helper.rb@ file, the specs require that a
85
- PostgreSQL database named @hierarchy_test@ exist and be owned by a
86
- @hierarchy_tester@ user. Unfortunately I haven't written a way to configure this
87
- (though patches are welcome). So, the following commands should suffice to get
88
- you started:
89
-
90
- <pre><code>
91
- createuser hierarchy_tester # answer "no" to all prompts
92
- createdb -O hierarchy_tester hierarchy_test
93
- </code></pre>
94
-
95
- With those steps done you should be able to run @rake spec@ and see the Glorious
96
- Green.
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
data/spec/spec_helper.rb DELETED
@@ -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