activerecord-hierarchical_query 0.0.7 → 0.0.8
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71bc88ee032e123ae1e612a9a589e5ee4b3f87b2
|
4
|
+
data.tar.gz: e8dea5c43cd1b41450635836f4a56bdcb95a77ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd73d0c3ccd15dc9217e629db225993c5fc7f73b3375804bfa80abd72a530906a915644b0080fa4a7f796f1b72e3078b3770a9980a62cbba4687d96a94a35870
|
7
|
+
data.tar.gz: 6d58bbd3b65d443482ce233fff71aafa2d03509da62130518c5fa4fb541b5f6bf97e98d90a6ab85cf81e7bc385e6f1cdb56b24a21b12f461f93694a1cd781f05
|
data/README.md
CHANGED
@@ -72,7 +72,9 @@ crumbs = records.pluck(:name).join(' / ')
|
|
72
72
|
|
73
73
|
Add this line to your application's Gemfile:
|
74
74
|
|
75
|
-
|
75
|
+
```ruby
|
76
|
+
gem 'activerecord-hierarchical_query'
|
77
|
+
```
|
76
78
|
|
77
79
|
And then execute:
|
78
80
|
|
@@ -82,6 +84,19 @@ Or install it yourself as:
|
|
82
84
|
|
83
85
|
$ gem install activerecord-hierarchical_query
|
84
86
|
|
87
|
+
You'll then need to require the gem:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
require 'active_record/hierarchical_query'
|
91
|
+
```
|
92
|
+
|
93
|
+
Alternatively, the require can be placed in the `Gemfile`:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
gem 'activerecord-hierarchical_query', require: 'active_record/hierarchical_query'
|
97
|
+
```
|
98
|
+
|
99
|
+
|
85
100
|
## Usage
|
86
101
|
|
87
102
|
Let's say you've got an ActiveRecord model `Category` with attributes `id`, `parent_id`
|
@@ -280,6 +295,16 @@ FROM "categories" INNER JOIN (
|
|
280
295
|
ORDER BY "categories__recursive"."__order_column" ASC
|
281
296
|
```
|
282
297
|
|
298
|
+
If you want to use a `LEFT OUTER JOIN` instead of an `INNER JOIN`, add a query option for `outer_join_hierarchical`. This option allows the query to return non-hierarchical entries:
|
299
|
+
```ruby
|
300
|
+
.join_recursive(outer_join_hierarchical: true)
|
301
|
+
```
|
302
|
+
|
303
|
+
If, when joining the recursive view to the main table, you want to change the foreign_key on the recursive view from the primary key of the main table to another column:
|
304
|
+
```ruby
|
305
|
+
.join_recursive(foreign_key: another_column)
|
306
|
+
```
|
307
|
+
|
283
308
|
## Related resources
|
284
309
|
|
285
310
|
* [About hierarchical queries (Wikipedia)](http://en.wikipedia.org/wiki/Hierarchical_and_recursive_queries_in_SQL)
|
@@ -6,15 +6,21 @@ module ActiveRecord
|
|
6
6
|
# @param [ActiveRecord::HierarchicalQuery::Query] query
|
7
7
|
# @param [ActiveRecord::Relation] join_to
|
8
8
|
# @param [#to_s] subquery_alias
|
9
|
-
def initialize(query, join_to, subquery_alias)
|
9
|
+
def initialize(query, join_to, subquery_alias, join_options = {})
|
10
10
|
@query = query
|
11
11
|
@builder = CTE::QueryBuilder.new(query)
|
12
12
|
@relation = join_to
|
13
13
|
@alias = Arel::Table.new(subquery_alias, ActiveRecord::Base)
|
14
|
+
@join_options = join_options
|
14
15
|
end
|
15
16
|
|
16
17
|
def build
|
17
|
-
|
18
|
+
# outer joins to include non-hierarchical entries if specified
|
19
|
+
# default option when flag is not specified is to include only entries participating
|
20
|
+
# in a hierarchy
|
21
|
+
join_sql = @join_options[:outer_join_hierarchical].present? ? outer_join.to_sql : inner_join.to_sql
|
22
|
+
relation = @relation.joins(join_sql)
|
23
|
+
|
18
24
|
# copy bound variables from inner subquery (remove duplicates)
|
19
25
|
relation.bind_values |= bind_values
|
20
26
|
# add ordering by "__order_column"
|
@@ -28,6 +34,10 @@ module ActiveRecord
|
|
28
34
|
Arel::Nodes::InnerJoin.new(aliased_subquery, constraint)
|
29
35
|
end
|
30
36
|
|
37
|
+
def outer_join
|
38
|
+
Arel::Nodes::OuterJoin.new(aliased_subquery, constraint)
|
39
|
+
end
|
40
|
+
|
31
41
|
def aliased_subquery
|
32
42
|
Arel::Nodes::As.new(subquery, @alias)
|
33
43
|
end
|
@@ -48,8 +58,12 @@ module ActiveRecord
|
|
48
58
|
@relation.table[@relation.klass.primary_key]
|
49
59
|
end
|
50
60
|
|
61
|
+
def custom_foreign_key
|
62
|
+
@join_options[:foreign_key]
|
63
|
+
end
|
64
|
+
|
51
65
|
def foreign_key
|
52
|
-
@alias[@query.klass.primary_key]
|
66
|
+
custom_foreign_key ? @alias[custom_foreign_key] : @alias[@query.klass.primary_key]
|
53
67
|
end
|
54
68
|
|
55
69
|
def bind_values
|
@@ -65,4 +79,4 @@ module ActiveRecord
|
|
65
79
|
end
|
66
80
|
end
|
67
81
|
end
|
68
|
-
end
|
82
|
+
end
|
@@ -300,7 +300,7 @@ module ActiveRecord
|
|
300
300
|
|
301
301
|
table_alias = join_options.fetch(:as, "#{table.name}__recursive")
|
302
302
|
|
303
|
-
JoinBuilder.new(self, relation, table_alias).build
|
303
|
+
JoinBuilder.new(self, relation, table_alias, join_options).build
|
304
304
|
end
|
305
305
|
|
306
306
|
private
|
@@ -317,4 +317,4 @@ module ActiveRecord
|
|
317
317
|
end
|
318
318
|
end # class Builder
|
319
319
|
end # module HierarchicalQuery
|
320
|
-
end # module ActiveRecord
|
320
|
+
end # module ActiveRecord
|
@@ -213,5 +213,21 @@ describe ActiveRecord::HierarchicalQuery do
|
|
213
213
|
).to match /my_table/
|
214
214
|
end
|
215
215
|
end
|
216
|
+
|
217
|
+
describe ':outer_join_hierarchical' do
|
218
|
+
it 'build an outer join' do
|
219
|
+
expect(
|
220
|
+
klass.join_recursive(outer_join_hierarchical: true) { connect_by(id: :parent_id) }.to_sql
|
221
|
+
).to match /LEFT OUTER JOIN/
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe ':foreign_key' do
|
226
|
+
it 'uses described foreign_key when joining table to recursive view' do
|
227
|
+
expect(
|
228
|
+
klass.join_recursive(foreign_key: 'some_column') { connect_by(id: :parent_id) }.to_sql
|
229
|
+
).to match /categories\"\.\"id\" = \"categories__recursive\"\.\"some_column/
|
230
|
+
end
|
231
|
+
end
|
216
232
|
end
|
217
|
-
end
|
233
|
+
end
|
metadata
CHANGED
@@ -1,97 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-hierarchical_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexei Mikhailov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 3.1.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 3.1.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.5'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.5'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 10.4.2
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 10.4.2
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 3.1.0
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 3.1.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: database_cleaner
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - ~>
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 1.3.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - ~>
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 1.3.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: simplecov
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - ~>
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: 0.9.1
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - ~>
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 0.9.1
|
97
97
|
description:
|
@@ -131,17 +131,17 @@ require_paths:
|
|
131
131
|
- lib
|
132
132
|
required_ruby_version: !ruby/object:Gem::Requirement
|
133
133
|
requirements:
|
134
|
-
- -
|
134
|
+
- - ">="
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: '0'
|
137
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
138
|
requirements:
|
139
|
-
- -
|
139
|
+
- - ">="
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
requirements: []
|
143
143
|
rubyforge_project:
|
144
|
-
rubygems_version: 2.
|
144
|
+
rubygems_version: 2.4.8
|
145
145
|
signing_key:
|
146
146
|
specification_version: 4
|
147
147
|
summary: Recursively traverse trees using a single SQL query
|
@@ -152,4 +152,3 @@ test_files:
|
|
152
152
|
- spec/schema.rb
|
153
153
|
- spec/spec_helper.rb
|
154
154
|
- spec/support/models.rb
|
155
|
-
has_rdoc:
|