activerecord-hierarchical_query 0.0.7 → 0.0.8

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
  SHA1:
3
- metadata.gz: 3c5308c4928b4519b1501e578fbe930058261e65
4
- data.tar.gz: d466545e9b356e702a16a5ac6ee9b6fdc0ac37fe
3
+ metadata.gz: 71bc88ee032e123ae1e612a9a589e5ee4b3f87b2
4
+ data.tar.gz: e8dea5c43cd1b41450635836f4a56bdcb95a77ce
5
5
  SHA512:
6
- metadata.gz: 3e9ba821eecd7ad1f1e495c6280464b9e6dd75ce080b9251176441a63d2ca4f05e7d8c1c4f7cfe13eb027714791a01fb3e24476ac9de1511490e8f133d3d36a7
7
- data.tar.gz: 5e1ef94d4c80629485d4092e26f534b7b003890337d89cefbd52ead9d21ca4864fe3df9610a03d46df7c009f8e56e3797641738e458c3ee162a66b7fe816b2bd
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
- gem 'activerecord-hierarchical_query'
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
- relation = @relation.joins(inner_join.to_sql)
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
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module HierarchicalQuery
3
- VERSION = '0.0.7'
3
+ VERSION = '0.0.8'
4
4
  end
5
5
  end
@@ -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.7
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: 2014-12-28 00:00:00.000000000 Z
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.2.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: