pg_ltree 1.1.8 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af73780dad2653e9068d80d56ad53a1cac86f88968cbe9f697bc832e42aedcf6
4
- data.tar.gz: a4bea89ea088fe18ce1a5d5ce9606bceecb1833a36b9ec4ce7b252bcde5e7f83
3
+ metadata.gz: 10ef65e0c0c08d2f3670fb0c688eae0e549d40feded3b2c9e63db1109d50b6e2
4
+ data.tar.gz: c50d76b1d9157dca93b1f49748718300f066b5799672d655aacda68917f48891
5
5
  SHA512:
6
- metadata.gz: '086bcf6439fdfd185d738ab1c120c41192567f8d3e9c1ee456c0ef82bf28d0e6c921d9c9a397ff5cacd7735dfc21605c078ade8927266e6685ef7fefbc1d0b58'
7
- data.tar.gz: 9317b961bd9ae4f6ff781c3aa72bf2b5ee0c5136bb6b2a28482853a8c0262278f5a00daf6d8b4dfd71302d4e2b52975abc8e4f2b0629fffdb03037d95ca51ced
6
+ metadata.gz: 6e6742bfcefacebf4124b782c96b1f4b4ada81da57f41f25ebb2dd2eaed7f5f15b32011fc1f8facda0e5648b6b279b604786216ddd1baf6254bec53be6c1ff5b
7
+ data.tar.gz: 62739b19de39ea1df10d1cd62ea48b981d103b2b54b149ab06f918157637f07f798a9a247811ab4e68b884bee2c85b1e1d15089fce30ec213e69a61bda74cfef
data/Rakefile CHANGED
@@ -1,51 +1,8 @@
1
- require 'bundler/gem_tasks'
1
+ require "bundler/gem_tasks"
2
+ require "standard/rake"
3
+ require "rspec/core/rake_task"
4
+ require "appraisal"
2
5
 
3
- require 'rake/testtask'
4
- require 'rdoc/task'
6
+ RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- gemspec = eval(File.read(Dir['*.gemspec'].first))
7
-
8
- RDoc::Task.new(:rdoc) do |rdoc|
9
- rdoc.rdoc_dir = 'rdoc'
10
- rdoc.title = 'PgLtree'
11
- rdoc.options << '--line-numbers'
12
- rdoc.rdoc_files.include('README.rdoc')
13
- rdoc.rdoc_files.include('lib/**/*.rb')
14
- end
15
-
16
- Rake::TestTask.new(:test) do |t|
17
- t.libs << 'lib'
18
- t.libs << 'test'
19
- t.pattern = 'test/**/*_test.rb'
20
- t.verbose = false
21
- end
22
-
23
- desc 'Default: run unit tests.'
24
- task default: 'test:all'
25
-
26
- namespace :test do
27
- AVAILABLE_CASES = %w(
28
- activerecord_40_pg_017 activerecord_40_pg_018
29
- activerecord_41_pg_017 activerecord_41_pg_018
30
- activerecord_42_pg_017 activerecord_42_pg_018
31
- activerecord_50_pg_018 activerecord_51_pg_020
32
- activerecord_51_pg_021 activerecord_52_pg_100
33
- activerecord_60_pg_021 activerecord_60_pg_100
34
- activerecord_60_pg_110
35
- ).freeze
36
-
37
- AVAILABLE_CASES.each do |version|
38
- desc "Test pg_ltree against #{version}"
39
- task version do
40
- sh "bundle install --gemfile=gemfiles/#{version}.gemfile --quiet"
41
- sh "BUNDLE_GEMFILE='gemfiles/#{version}.gemfile' bundle exec rake -t test"
42
- end
43
- end
44
-
45
- desc 'Run all tests for pg_ltree'
46
- task :all do
47
- AVAILABLE_CASES.each do |version|
48
- sh "rake test:#{version}"
49
- end
50
- end
51
- end
8
+ task default: :spec
@@ -0,0 +1,40 @@
1
+ require_relative "model"
2
+ require_relative "callbacks"
3
+
4
+ module PgLtree
5
+ module Base
6
+ extend ActiveSupport::Concern
7
+
8
+ class_methods do
9
+ attr_reader :ltree_options
10
+
11
+ # Initialize ltree module for the model
12
+ #
13
+ # @param column [String] lTree column name
14
+ # @param cascade_update [Boolean] Update all child nodes when the self path is changed
15
+ # @param cascade_destroy [Boolean] Destroy all child nodes on self-destroying
16
+ def ltree(column = :path, cascade_update: true, cascade_destroy: true, cascade: nil)
17
+ if cascade
18
+ ActiveSupport::Deprecation.warn("'cascade' param is deprecated. Use 'cascade_update' and 'cascade_destroy' instead.")
19
+ end
20
+
21
+ @ltree_options = {
22
+ column: column,
23
+ cascade_update: cascade.nil? ? cascade_update : cascade,
24
+ cascade_destroy: cascade.nil? ? cascade_destroy : cascade
25
+ }
26
+
27
+ send(:include, PgLtree::Model)
28
+ send(:include, PgLtree::Callbacks)
29
+ end
30
+
31
+ def ltree_option_for(key)
32
+ ltree_options[key]
33
+ end
34
+ end
35
+
36
+ included do
37
+ delegate :ltree_option_for, to: :class
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ module PgLtree
2
+ module Callbacks
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ after_commit :cascade_update, on: :update, if: -> { ltree_option_for :cascade_update }
7
+ after_commit :cascade_destroy, on: :destroy, if: -> { ltree_option_for :cascade_destroy }
8
+
9
+ # Update child nodes path
10
+ #
11
+ # @return [ActiveRecord::Relation]
12
+ def cascade_update
13
+ ltree_scope
14
+ .where(["#{self.class.table_name}.#{ltree_path_column} <@ ?", ltree_path_before_last_save])
15
+ .where(["#{self.class.table_name}.#{ltree_path_column} != ?", ltree_path])
16
+ .update_all ["#{ltree_path_column} = ? || subpath(#{ltree_path_column}, nlevel(?))", ltree_path, ltree_path_before_last_save]
17
+ end
18
+
19
+ # Destroy child nodes
20
+ #
21
+ # @return [ActiveRecord::Relation]
22
+ def cascade_destroy
23
+ ltree_scope.where("#{self.class.table_name}.#{ltree_path_column} <@ ?", ltree_path_in_database).destroy_all
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,30 +1,12 @@
1
1
  module PgLtree
2
- # Implementatios Postgres ltree for ActiveRecord
3
- #
4
- # @see [ActiveRecord::Base]
5
- # @see http://www.postgresql.org/docs/current/static/ltree.html
6
- #
7
- # @author a.ponomarenko
8
- module Ltree
9
- # Initialzie ltree for active model
10
- #
11
- # @param column [String] ltree column name
12
- def ltree(column = :path, options: { cascade: true })
13
- cattr_accessor :ltree_path_column
14
-
15
- self.ltree_path_column = column
16
-
17
- if options[:cascade]
18
- after_update :cascade_update
19
- after_destroy :cascade_destroy
20
- end
21
-
22
- extend ClassMethods
23
- include InstanceMethods
24
- end
2
+ module Model
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ def ltree_path_column
7
+ ltree_option_for :column
8
+ end
25
9
 
26
- # Define class methods
27
- module ClassMethods
28
10
  # Get roots
29
11
  #
30
12
  # @return [ActiveRecord::Relation] relations of node's roots
@@ -45,9 +27,9 @@ module PgLtree
45
27
  # @return [ActiveRecord::Relation] relations of node's leaves
46
28
  def leaves
47
29
  subquery = unscoped.select("#{table_name}.#{ltree_path_column}")
48
- .from("#{table_name} AS subquery")
49
- .where("#{table_name}.#{ltree_path_column} <> subquery.#{ltree_path_column}")
50
- .where("#{table_name}.#{ltree_path_column} @> subquery.#{ltree_path_column}")
30
+ .from("#{table_name} AS subquery")
31
+ .where("#{table_name}.#{ltree_path_column} <> subquery.#{ltree_path_column}")
32
+ .where("#{table_name}.#{ltree_path_column} @> subquery.#{ltree_path_column}")
51
33
 
52
34
  where.not ltree_path_column => subquery
53
35
  end
@@ -69,8 +51,7 @@ module PgLtree
69
51
  end
70
52
  end
71
53
 
72
- # Define instance methods
73
- module InstanceMethods
54
+ included do
74
55
  # Get default scope of ltree
75
56
  #
76
57
  # @return current class
@@ -81,9 +62,7 @@ module PgLtree
81
62
  # Get lTree column
82
63
  #
83
64
  # @return [String] ltree column name
84
- def ltree_path_column
85
- ltree_scope.ltree_path_column
86
- end
65
+ delegate :ltree_path_column, to: :ltree_scope
87
66
 
88
67
  # Get lTree value
89
68
  #
@@ -140,21 +119,23 @@ module PgLtree
140
119
  #
141
120
  # return [Object] root node
142
121
  def root
143
- ltree_scope.where("#{ltree_scope.table_name}.#{ltree_path_column} = SUBPATH(?, 0, 1)", ltree_path).first
122
+ ltree_scope.where("#{self.class.table_name}.#{ltree_path_column} = SUBPATH(?, 0, 1)", ltree_path).first
144
123
  end
145
124
 
146
125
  # Get parent of the node
147
126
  #
148
127
  # return [Object] root node
149
128
  def parent
150
- ltree_scope.find_by "#{ltree_scope.table_name}.#{ltree_path_column} = SUBPATH(?, 0, NLEVEL(?) - 1)", ltree_path, ltree_path
129
+ ltree_scope.find_by "#{self.class.table_name}.#{ltree_path_column} = SUBPATH(?, 0, NLEVEL(?) - 1)", ltree_path,
130
+ ltree_path
151
131
  end
152
132
 
153
133
  # Get leaves of the node
154
134
  #
155
135
  # @return [ActiveRecord::Relation]
156
136
  def leaves
157
- ltree_scope.leaves.where("#{ltree_scope.table_name}.#{ltree_path_column} <@ ?", ltree_path).where.not ltree_path_column => ltree_path
137
+ ltree_scope.leaves.where("#{self.class.table_name}.#{ltree_path_column} <@ ?",
138
+ ltree_path).where.not ltree_path_column => ltree_path
158
139
  end
159
140
 
160
141
  # Check what current node have leaves
@@ -168,7 +149,7 @@ module PgLtree
168
149
  #
169
150
  # @return [ActiveRecord::Relation]
