activerecord-hierarchical_query 1.0.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +71 -49
- data/lib/active_record/hierarchical_query/cte/columns.rb +17 -3
- data/lib/active_record/hierarchical_query/cte/non_recursive_term.rb +8 -2
- data/lib/active_record/hierarchical_query/cte/recursive_term.rb +8 -2
- data/lib/active_record/hierarchical_query/cte/union_term.rb +10 -2
- data/lib/active_record/hierarchical_query/join_builder.rb +27 -6
- data/lib/active_record/hierarchical_query/version.rb +1 -1
- data/lib/arel/nodes/postgresql.rb +1 -1
- data/spec/active_record/hierarchical_query_spec.rb +12 -0
- data/spec/spec_helper.rb +24 -9
- data/spec/support/models.rb +10 -0
- metadata +41 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b5166c41ef62af29c1883f5b6e3f3447ba422bf76bae1bf5672f1f4991bbda08
|
4
|
+
data.tar.gz: 519b6c33c67c1b3e69578ca7abf693f1076a69f9d7f45cec5b800b954f17c7a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21208d283a34594e442d19023db12e2d8cf3f79b04a55c397ce1dd97b5ccc6990db05a799b1a71a85410d5c2a905b7ba5e3791cbcb83e34611d138afe8c044d9
|
7
|
+
data.tar.gz: e54b02481e06962334aa9627c1fa1971dd92960aa5d2247dd4172a82f59738bcb5d10cafbc65efe8e8dcf373d81da7e4544e3fc0c938937fd33e343f7e672cd7
|
data/README.md
CHANGED
@@ -3,12 +3,32 @@
|
|
3
3
|
[![Build Status](https://travis-ci.org/take-five/activerecord-hierarchical_query.png?branch=master)](https://travis-ci.org/take-five/activerecord-hierarchical_query)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/take-five/activerecord-hierarchical_query.png)](https://codeclimate.com/github/take-five/activerecord-hierarchical_query)
|
5
5
|
[![Coverage Status](https://coveralls.io/repos/take-five/activerecord-hierarchical_query/badge.png)](https://coveralls.io/r/take-five/activerecord-hierarchical_query)
|
6
|
-
[![Dependency Status](https://gemnasium.com/take-five/activerecord-hierarchical_query.png)](https://gemnasium.com/take-five/activerecord-hierarchical_query)
|
7
6
|
[![Gem Version](https://badge.fury.io/rb/activerecord-hierarchical_query.png)](http://badge.fury.io/rb/activerecord-hierarchical_query)
|
8
7
|
|
9
|
-
Create hierarchical queries using simple DSL, recursively
|
8
|
+
Create hierarchical queries using simple DSL, recursively
|
9
|
+
traverse trees using single SQL query.
|
10
10
|
|
11
|
-
If a table contains hierarchical data, then you can select rows
|
11
|
+
If a table contains hierarchical data, then you can select rows
|
12
|
+
in hierarchical order using hierarchical query builder.
|
13
|
+
|
14
|
+
## Requirements
|
15
|
+
|
16
|
+
- ActiveRecord >= 5.0, < 6.1
|
17
|
+
- PostgreSQL >= 8.4
|
18
|
+
- Postgres Gem >= 0.21, < 1.2
|
19
|
+
|
20
|
+
Note that though PostgresSQL 8.4 and up should work, this library
|
21
|
+
is tested on PostgresSQL 10.5.
|
22
|
+
|
23
|
+
### Rails Version
|
24
|
+
|
25
|
+
**Rails 4 support has ended.**
|
26
|
+
|
27
|
+
If you have trouble with Rails 5.1 or 5.0, try upgrading to Rails 5.2
|
28
|
+
first. Rails 6 should work, but please report issues immediately as
|
29
|
+
support is recent.
|
30
|
+
|
31
|
+
## In a nutshell
|
12
32
|
|
13
33
|
### Traverse trees
|
14
34
|
|
@@ -59,25 +79,12 @@ records = Category.join_recursive do |query|
|
|
59
79
|
.connect_by(parent_id: :id)
|
60
80
|
end.order('depth ASC')
|
61
81
|
|
62
|
-
#
|
82
|
+
# returns a regular ActiveRecord::Relation instance
|
83
|
+
# so methods like `pluck` all work as expected.
|
84
|
+
|
63
85
|
crumbs = records.pluck(:name).join(' / ')
|
64
86
|
```
|
65
87
|
|
66
|
-
## Requirements
|
67
|
-
|
68
|
-
* ActiveRecord >= 3.1.0
|
69
|
-
* PostgreSQL >= 8.4
|
70
|
-
|
71
|
-
## Rails 5
|
72
|
-
|
73
|
-
Rails 5 is supported on the `rails-5` branch and through gem versions
|
74
|
-
`>= 1.0.0` on rubygems.org. The Rails branch is intended to
|
75
|
-
follow minor Rails releases (currently 5.1), but it should be
|
76
|
-
compatible with 5.0 as well. If you have trouble try upgrading Rails
|
77
|
-
first. Tag @zachaysan with in a GitHub issue if the latest version
|
78
|
-
of Rails is not supported or if there are reproducable problems on
|
79
|
-
the latest minor version of Rails 5.
|
80
|
-
|
81
88
|
## Installation
|
82
89
|
|
83
90
|
Add this line to your application's Gemfile:
|
@@ -106,12 +113,12 @@ Alternatively, the require can be placed in the `Gemfile`:
|
|
106
113
|
gem 'activerecord-hierarchical_query', require: 'active_record/hierarchical_query'
|
107
114
|
```
|
108
115
|
|
109
|
-
|
110
116
|
## Usage
|
111
117
|
|
112
|
-
Let's say you've got an ActiveRecord model `Category` with
|
113
|
-
and `name`. You can traverse nodes
|
114
|
-
|
118
|
+
Let's say you've got an ActiveRecord model `Category` with
|
119
|
+
attributes `id`, `parent_id` and `name`. You can traverse nodes
|
120
|
+
recursively starting from root rows connected by `parent_id`
|
121
|
+
column ordered by `name`:
|
115
122
|
|
116
123
|
```ruby
|
117
124
|
Category.join_recursive do
|
@@ -123,13 +130,15 @@ end
|
|
123
130
|
|
124
131
|
Hierarchical queries consist of these important clauses:
|
125
132
|
|
126
|
-
|
133
|
+
- **START WITH** clause
|
127
134
|
|
128
135
|
This clause specifies the root row(s) of the hierarchy.
|
129
|
-
|
136
|
+
|
137
|
+
- **CONNECT BY** clause
|
130
138
|
|
131
139
|
This clause specifies relationship between parent rows and child rows of the hierarchy.
|
132
|
-
|
140
|
+
|
141
|
+
- **ORDER SIBLINGS** clause
|
133
142
|
|
134
143
|
This clause specifies an order of rows in which they appear on each hierarchy level.
|
135
144
|
|
@@ -137,14 +146,16 @@ These terms are borrowed from [Oracle hierarchical queries syntax](http://docs.o
|
|
137
146
|
|
138
147
|
Hierarchical queries are processed as follows:
|
139
148
|
|
140
|
-
|
149
|
+
- First, root rows are selected -- those rows that satisfy `START WITH` condition in
|
141
150
|
order specified by `ORDER SIBLINGS` clause. In example above it's specified by
|
142
151
|
statements `query.start_with(parent_id: nil)` and `query.order_siblings(:name)`.
|
143
|
-
|
152
|
+
|
153
|
+
- Second, child rows for each root rows are selected. Each child row must satisfy
|
144
154
|
condition specified by `CONNECT BY` clause with respect to one of the root rows
|
145
155
|
(`query.connect_by(id: :parent_id)` in example above). Order of child rows is
|
146
156
|
also specified by `ORDER SIBLINGS` clause.
|
147
|
-
|
157
|
+
|
158
|
+
- Successive generations of child rows are selected with respect to `CONNECT BY` clause.
|
148
159
|
First the children of each row selected in step 2 selected, then the children of those
|
149
160
|
children and so on.
|
150
161
|
|
@@ -201,7 +212,8 @@ Category.join_recursive do
|
|
201
212
|
end
|
202
213
|
```
|
203
214
|
|
204
|
-
You can even refer to parent table, just don't forget to include
|
215
|
+
You can even refer to parent table, just don't forget to include
|
216
|
+
columns in `SELECT` clause!
|
205
217
|
|
206
218
|
```ruby
|
207
219
|
Category.join_recursive do |query|
|
@@ -222,8 +234,9 @@ end
|
|
222
234
|
|
223
235
|
### NOCYCLE
|
224
236
|
|
225
|
-
Recursive query will loop if hierarchy contains cycles (your
|
226
|
-
`NOCYCLE` clause, which is turned off by
|
237
|
+
Recursive query will loop if hierarchy contains cycles (your
|
238
|
+
graph is not acyclic). `NOCYCLE` clause, which is turned off by
|
239
|
+
default, could prevent it.
|
227
240
|
|
228
241
|
Loop example:
|
229
242
|
|
@@ -235,7 +248,8 @@ node_1.parent = node_2
|
|
235
248
|
node_1.save
|
236
249
|
```
|
237
250
|
|
238
|
-
`node_1` and `node_2` now link to each other, so following
|
251
|
+
`node_1` and `node_2` now link to each other, so the following
|
252
|
+
query will not terminate:
|
239
253
|
|
240
254
|
```ruby
|
241
255
|
Category.join_recursive do |query|
|
@@ -255,8 +269,11 @@ end
|
|
255
269
|
```
|
256
270
|
|
257
271
|
## DISTINCT
|
258
|
-
|
259
|
-
|
272
|
+
|
273
|
+
By default, the union term in the Common Table Expression uses a
|
274
|
+
`UNION ALL`. If you want to `SELECT DISTINCT` CTE values, add a
|
275
|
+
query option for `distinct`:
|
276
|
+
|
260
277
|
```ruby
|
261
278
|
Category.join_recursive do |query|
|
262
279
|
query.connect_by(id: :parent_id)
|
@@ -265,7 +282,9 @@ Category.join_recursive do |query|
|
|
265
282
|
end
|
266
283
|
```
|
267
284
|
|
268
|
-
If you want to join CTE terms by `UNION DISTINCT`, pass an option
|
285
|
+
If you want to join CTE terms by `UNION DISTINCT`, pass an option
|
286
|
+
to `join_recursive`:
|
287
|
+
|
269
288
|
```ruby
|
270
289
|
Category.join_recursive(union_type: :distinct) do |query|
|
271
290
|
query.connect_by(id: :parent_id)
|
@@ -291,7 +310,7 @@ Category.join_recursive do |query|
|
|
291
310
|
end
|
292
311
|
```
|
293
312
|
|
294
|
-
|
313
|
+
Would generate following SQL:
|
295
314
|
|
296
315
|
```sql
|
297
316
|
SELECT "categories".*
|
@@ -324,27 +343,30 @@ FROM "categories" INNER JOIN (
|
|
324
343
|
ORDER BY "categories__recursive"."__order_column" ASC
|
325
344
|
```
|
326
345
|
|
327
|
-
If you want to use a `LEFT OUTER JOIN` instead of an `INNER JOIN`,
|
346
|
+
If you want to use a `LEFT OUTER JOIN` instead of an `INNER JOIN`,
|
347
|
+
add a query option for `outer_join_hierarchical`. This
|
348
|
+
option allows the query to return non-hierarchical entries:
|
349
|
+
|
328
350
|
```ruby
|
329
351
|
.join_recursive(outer_join_hierarchical: true)
|
330
352
|
```
|
331
353
|
|
332
|
-
If, when joining the recursive view to the main table, you want
|
354
|
+
If, when joining the recursive view to the main table, you want
|
355
|
+
to change the foreign_key on the recursive view from the primary
|
356
|
+
key of the main table to another column:
|
357
|
+
|
333
358
|
```ruby
|
334
|
-
.join_recursive(foreign_key: another_column)
|
359
|
+
.join_recursive(foreign_key: another_column)
|
335
360
|
```
|
336
361
|
|
337
362
|
## Related resources
|
338
363
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
364
|
+
- [About hierarchical queries (Wikipedia)](http://en.wikipedia.org/wiki/Hierarchical_and_recursive_queries_in_SQL)
|
365
|
+
- [Hierarchical queries in Oracle](http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm)
|
366
|
+
- [Recursive queries in PostgreSQL](http://www.postgresql.org/docs/9.3/static/queries-with.html)
|
367
|
+
- [Using Recursive SQL with ActiveRecord trees](http://hashrocket.com/blog/posts/recursive-sql-in-activerecord)
|
343
368
|
|
344
369
|
## Contributing
|
345
370
|
|
346
|
-
|
347
|
-
|
348
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
349
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
350
|
-
5. Create new Pull Request
|
371
|
+
Read through the short
|
372
|
+
[contributing guide](https://github.com/take-five/activerecord-hierarchical_query/blob/master/CONTRIBUTING.md).
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'arel/visitors/depth_first'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module HierarchicalQuery
|
5
3
|
module CTE
|
@@ -18,7 +16,23 @@ module ActiveRecord
|
|
18
16
|
|
19
17
|
private
|
20
18
|
def connect_by_columns
|
21
|
-
|
19
|
+
columns = []
|
20
|
+
traverse(@query.join_conditions) do |node|
|
21
|
+
columns << node.name.to_s if node.is_a?(Arel::Attributes::Attribute)
|
22
|
+
end
|
23
|
+
columns
|
24
|
+
end
|
25
|
+
|
26
|
+
def traverse(ast, &blck)
|
27
|
+
if ast && ast.respond_to?(:left) && ast.left
|
28
|
+
traverse(ast.left, &blck)
|
29
|
+
end
|
30
|
+
|
31
|
+
if ast && ast.respond_to?(:right) && ast.right
|
32
|
+
traverse(ast.right, &blck)
|
33
|
+
end
|
34
|
+
|
35
|
+
yield ast
|
22
36
|
end
|
23
37
|
end
|
24
38
|
end
|
@@ -14,8 +14,14 @@ module ActiveRecord
|
|
14
14
|
@builder = builder
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
if ActiveRecord.version < Gem::Version.new("5.2")
|
18
|
+
def bind_values
|
19
|
+
scope.bound_attributes
|
20
|
+
end
|
21
|
+
else
|
22
|
+
def bind_values
|
23
|
+
scope.values || {}
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
27
|
def arel
|
@@ -12,8 +12,14 @@ module ActiveRecord
|
|
12
12
|
@builder = builder
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
if ActiveRecord.version < Gem::Version.new("5.2")
|
16
|
+
def bind_values
|
17
|
+
scope.bound_attributes
|
18
|
+
end
|
19
|
+
else
|
20
|
+
def bind_values
|
21
|
+
scope.values || {}
|
22
|
+
end
|
17
23
|
end
|
18
24
|
|
19
25
|
def arel
|
@@ -11,8 +11,16 @@ module ActiveRecord
|
|
11
11
|
@union_type = options.fetch(:union_type, :all)
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
if ActiveRecord.version < Gem::Version.new("5.2")
|
15
|
+
def bind_values
|
16
|
+
non_recursive_term.bind_values + recursive_term.bind_values
|
17
|
+
end
|
18
|
+
else
|
19
|
+
def bind_values
|
20
|
+
non_recursive_term
|
21
|
+
.bind_values
|
22
|
+
.merge recursive_term.bind_values
|
23
|
+
end
|
16
24
|
end
|
17
25
|
|
18
26
|
def arel
|
@@ -23,13 +23,21 @@ module ActiveRecord
|
|
23
23
|
|
24
24
|
relation = relation.joins(joined_arel_node)
|
25
25
|
|
26
|
-
|
26
|
+
return relation unless ActiveRecord.version < Gem::Version.new("5.2")
|
27
|
+
|
27
28
|
relation.bind_values += bind_values
|
28
29
|
|
29
30
|
relation
|
30
31
|
end
|
31
32
|
|
32
33
|
private
|
34
|
+
|
35
|
+
if ActiveRecord.version < Gem::Version.new("5.2")
|
36
|
+
def bind_values
|
37
|
+
@builder.bind_values
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
33
41
|
def joined_arel_node
|
34
42
|
@options[:outer_join_hierarchical] == true ? outer_join : inner_join
|
35
43
|
end
|
@@ -70,10 +78,6 @@ module ActiveRecord
|
|
70
78
|
custom_foreign_key ? @alias[custom_foreign_key] : @alias[@query.klass.primary_key]
|
71
79
|
end
|
72
80
|
|
73
|
-
def bind_values
|
74
|
-
@builder.bind_values
|
75
|
-
end
|
76
|
-
|
77
81
|
def ordered?
|
78
82
|
@query.orderings.any?
|
79
83
|
end
|
@@ -84,12 +88,29 @@ module ActiveRecord
|
|
84
88
|
|
85
89
|
# This node is required to support joins to aliased Arel nodes
|
86
90
|
class SubqueryAlias < Arel::Nodes::As
|
91
|
+
|
87
92
|
attr_reader :table_name
|
88
93
|
|
94
|
+
unless method_defined? :name
|
95
|
+
alias_method :name, :table_name
|
96
|
+
end
|
97
|
+
|
89
98
|
def initialize(subquery, alias_node)
|
90
99
|
super
|
91
|
-
|
100
|
+
|
101
|
+
@table_name = alias_node.try :name
|
102
|
+
|
103
|
+
return unless alias_node.respond_to? :left
|
104
|
+
|
105
|
+
aliased_name = alias_node.left.relation.name
|
106
|
+
return if @table_name == aliased_name
|
107
|
+
|
108
|
+
# Defensive coding; this shouldn't happen unless the
|
109
|
+
# Rails team does a change to how Arel works.
|
110
|
+
message = "Unexpected alias name mismatch"
|
111
|
+
raise RuntimeError, message
|
92
112
|
end
|
113
|
+
|
93
114
|
end
|
94
115
|
end
|
95
116
|
end
|
@@ -25,7 +25,7 @@ module Arel
|
|
25
25
|
ARRAY_CLOSING = ']'.freeze
|
26
26
|
ARRAY_CONCAT = '||'.freeze
|
27
27
|
|
28
|
-
if Arel::VERSION < '6.0.0'
|
28
|
+
if Gem::Version.new(Arel::VERSION) < Gem::Version.new('6.0.0')
|
29
29
|
def visit_Arel_Nodes_PostgresArray o, *a
|
30
30
|
"#{ARRAY_OPENING}#{visit o.values, *a}#{ARRAY_CLOSING}"
|
31
31
|
end
|
@@ -59,6 +59,18 @@ describe ActiveRecord::HierarchicalQuery do
|
|
59
59
|
end
|
60
60
|
).to include root, child_1, child_2, child_3, child_4, child_5
|
61
61
|
end
|
62
|
+
|
63
|
+
it 'handles Arel::Nodes::As name delegation' do
|
64
|
+
expected_array = \
|
65
|
+
klass.join_recursive do
|
66
|
+
connect_by { |parent, child| parent[:id].eq child[:parent_id] }
|
67
|
+
end
|
68
|
+
|
69
|
+
expect(
|
70
|
+
child_5.alias_node_query
|
71
|
+
).to match_array expected_array
|
72
|
+
end
|
73
|
+
|
62
74
|
end
|
63
75
|
|
64
76
|
describe 'START WITH clause' do
|
data/spec/spec_helper.rb
CHANGED
@@ -2,9 +2,14 @@
|
|
2
2
|
require 'pathname'
|
3
3
|
require 'logger'
|
4
4
|
|
5
|
+
begin
|
6
|
+
require 'pry'
|
7
|
+
rescue LoadError
|
8
|
+
end
|
9
|
+
|
5
10
|
ENV['TZ'] = 'UTC'
|
6
11
|
|
7
|
-
SPEC_ROOT = Pathname.new(File.dirname(__FILE__))
|
12
|
+
SPEC_ROOT = Pathname.new(File.dirname(__FILE__)) unless defined? SPEC_ROOT
|
8
13
|
|
9
14
|
require 'bundler'
|
10
15
|
Bundler.setup(:default, ENV['TRAVIS'] ? :travis : :local)
|
@@ -15,25 +20,35 @@ require 'active_record'
|
|
15
20
|
|
16
21
|
ActiveRecord::Base.configurations = YAML.load(SPEC_ROOT.join('database.yml').read)
|
17
22
|
ActiveRecord::Base.establish_connection(:pg)
|
23
|
+
|
18
24
|
ActiveRecord::Base.logger = Logger.new(ENV['DEBUG'] ? $stderr : '/dev/null')
|
19
25
|
ActiveRecord::Base.logger.formatter = proc do |severity, datetime, progname, msg|
|
20
26
|
"#{datetime.strftime('%H:%M:%S.%L')}: #{msg}\n"
|
21
27
|
end
|
22
28
|
|
23
|
-
|
29
|
+
begin
|
30
|
+
load SPEC_ROOT.join('schema.rb')
|
31
|
+
rescue ActiveRecord::NoDatabaseError
|
32
|
+
bold = "\033[1m"
|
33
|
+
red = "\033[31m"
|
34
|
+
reset = "\033[0m"
|
35
|
+
|
36
|
+
puts ""
|
37
|
+
puts bold + red + "Database missing." + reset
|
38
|
+
puts "If you have #{bold}sudo#{reset}, run the below " +
|
39
|
+
"(ignore any role creation errors)."
|
40
|
+
puts ""
|
41
|
+
puts bold + "rake db:create" + reset
|
42
|
+
puts ""
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
24
46
|
require SPEC_ROOT.join('support', 'models').to_s
|
25
47
|
|
26
48
|
DatabaseCleaner.strategy = :transaction
|
27
49
|
|
28
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
29
50
|
RSpec.configure do |config|
|
30
|
-
config.run_all_when_everything_filtered = true
|
31
|
-
config.filter_run :focus
|
32
51
|
|
33
|
-
# Run specs in random order to surface order dependencies. If you find an
|
34
|
-
# order dependency and want to debug it, you can fix the order by providing
|
35
|
-
# the seed, which is printed after each run.
|
36
|
-
# --seed 1234
|
37
52
|
config.order = 'random'
|
38
53
|
|
39
54
|
config.around(:each) do |example|
|
data/spec/support/models.rb
CHANGED
@@ -37,6 +37,16 @@ class Category < ActiveRecord::Base
|
|
37
37
|
def ancestors
|
38
38
|
parent ? parent.ancestors + [parent] : []
|
39
39
|
end
|
40
|
+
|
41
|
+
# Arel::Nodes::As delegates name to the left relation
|
42
|
+
def alias_node_query
|
43
|
+
Category.left_outer_joins(:articles)
|
44
|
+
.join_recursive do |query|
|
45
|
+
query
|
46
|
+
.connect_by(id: :parent_id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
40
50
|
end
|
41
51
|
|
42
52
|
class Article < ActiveRecord::Base
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-hierarchical_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexei Mikhailov
|
8
|
+
- Zach Aysan
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2021-05-26 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: activerecord
|
@@ -16,93 +17,114 @@ dependencies:
|
|
16
17
|
requirements:
|
17
18
|
- - ">="
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
+
version: '5.0'
|
20
21
|
- - "<"
|
21
22
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
23
|
+
version: '6.2'
|
23
24
|
type: :runtime
|
24
25
|
prerelease: false
|
25
26
|
version_requirements: !ruby/object:Gem::Requirement
|
26
27
|
requirements:
|
27
28
|
- - ">="
|
28
29
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
+
version: '5.0'
|
30
31
|
- - "<"
|
31
32
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
33
|
+
version: '6.2'
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: pg
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.21'
|
41
|
+
- - "<"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.3'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0.21'
|
51
|
+
- - "<"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.3'
|
33
54
|
- !ruby/object:Gem::Dependency
|
34
55
|
name: bundler
|
35
56
|
requirement: !ruby/object:Gem::Requirement
|
36
57
|
requirements:
|
37
|
-
- - "
|
58
|
+
- - ">="
|
38
59
|
- !ruby/object:Gem::Version
|
39
|
-
version: '1.
|
60
|
+
version: '1.16'
|
40
61
|
type: :development
|
41
62
|
prerelease: false
|
42
63
|
version_requirements: !ruby/object:Gem::Requirement
|
43
64
|
requirements:
|
44
|
-
- - "
|
65
|
+
- - ">="
|
45
66
|
- !ruby/object:Gem::Version
|
46
|
-
version: '1.
|
67
|
+
version: '1.16'
|
47
68
|
- !ruby/object:Gem::Dependency
|
48
69
|
name: rake
|
49
70
|
requirement: !ruby/object:Gem::Requirement
|
50
71
|
requirements:
|
51
72
|
- - "~>"
|
52
73
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
74
|
+
version: '12.3'
|
54
75
|
type: :development
|
55
76
|
prerelease: false
|
56
77
|
version_requirements: !ruby/object:Gem::Requirement
|
57
78
|
requirements:
|
58
79
|
- - "~>"
|
59
80
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
81
|
+
version: '12.3'
|
61
82
|
- !ruby/object:Gem::Dependency
|
62
83
|
name: rspec
|
63
84
|
requirement: !ruby/object:Gem::Requirement
|
64
85
|
requirements:
|
65
86
|
- - "~>"
|
66
87
|
- !ruby/object:Gem::Version
|
67
|
-
version: 3.
|
88
|
+
version: '3.8'
|
68
89
|
type: :development
|
69
90
|
prerelease: false
|
70
91
|
version_requirements: !ruby/object:Gem::Requirement
|
71
92
|
requirements:
|
72
93
|
- - "~>"
|
73
94
|
- !ruby/object:Gem::Version
|
74
|
-
version: 3.
|
95
|
+
version: '3.8'
|
75
96
|
- !ruby/object:Gem::Dependency
|
76
97
|
name: database_cleaner
|
77
98
|
requirement: !ruby/object:Gem::Requirement
|
78
99
|
requirements:
|
79
100
|
- - "~>"
|
80
101
|
- !ruby/object:Gem::Version
|
81
|
-
version: 1.
|
102
|
+
version: '1.7'
|
82
103
|
type: :development
|
83
104
|
prerelease: false
|
84
105
|
version_requirements: !ruby/object:Gem::Requirement
|
85
106
|
requirements:
|
86
107
|
- - "~>"
|
87
108
|
- !ruby/object:Gem::Version
|
88
|
-
version: 1.
|
109
|
+
version: '1.7'
|
89
110
|
- !ruby/object:Gem::Dependency
|
90
111
|
name: simplecov
|
91
112
|
requirement: !ruby/object:Gem::Requirement
|
92
113
|
requirements:
|
93
114
|
- - "~>"
|
94
115
|
- !ruby/object:Gem::Version
|
95
|
-
version: 0.
|
116
|
+
version: '0.16'
|
96
117
|
type: :development
|
97
118
|
prerelease: false
|
98
119
|
version_requirements: !ruby/object:Gem::Requirement
|
99
120
|
requirements:
|
100
121
|
- - "~>"
|
101
122
|
- !ruby/object:Gem::Version
|
102
|
-
version: 0.
|
123
|
+
version: '0.16'
|
103
124
|
description:
|
104
125
|
email:
|
105
126
|
- amikhailov83@gmail.com
|
127
|
+
- zachaysan@gmail.com
|
106
128
|
executables: []
|
107
129
|
extensions: []
|
108
130
|
extra_rdoc_files: []
|
@@ -147,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
169
|
- !ruby/object:Gem::Version
|
148
170
|
version: '0'
|
149
171
|
requirements: []
|
150
|
-
|
151
|
-
rubygems_version: 2.4.8
|
172
|
+
rubygems_version: 3.2.15
|
152
173
|
signing_key:
|
153
174
|
specification_version: 4
|
154
175
|
summary: Recursively traverse trees using a single SQL query
|