170
151
  def self_and_ancestors
171
- ltree_scope.where("#{ltree_scope.table_name}.#{ltree_path_column} @> ?", ltree_path)
152
+ ltree_scope.where("#{self.class.table_name}.#{ltree_path_column} @> ?", ltree_path)
172
153
  end
173
154
 
174
155
  # Get ancestors
@@ -182,15 +163,7 @@ module PgLtree
182
163
  #
183
164
  # @return [ActiveRecord::Relation]
184
165
  def self_and_descendants
185
- ltree_scope.where("#{ltree_scope.table_name}.#{ltree_path_column} <@ ?", ltree_path)
186
- end
187
-
188
- # Get self and descendants
189
- # @deprecated Please use {#self_and_descendants} instead
190
- # @return [ActiveRecord::Relation]
191
- def self_and_descendents
192
- warn '[DEPRECATION] `self_and_descendents` is deprecated. Please use `self_and_descendants` instead.'
193
- self_and_descendants
166
+ ltree_scope.where("#{self.class.table_name}.#{ltree_path_column} <@ ?", ltree_path)
194
167
  end
195
168
 
196
169
  # Get descendants
@@ -200,20 +173,12 @@ module PgLtree
200
173
  self_and_descendants.where.not ltree_path_column => ltree_path
201
174
  end
202
175
 
203
- # Get descendants
204
- # @deprecated Please use {#descendants} instead
205
- # @return [ActiveRecord::Relation]
206
- def descendents
207
- warn '[DEPRECATION] `descendents` is deprecated. Please use `descendants` instead.'
208
- descendants
209
- end
210
-
211
176
  # Get self and siblings
212
177
  #
213
178
  # @return [ActiveRecord::Relation]
214
179
  def self_and_siblings
215
180
  ltree_scope.where(
216
- "SUBPATH(?, 0, NLEVEL(?) - 1) @> #{ltree_scope.table_name}.#{ltree_path_column} AND nlevel(#{ltree_scope.table_name}.#{ltree_path_column}) = NLEVEL(?)",
181
+ "SUBPATH(?, 0, NLEVEL(?) - 1) @> #{self.class.table_name}.#{ltree_path_column} AND nlevel(#{self.class.table_name}.#{ltree_path_column}) = NLEVEL(?)",
217
182
  ltree_path, ltree_path, ltree_path
218
183
  )
219
184
  end
@@ -229,23 +194,25 @@ module PgLtree
229
194
  #
230
195
  # @return [ActiveRecord::Relation]
231
196
  def children
232
- ltree_scope.where "? @> #{ltree_scope.table_name}.#{ltree_path_column} AND nlevel(#{ltree_scope.table_name}.#{ltree_path_column}) = NLEVEL(?) + 1",
233
- ltree_path, ltree_path
197
+ ltree_scope.where "? @> #{self.class.table_name}.#{ltree_path_column} AND nlevel(#{self.class.table_name}.#{ltree_path_column}) = NLEVEL(?) + 1",
198
+ ltree_path, ltree_path
234
199
  end
235
200
 
236
201
  # Update all childen for current path
237
202
  #
238
203
  # @return [ActiveRecord::Relation]
239
204
  def cascade_update
240
- ltree_scope.where(["#{ltree_scope.table_name}.#{ltree_path_column} <@ ?", ltree_path_before_last_save]).where(["#{ltree_scope.table_name}.#{ltree_path_column} != ?", ltree_path])
241
- .update_all ["#{ltree_path_column} = ? || subpath(#{ltree_path_column}, nlevel(?))", ltree_path, ltree_path_before_last_save]
205
+ ltree_scope
206
+ .where("#{self.class.table_name}.#{ltree_path_column} <@ ?", ltree_path_before_last_save)
207
+ .where("#{self.class.table_name}.#{ltree_path_column} != ?", ltree_path)
208
+ .update_all("#{ltree_path_column} = ? || subpath(#{ltree_path_column}, nlevel(?))", ltree_path, ltree_path_before_last_save)
242
209
  end
243
210
 
244
211
  # Delete all children for current path
245
212
  #
246
213
  # @return [ActiveRecord::Relation]
247
214
  def cascade_destroy
248
- ltree_scope.where("#{ltree_scope.table_name}.#{ltree_path_column} <@ ?", ltree_path_in_database).delete_all
215
+ ltree_scope.where("#{self.class.table_name}.#{ltree_path_column} <@ ?", ltree_path_in_database).destroy_all
249
216
  end
250
217
  end
251
218
  end
@@ -1,7 +1,3 @@
1
- # Organize ActiveRecord model into a tree structure with PostgreSQL LTree
2
- #
3
- # @author a.ponomarenko
4
1
  module PgLtree
5
- # Gem Version
6
- VERSION = '1.1.8'.freeze
2
+ VERSION = "1.2.0".freeze
7
3
  end
data/lib/pg_ltree.rb CHANGED
@@ -1,17 +1,9 @@
1
- require 'active_record'
2
- require 'pg_ltree/ltree'
3
- require 'pg_ltree/scoped_for'
4
- require 'pg_ltree/version'
1
+ require "active_support"
5
2
 
6
- Dir[File.expand_path('../pg_ltree/versions/**/*.rb', __FILE__)].each { |file| require file }
7
-
8
- if defined?(ActiveRecord)
9
- ActiveRecord::Base.extend(PgLtree::Ltree)
3
+ module PgLtree
4
+ autoload :Base, "pg_ltree/base"
5
+ end
10
6
 
11
- # The behavior of _was changes in Rails 5.1
12
- # http://blog.toshima.ru/2017/04/06/saved-change-to-attribute.html
13
- # This is for backward compability
14
- if ActiveRecord::VERSION::MAJOR < 5 || (ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR < 1)
15
- ActiveRecord::Base.extend(PgLtree::Versions::RailsOlderThan51)
16
- end
7
+ ActiveSupport.on_load(:active_record) do
8
+ ActiveRecord::Base.include PgLtree::Base
17
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_ltree
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.8
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Panamarenka
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-13 00:00:00.000000000 Z
11
+ date: 2022-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,27 +16,27 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.0
20
- - - "<="
19
+ version: '5.2'
20
+ - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 7.0.0.rc1
22
+ version: '8.0'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 4.0.0
30
- - - "<="
29
+ version: '5.2'
30
+ - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 7.0.0.rc1
32
+ version: '8.0'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: pg
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: 0.17.0
39
+ version: '0.19'
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
42
  version: '2'
@@ -46,7 +46,7 @@ dependencies:
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 0.17.0
49
+ version: '0.19'
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '2'
@@ -93,7 +93,7 @@ dependencies:
93
93
  - !ruby/object:Gem::Version
94
94
  version: '0'
95
95
  - !ruby/object:Gem::Dependency
96
- name: yard
96
+ name: standard
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  requirements:
99
99
  - - ">="
@@ -107,20 +107,62 @@ dependencies:
107
107
  - !ruby/object:Gem::Version
108
108
  version: '0'
109
109
  - !ruby/object:Gem::Dependency
110
- name: minitest
110
+ name: yard
111
111
  requirement: !ruby/object:Gem::Requirement
112
112
  requirements:
113
- - - ">="
113
+ - - "~>"
114
114
  - !ruby/object:Gem::Version
115
- version: '0'
115
+ version: 0.9.28
116
116
  type: :development
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
119
119
  requirements:
120
- - - ">="
120
+ - - "~>"
121
121
  - !ruby/object:Gem::Version
122
- version: '0'
123
- description: Organise ActiveRecord model into a tree structure with PostgreSQL LTree
122
+ version: 0.9.28
123
+ - !ruby/object:Gem::Dependency
124
+ name: appraisal
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '2.4'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '2.4'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rspec
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '3.11'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '3.11'
151
+ - !ruby/object:Gem::Dependency
152
+ name: database_cleaner
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '2.0'
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '2.0'
165
+ description: Organize ActiveRecord model into a tree structure using PostgreSQL LTree
124
166
  email:
125
167
  - andrei.panamarenka@gmail.com
126
168
  executables: []
@@ -130,21 +172,15 @@ files:
130
172
  - MIT-LICENSE
131
173
  - Rakefile
132
174
  - lib/pg_ltree.rb
133
- - lib/pg_ltree/ltree.rb
134
- - lib/pg_ltree/scoped_for.rb
175
+ - lib/pg_ltree/base.rb
176
+ - lib/pg_ltree/callbacks.rb
177
+ - lib/pg_ltree/model.rb
135
178
  - lib/pg_ltree/version.rb
136
- - lib/pg_ltree/versions/rails_older_than_51.rb
137
- - test/database.yml
138
- - test/database.yml.sample
139
- - test/pg_ltree/ltree_test.rb
140
- - test/pg_ltree/scoped_for_test.rb
141
- - test/pg_ltree_test.rb
142
- - test/test_helper.rb
143
179
  homepage: https://github.com/sjke/pg_ltree
144
180
  licenses:
145
181
  - MIT
146
182
  metadata: {}
147
- post_install_message:
183
+ post_install_message:
148
184
  rdoc_options: []
149
185
  require_paths:
150
186
  - lib
@@ -159,14 +195,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
195
  - !ruby/object:Gem::Version
160
196
  version: '0'
161
197
  requirements: []
162
- rubygems_version: 3.1.0.pre2
163
- signing_key:
198
+ rubygems_version: 3.1.6
199
+ signing_key:
164
200
  specification_version: 4
165
- summary: Organise ActiveRecord model into a tree structure with PostgreSQL LTree
166
- test_files:
167
- - test/database.yml.sample
168
- - test/pg_ltree_test.rb
169
- - test/database.yml
170
- - test/pg_ltree/scoped_for_test.rb
171
- - test/pg_ltree/ltree_test.rb
172
- - test/test_helper.rb
201
+ summary: Organize ActiveRecord model into a tree structure using PostgreSQL LTree
202
+ test_files: []
@@ -1,28 +0,0 @@
1
- module PgLtree
2
- # Narrowing the Scope for ActiveRecord Model
3
- # @note When model have composite uniq key (for example: state + path), you should use this module for narrowing the scope
4
- #
5
- # @author a.ponomarenko
6
- module ScopedFor
7
- # Define base instance scope for model by columns
8
- #
9
- # @param columns [Array] List of scoped fields
10
- def ltree_scoped_for(columns = [])
11
- cattr_accessor :ltree_scoped_for
12
-
13
- self.ltree_scoped_for = Array.wrap(columns)
14
-
15
- include InstanceMethods
16
- end
17
-
18
- # Define instance methods
19
- module InstanceMethods
20
- # Get default scope of ltree
21
- #
22
- # @return current class
23
- def ltree_scope
24
- self.class.where *(ltree_scoped_for.map { |column| { column => public_send(column) } })
25
- end
26
- end
27
- end
28
- end
@@ -1,28 +0,0 @@
1
- module PgLtree
2
- module Versions
3
- module RailsOlderThan51
4
- def ltree(column = :path, options: { cascade: true })
5
- super
6
- include InstanceMethods
7
- end
8
-
9
- module InstanceMethods
10
- # Get lTree previous value
11
- #
12
- # Related changes in > Rails 5.1.0
13
- # https://github.com/rails/rails/pull/25337
14
- #
15
- # @return [String] Rails 5.1 replace attribute_was method with two methods, this is a wrapper for older rails
16
- def ltree_path_before_last_save
17
- public_send :attribute_was, ltree_path_column
18
- end
19
-
20
- #
21
- # @return [String] Rails 5.1 replace attribute_was method with two methods, this is a wrapper for older rails
22
- def ltree_path_in_database
23
- public_send :attribute_was, ltree_path_column
24
- end
25
- end
26
- end
27
- end
28
- end
data/test/database.yml DELETED
@@ -1,5 +0,0 @@
1
- adapter: postgresql
2
- host: localhost
3
- username: postgres
4
- password:
5
- database: pg_ltree_test
@@ -1,5 +0,0 @@
1
- adapter: postgresql
2
- host: localhost
3
- username: postgres
4
- password:
5
- database: pg_ltree_test
@@ -1,198 +0,0 @@
1
- require 'test_helper'
2
-
3
- class PgLtree::LtreeTest < BaseTest
4
- def setup
5
- super
6
- %w(
7
- Top
8
- Top.Science
9
- Top.Science.Astronomy
10
- Top.Science.Astronomy.Astrophysics
11
- Top.Science.Astronomy.Cosmology
12
- Top.Hobbies
13
- Top.Hobbies.Amateurs_Astronomy
14
- Top.Collections
15
- Top.Collections.Pictures
16
- Top.Collections.Pictures.Astronomy
17
- Top.Collections.Pictures.Astronomy.Stars
18
- Top.Collections.Pictures.Astronomy.Galaxies
19
- Top.Collections.Pictures.Astronomy.Astronauts
20
- ).each do |path|
21
- TreeNode.create! path: path
22
- end
23
- end
24
-
25
- test 'Default configuration' do
26
- assert_equal TreeNode.ltree_path_column, :path
27
- end
28
-
29
- test 'Custom configuration' do
30
- assert_equal NotUniqTreeNode.ltree_path_column, :new_path
31
- end
32
-
33
- test '#roots' do
34
- assert_equal TreeNode.roots.pluck(:path), ['Top']
35
- end
36
-
37
- test '#at_depth' do
38
- assert_equal TreeNode.at_depth(5).pluck(:path), %w(
39
- Top.Collections.Pictures.Astronomy.Stars
40
- Top.Collections.Pictures.Astronomy.Galaxies
41
- Top.Collections.Pictures.Astronomy.Astronauts
42
- )
43
- end
44
-
45
- test '#leaves' do
46
- assert_equal TreeNode.leaves.pluck(:path), %w(
47
- Top.Science.Astronomy.Astrophysics
48
- Top.Science.Astronomy.Cosmology
49
- Top.Hobbies.Amateurs_Astronomy
50
- Top.Collections.Pictures.Astronomy.Stars
51
- Top.Collections.Pictures.Astronomy.Galaxies
52
- Top.Collections.Pictures.Astronomy.Astronauts
53
- )
54
- end
55
-
56
- test '#leaves with a relation' do
57
- assert_equal TreeNode.where("path <> 'Top.Collections.Pictures.Astronomy.Stars'").leaves.pluck(:path), %w(
58
- Top.Science.Astronomy.Astrophysics
59
- Top.Science.Astronomy.Cosmology
60
- Top.Hobbies.Amateurs_Astronomy
61
- Top.Collections.Pictures.Astronomy.Galaxies
62
- Top.Collections.Pictures.Astronomy.Astronauts
63
- )
64
- end
65
-
66
- test '#where_path_liked' do
67
- assert_equal TreeNode.where_path_liked('*{2}.Astronomy|Pictures').pluck(:path), %w(
68
- Top.Science.Astronomy
69
- Top.Collections.Pictures
70
- )
71
- end
72
-
73
- test '#where_path_matches_ltxtquery' do
74
- assert_equal TreeNode.where_path_matches_ltxtquery('Astro*% & !pictures@').pluck(:path), %w(
75
- Top.Science.Astronomy
76
- Top.Science.Astronomy.Astrophysics
77
- Top.Science.Astronomy.Cosmology
78
- Top.Hobbies.Amateurs_Astronomy
79
- )
80
- end
81
-
82
- test '.root?' do
83
- assert TreeNode.find_by(path: 'Top').root?
84
- assert_not TreeNode.find_by(path: 'Top.Science').root?
85
- end
86
-
87
- test '.height' do
88
- assert_equal 4, TreeNode.find_by(path: 'Top').height
89
- assert_equal 0, TreeNode.find_by(path: 'Top.Science.Astronomy.Astrophysics').height
90
- end
91
-
92
- test '.depth' do
93
- assert_equal TreeNode.find_by(path: 'Top.Hobbies.Amateurs_Astronomy').depth, 3
94
- end
95
-
96
- test '.depth on new record' do
97
- assert_equal TreeNode.new(path: 'Top.Hobbies.Amateurs_Astronomy').depth, 3
98
- end
99
-
100
- test '.depth on new record when database is empty' do
101
- TreeNode.delete_all
102
- assert_equal TreeNode.new(path: 'Top.Hobbies.Amateurs_Astronomy').depth, 3
103
- end
104
-
105
- test '.root' do
106
- assert_equal TreeNode.find_by(path: 'Top.Hobbies.Amateurs_Astronomy').root.path, 'Top'
107
- end
108
-
109
- test '.parent' do
110
- assert_equal TreeNode.find_by(path: 'Top.Collections.Pictures.Astronomy.Astronauts').parent.path,
111
- 'Top.Collections.Pictures.Astronomy'
112
- end
113
-
114
- test '.leaves' do
115
- assert_equal TreeNode.find_by(path: 'Top.Science').leaves.pluck(:path), %w(
116
- Top.Science.Astronomy.Astrophysics
117
- Top.Science.Astronomy.Cosmology
118
- )
119
- end
120
-
121
- test '.leaf?' do
122
- assert_not TreeNode.find_by(path: 'Top').leaf?
123
- assert TreeNode.find_by(path: 'Top.Collections.Pictures.Astronomy.Astronauts').leaf?
124
- end
125
-
126
- test '.self_and_ancestors' do
127
- assert_equal TreeNode.find_by(path: 'Top.Collections.Pictures.Astronomy.Astronauts').self_and_ancestors.pluck(:path), %w(
128
- Top
129
- Top.Collections
130
- Top.Collections.Pictures
131
- Top.Collections.Pictures.Astronomy
132
- Top.Collections.Pictures.Astronomy.Astronauts
133
- )
134
- end
135
-
136
- test '.ancestors' do
137
- assert_equal TreeNode.find_by(path: 'Top.Collections.Pictures.Astronomy.Astronauts').ancestors.pluck(:path), %w(
138
- Top
139
- Top.Collections
140
- Top.Collections.Pictures
141
- Top.Collections.Pictures.Astronomy
142
- )
143
- end
144
-
145
- test '.self_and_descendants' do
146
- assert_equal TreeNode.find_by(path: 'Top.Science').self_and_descendants.pluck(:path), %w(
147
- Top.Science
148
- Top.Science.Astronomy
149
- Top.Science.Astronomy.Astrophysics
150
- Top.Science.Astronomy.Cosmology
151
- )
152
- end
153
-
154
- test '.descendants' do
155
- assert_equal TreeNode.find_by(path: 'Top.Science').descendants.pluck(:path), %w(
156
- Top.Science.Astronomy
157
- Top.Science.Astronomy.Astrophysics
158
- Top.Science.Astronomy.Cosmology
159
- )
160
- end
161
-
162
- test '.self_and_siblings' do
163
- assert_equal TreeNode.find_by(path: 'Top.Collections.Pictures.Astronomy.Stars').self_and_siblings.pluck(:path), %w(
164
- Top.Collections.Pictures.Astronomy.Stars
165
- Top.Collections.Pictures.Astronomy.Galaxies
166
- Top.Collections.Pictures.Astronomy.Astronauts
167
- )
168
- end
169
-
170
- test '.siblings' do
171
- assert_equal TreeNode.find_by(path: 'Top.Collections.Pictures.Astronomy.Stars').siblings.pluck(:path), %w(
172
- Top.Collections.Pictures.Astronomy.Galaxies
173
- Top.Collections.Pictures.Astronomy.Astronauts
174
- )
175
- end
176
-
177
- test '.children' do
178
- assert_equal TreeNode.find_by(path: 'Top.Hobbies').children.pluck(:path), %w(
179
- Top.Hobbies.Amateurs_Astronomy
180
- )
181
- end
182
-
183
- test '.cascade_update' do
184
- node = TreeNode.find_by(path: 'Top.Hobbies')
185
- node.update path: 'Top.WoW'
186
-
187
- assert_equal node.self_and_descendants.pluck(:path), %w(
188
- Top.WoW
189
- Top.WoW.Amateurs_Astronomy
190
- )
191
- end
192
-
193
- test '.cascade_destroy' do
194
- TreeNode.find_by(path: 'Top.Collections').destroy
195
-
196
- assert_equal TreeNode.where("path ~ 'Top.Collections'").pluck(:path), %w()
197
- end
198
- end
@@ -1,192 +0,0 @@
1
- require 'test_helper'
2
-
3
- class PgLtree::ScopedForTest < BaseTest
4
- def setup
5
- super
6
- %w(
7
- Top
8
- Top.Science
9
- Top.Science.Astronomy
10
- Top.Science.Astronomy.Astrophysics
11
- Top.Science.Astronomy.Cosmology
12
- Top.Hobbies
13
- Top.Hobbies.Amateurs_Astronomy
14
- Top.Collections
15
- Top.Collections.Pictures
16
- Top.Collections.Pictures.Astronomy
17
- Top.Collections.Pictures.Astronomy.Stars
18
- Top.Collections.Pictures.Astronomy.Galaxies
19
- Top.Collections.Pictures.Astronomy.Astronauts
20
- ).each do |path|
21
- %i( active deactive ).each do |status|
22
- NotUniqTreeNode.create! new_path: path, status: status
23
- end
24
- end
25
- end
26
-
27
- test '#roots' do
28
- assert_equal NotUniqTreeNode.roots.pluck(:new_path), %w(Top Top)
29
- end
30
-
31
- test '#at_depth' do
32
- assert_equal NotUniqTreeNode.at_depth(5).pluck(:new_path), %w(
33
- Top.Collections.Pictures.Astronomy.Stars
34
- Top.Collections.Pictures.Astronomy.Stars
35
- Top.Collections.Pictures.Astronomy.Galaxies
36
- Top.Collections.Pictures.Astronomy.Galaxies
37
- Top.Collections.Pictures.Astronomy.Astronauts
38
- Top.Collections.Pictures.Astronomy.Astronauts
39
- )
40
- end
41
-
42
- test '#leaves' do
43
- assert_equal NotUniqTreeNode.where(status: :active).leaves.pluck(:new_path), %w(
44
- Top.Science.Astronomy.Astrophysics
45
- Top.Science.Astronomy.Cosmology
46
- Top.Hobbies.Amateurs_Astronomy
47
- Top.Collections.Pictures.Astronomy.Stars
48
- Top.Collections.Pictures.Astronomy.Galaxies
49
- Top.Collections.Pictures.Astronomy.Astronauts
50
- )
51
- end
52
-
53
- test '#where_path_liked' do
54
- assert_equal NotUniqTreeNode.where_path_liked('*{2}.Astronomy|Pictures').pluck(:new_path), %w(
55
- Top.Science.Astronomy
56
- Top.Science.Astronomy
57
- Top.Collections.Pictures
58
- Top.Collections.Pictures
59
- )
60
- end
61
-
62
- def not_uniq_tree_node_find_by_path(path)
63
- NotUniqTreeNode.find_by(status: :active, new_path: path)
64
- end
65
-
66
- test '.root?' do
67
- assert not_uniq_tree_node_find_by_path('Top').root?
68
- assert_not not_uniq_tree_node_find_by_path('Top.Science').root?
69
- end
70
-
71
- test '.depth' do
72
- assert_equal not_uniq_tree_node_find_by_path('Top.Hobbies.Amateurs_Astronomy').depth, 3
73
- end
74
-
75
- test '.root' do
76
- assert_equal not_uniq_tree_node_find_by_path('Top.Hobbies.Amateurs_Astronomy').root.new_path, 'Top'
77
- end
78
-
79
- test '.parent' do
80
- assert_equal not_uniq_tree_node_find_by_path('Top.Collections.Pictures.Astronomy.Astronauts').parent.new_path,
81
- 'Top.Collections.Pictures.Astronomy'
82
- end
83
-
84
- test '.leaves' do
85
- assert_equal not_uniq_tree_node_find_by_path('Top.Science').leaves.pluck(:new_path), %w(
86
- Top.Science.Astronomy.Astrophysics
87
- Top.Science.Astronomy.Cosmology
88
- )
89
- end
90
-
91
- test '.leaf?' do
92
- assert_not not_uniq_tree_node_find_by_path('Top').leaf?
93
- assert not_uniq_tree_node_find_by_path('Top.Collections.Pictures.Astronomy.Astronauts').leaf?
94
- end
95
-
96
- test '.self_and_ancestors' do
97
- assert_equal not_uniq_tree_node_find_by_path('Top.Collections.Pictures.Astronomy.Astronauts').self_and_ancestors.pluck(:new_path), %w(
98
- Top
99
- Top.Collections
100
- Top.Collections.Pictures
101
- Top.Collections.Pictures.Astronomy
102
- Top.Collections.Pictures.Astronomy.Astronauts
103
- )
104
- end
105
-
106
- test '.ancestors' do
107
- assert_equal not_uniq_tree_node_find_by_path('Top.Collections.Pictures.Astronomy.Astronauts').ancestors.pluck(:new_path), %w(
108
- Top
109
- Top.Collections
110
- Top.Collections.Pictures
111
- Top.Collections.Pictures.Astronomy
112
- )
113
- end
114
-
115
- test '.self_and_descendants' do
116
- assert_equal not_uniq_tree_node_find_by_path('Top.Science').self_and_descendants.pluck(:new_path), %w(
117
- Top.Science
118
- Top.Science.Astronomy
119
- Top.Science.Astronomy.Astrophysics
120
- Top.Science.Astronomy.Cosmology
121
- )
122
- end
123
-
124
- test '.descendants' do
125
- assert_equal not_uniq_tree_node_find_by_path('Top.Science').descendants.pluck(:new_path), %w(
126
- Top.Science.Astronomy
127
- Top.Science.Astronomy.Astrophysics
128
- Top.Science.Astronomy.Cosmology
129
- )
130
- end
131
-
132
- test '.self_and_siblings' do
133
- assert_equal not_uniq_tree_node_find_by_path('Top.Collections.Pictures.Astronomy.Stars').self_and_siblings.pluck(:new_path), %w(
134
- Top.Collections.Pictures.Astronomy.Stars
135
- Top.Collections.Pictures.Astronomy.Galaxies
136
- Top.Collections.Pictures.Astronomy.Astronauts
137
- )
138
- end
139
-
140
- test '.siblings' do
141
- assert_equal not_uniq_tree_node_find_by_path('Top.Collections.Pictures.Astronomy.Stars').siblings.pluck(:new_path), %w(
142
- Top.Collections.Pictures.Astronomy.Galaxies
143
- Top.Collections.Pictures.Astronomy.Astronauts
144
- )
145
- end
146
-
147
- test '.children' do
148
- assert_equal not_uniq_tree_node_find_by_path('Top.Hobbies').children.pluck(:new_path), %w(
149
- Top.Hobbies.Amateurs_Astronomy
150
- )
151
- end
152
-
153
- test '.cascade_update' do
154
- node = NotUniqTreeNode.find_by(new_path: 'Top.Hobbies', status: :active)
155
- node.update new_path: 'Top.WoW'
156
-
157
- assert_equal node.self_and_descendants.pluck(:new_path), %w(
158
- Top.WoW
159
- Top.WoW.Amateurs_Astronomy
160
- )
161
- end
162
-
163
- test '.cascade_destroy' do
164
- assert_equal NotUniqTreeNode.where("new_path <@ 'Top.Collections'").pluck(:new_path), %w(
165
- Top.Collections
166
- Top.Collections
167
- Top.Collections.Pictures
168
- Top.Collections.Pictures
169
- Top.Collections.Pictures.Astronomy
170
- Top.Collections.Pictures.Astronomy
171
- Top.Collections.Pictures.Astronomy.Stars
172
- Top.Collections.Pictures.Astronomy.Stars
173
- Top.Collections.Pictures.Astronomy.Galaxies
174
- Top.Collections.Pictures.Astronomy.Galaxies
175
- Top.Collections.Pictures.Astronomy.Astronauts
176
- Top.Collections.Pictures.Astronomy.Astronauts
177
- )
178
-
179
- NotUniqTreeNode.find_by(new_path: 'Top.Collections', status: :active).destroy
180
-
181
- assert_equal NotUniqTreeNode.where("new_path <@ 'Top.Collections'").where(status: :active).pluck(:new_path), %w()
182
-
183
- assert_equal NotUniqTreeNode.where("new_path <@ 'Top.Collections'").where(status: :deactive).pluck(:new_path), %w(
184
- Top.Collections
185
- Top.Collections.Pictures
186
- Top.Collections.Pictures.Astronomy
187
- Top.Collections.Pictures.Astronomy.Stars
188
- Top.Collections.Pictures.Astronomy.Galaxies
189
- Top.Collections.Pictures.Astronomy.Astronauts
190
- )
191
- end
192
- end
@@ -1,7 +0,0 @@
1
- require 'test_helper'
2
-
3
- class PgLtreeTest < ActiveSupport::TestCase
4
- test 'truth' do
5
- assert_kind_of Module, PgLtree
6
- end
7
- end
data/test/test_helper.rb DELETED
@@ -1,78 +0,0 @@
1
- require 'bundler'
2
- begin
3
- Bundler.require(:default, :development)
4
- rescue Bundler::BundlerError => e
5
- $stderr.puts e.message
6
- $stderr.puts 'Run `bundle install` to install missing gems'
7
- exit e.status_code
8
- end
9
-
10
- require 'pg'
11
- require 'pg_ltree'
12
- require 'minitest/autorun'
13
-
14
- class BaseTest < ActiveSupport::TestCase
15
- def setup
16
- prepare_db
17
- end
18
-
19
- def teardown
20
- drop_db
21
- end
22
-
23
- private
24
-
25
- def prepare_db
26
- begin
27
- db_connection = YAML.load_file(File.expand_path('../database.yml', __FILE__))
28
- rescue => e
29
- $stderr.puts e.message
30
- $stderr.puts 'Copy `test/database.yml.sample` to `test/database.yml` and configure connection to DB'
31
- exit 0
32
- end
33
-
34
- begin
35
- PG.connect(host: db_connection["host"], user: db_connection["username"], password: db_connection["password"])
36
- .exec("CREATE DATABASE #{db_connection['database']}")
37
- rescue
38
- # Ignore errors on DB:CEATE
39
- end
40
-
41
- ActiveRecord::Base.establish_connection db_connection
42
- ActiveRecord::Schema.verbose = false
43
-
44
- ActiveRecord::Schema.define(version: 1) do
45
- enable_extension 'plpgsql'
46
- enable_extension 'ltree'
47
-
48
- create_table 'not_uniq_tree_nodes', force: :cascade do |t|
49
- t.string 'status'
50
- t.ltree 'new_path'
51
- end
52
-
53
- create_table 'tree_nodes', force: :cascade do |t|
54
- t.ltree 'path'
55
- end
56
- end
57
- end
58
-
59
- def drop_db
60
- tables = if ActiveRecord::VERSION::MAJOR < 5
61
- ActiveRecord::Base.connection.tables
62
- else
63
- ActiveRecord::Base.connection.data_sources
64
- end
65
- tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
66
- end
67
- end
68
-
69
- class NotUniqTreeNode < ActiveRecord::Base
70
- extend PgLtree::ScopedFor
71
-
72
- ltree :new_path
73
- ltree_scoped_for :status
74
- end
75
-
76
- class TreeNode < ActiveRecord::Base
77
- ltree
78
- end