dbee-active_record 2.0.1 → 2.1.0.pre.alpha.1
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 +4 -4
- data/.rubocop.yml +24 -9
- data/.ruby-version +1 -1
- data/.travis.yml +3 -7
- data/CHANGELOG.md +26 -0
- data/dbee-active_record.gemspec +13 -5
- data/exe/.gitkeep +0 -0
- data/lib/dbee/providers/active_record_provider/expression_builder.rb +47 -19
- data/lib/dbee/providers/active_record_provider/expression_builder/{constraint_maker.rb → constraint.rb} +11 -11
- data/lib/dbee/providers/active_record_provider/expression_builder/{order_maker.rb → order.rb} +8 -8
- data/lib/dbee/providers/active_record_provider/expression_builder/select.rb +71 -0
- data/lib/dbee/providers/active_record_provider/expression_builder/where.rb +91 -0
- data/lib/dbee/providers/active_record_provider/version.rb +1 -1
- data/spec/db_helper.rb +130 -14
- data/spec/dbee/providers/active_record_provider_spec.rb +102 -1
- data/spec/fixtures/active_record_snapshots/one_table_query_with_filters.yaml +24 -16
- data/spec/fixtures/active_record_snapshots/two_table_query_with_aggregation.yaml +71 -0
- data/spec/fixtures/active_record_snapshots/two_table_query_with_pivoting.yaml +88 -0
- data/spec/fixtures/models.yaml +20 -0
- metadata +30 -21
- data/lib/dbee/providers/active_record_provider/expression_builder/select_maker.rb +0 -33
- data/lib/dbee/providers/active_record_provider/expression_builder/where_maker.rb +0 -56
@@ -0,0 +1,88 @@
|
|
1
|
+
model_name: Patients
|
2
|
+
query:
|
3
|
+
fields:
|
4
|
+
- key_path: id
|
5
|
+
display: 'ID #'
|
6
|
+
- key_path: first
|
7
|
+
display: First Name
|
8
|
+
- key_path: patient_field_values.value
|
9
|
+
display: Date of Birth
|
10
|
+
aggregator: max
|
11
|
+
filters:
|
12
|
+
- key_path: patient_field_values.fields.section
|
13
|
+
value: demographics
|
14
|
+
- key_path: patient_field_values.fields.key
|
15
|
+
value: dob
|
16
|
+
- key_path: patient_field_values.value
|
17
|
+
display: Demographic Notes
|
18
|
+
aggregator: max
|
19
|
+
filters:
|
20
|
+
- key_path: patient_field_values.fields.section
|
21
|
+
value: demographics
|
22
|
+
- key_path: patient_field_values.fields.key
|
23
|
+
value: notes
|
24
|
+
- key_path: patient_field_values.value
|
25
|
+
display: 'Drivers License #'
|
26
|
+
aggregator: max
|
27
|
+
filters:
|
28
|
+
- key_path: patient_field_values.fields.section
|
29
|
+
value: demographics
|
30
|
+
- key_path: patient_field_values.fields.key
|
31
|
+
value: drivers_license
|
32
|
+
- key_path: patient_field_values.value
|
33
|
+
display: Contact Notes
|
34
|
+
aggregator: max
|
35
|
+
filters:
|
36
|
+
- key_path: patient_field_values.fields.section
|
37
|
+
value: contact
|
38
|
+
- key_path: patient_field_values.fields.key
|
39
|
+
value: notes
|
40
|
+
|
41
|
+
sqlite_readable: |+
|
42
|
+
SELECT
|
43
|
+
"patients"."id" AS 'ID #',
|
44
|
+
"patients"."first" AS 'First Name',
|
45
|
+
MAX(CASE WHEN "patient_field_values_fields"."section" = 'demographics' AND "patient_field_values_fields"."key" = 'dob' THEN "patient_field_values"."value" END) AS 'Date of Birth',
|
46
|
+
MAX(CASE WHEN "patient_field_values_fields"."section" = 'demographics' AND "patient_field_values_fields"."key" = 'notes' THEN "patient_field_values"."value" END) AS 'Demographic Notes',
|
47
|
+
MAX(CASE WHEN "patient_field_values_fields"."section" = 'demographics' AND "patient_field_values_fields"."key" = 'drivers_license' THEN "patient_field_values"."value" END) AS 'Drivers License #',
|
48
|
+
MAX(CASE WHEN "patient_field_values_fields"."section" = 'contact' AND "patient_field_values_fields"."key" = 'notes' THEN "patient_field_values"."value" END) AS 'Contact Notes'
|
49
|
+
FROM "patients" "patients"
|
50
|
+
LEFT OUTER JOIN "patient_field_values" "patient_field_values" ON "patient_field_values"."patient_id" = "patients"."id"
|
51
|
+
LEFT OUTER JOIN "fields" "patient_field_values_fields" ON "patient_field_values_fields"."id" = "patient_field_values"."field_id"
|
52
|
+
GROUP BY "patients"."id", "patients"."first"
|
53
|
+
sqlite_not_readable: |+
|
54
|
+
SELECT
|
55
|
+
"t0"."id" AS 'c0',
|
56
|
+
"t0"."first" AS 'c1',
|
57
|
+
MAX(CASE WHEN "t2"."section" = 'demographics' AND "t2"."key" = 'dob' THEN "t1"."value" END) AS 'c2',
|
58
|
+
MAX(CASE WHEN "t2"."section" = 'demographics' AND "t2"."key" = 'notes' THEN "t1"."value" END) AS 'c3',
|
59
|
+
MAX(CASE WHEN "t2"."section" = 'demographics' AND "t2"."key" = 'drivers_license' THEN "t1"."value" END) AS 'c4',
|
60
|
+
MAX(CASE WHEN "t2"."section" = 'contact' AND "t2"."key" = 'notes' THEN "t1"."value" END) AS 'c5'
|
61
|
+
FROM "patients" "t0"
|
62
|
+
LEFT OUTER JOIN "patient_field_values" "t1" ON "t1"."patient_id" = "t0"."id"
|
63
|
+
LEFT OUTER JOIN "fields" "t2" ON "t2"."id" = "t1"."field_id"
|
64
|
+
GROUP BY "t0"."id", "t0"."first"
|
65
|
+
mysql_readable: |+
|
66
|
+
SELECT
|
67
|
+
`patients`.`id` AS 'ID #',
|
68
|
+
`patients`.`first` AS 'First Name',
|
69
|
+
MAX(CASE WHEN `patient_field_values_fields`.`section` = 'demographics' AND `patient_field_values_fields`.`key` = 'dob' THEN `patient_field_values`.`value` END) AS 'Date of Birth',
|
70
|
+
MAX(CASE WHEN `patient_field_values_fields`.`section` = 'demographics' AND `patient_field_values_fields`.`key` = 'notes' THEN `patient_field_values`.`value` END) AS 'Demographic Notes',
|
71
|
+
MAX(CASE WHEN `patient_field_values_fields`.`section` = 'demographics' AND `patient_field_values_fields`.`key` = 'drivers_license' THEN `patient_field_values`.`value` END) AS 'Drivers License #',
|
72
|
+
MAX(CASE WHEN `patient_field_values_fields`.`section` = 'contact' AND `patient_field_values_fields`.`key` = 'notes' THEN `patient_field_values`.`value` END) AS 'Contact Notes'
|
73
|
+
FROM `patients` `patients`
|
74
|
+
LEFT OUTER JOIN `patient_field_values` `patient_field_values` ON `patient_field_values`.`patient_id` = `patients`.`id`
|
75
|
+
LEFT OUTER JOIN `fields` `patient_field_values_fields` ON `patient_field_values_fields`.`id` = `patient_field_values`.`field_id`
|
76
|
+
GROUP BY `patients`.`id`, `patients`.`first`
|
77
|
+
mysql_not_readable: |+
|
78
|
+
SELECT
|
79
|
+
`t0`.`id` AS 'c0',
|
80
|
+
`t0`.`first` AS 'c1',
|
81
|
+
MAX(CASE WHEN `t2`.`section` = 'demographics' AND `t2`.`key` = 'dob' THEN `t1`.`value` END) AS 'c2',
|
82
|
+
MAX(CASE WHEN `t2`.`section` = 'demographics' AND `t2`.`key` = 'notes' THEN `t1`.`value` END) AS 'c3',
|
83
|
+
MAX(CASE WHEN `t2`.`section` = 'demographics' AND `t2`.`key` = 'drivers_license' THEN `t1`.`value` END) AS 'c4',
|
84
|
+
MAX(CASE WHEN `t2`.`section` = 'contact' AND `t2`.`key` = 'notes' THEN `t1`.`value` END) AS 'c5'
|
85
|
+
FROM `patients` `t0`
|
86
|
+
LEFT OUTER JOIN `patient_field_values` `t1` ON `t1`.`patient_id` = `t0`.`id`
|
87
|
+
LEFT OUTER JOIN `fields` `t2` ON `t2`.`id` = `t1`.`field_id`
|
88
|
+
GROUP BY `t0`.`id`, `t0`.`first`
|
data/spec/fixtures/models.yaml
CHANGED
@@ -103,3 +103,23 @@ Partitioner Example 2:
|
|
103
103
|
value: Dog
|
104
104
|
- name: deleted
|
105
105
|
value: false
|
106
|
+
|
107
|
+
Patients:
|
108
|
+
name: patients
|
109
|
+
models:
|
110
|
+
- name: patient_payments
|
111
|
+
constraints:
|
112
|
+
- type: reference
|
113
|
+
parent: id
|
114
|
+
name: patient_id
|
115
|
+
- name: patient_field_values
|
116
|
+
constraints:
|
117
|
+
- type: reference
|
118
|
+
parent: id
|
119
|
+
name: patient_id
|
120
|
+
models:
|
121
|
+
- name: fields
|
122
|
+
constraints:
|
123
|
+
- type: reference
|
124
|
+
parent: field_id
|
125
|
+
name: id
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbee-active_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.1
|
4
|
+
version: 2.1.0.pre.alpha.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -34,16 +34,16 @@ dependencies:
|
|
34
34
|
name: dbee
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- -
|
37
|
+
- - '='
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
39
|
+
version: 2.1.0.pre.alpha
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
|
-
- -
|
44
|
+
- - '='
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
46
|
+
version: 2.1.0.pre.alpha
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: guard-rspec
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,14 +120,14 @@ dependencies:
|
|
120
120
|
requirements:
|
121
121
|
- - "~>"
|
122
122
|
- !ruby/object:Gem::Version
|
123
|
-
version: 0.
|
123
|
+
version: 0.81.0
|
124
124
|
type: :development
|
125
125
|
prerelease: false
|
126
126
|
version_requirements: !ruby/object:Gem::Requirement
|
127
127
|
requirements:
|
128
128
|
- - "~>"
|
129
129
|
- !ruby/object:Gem::Version
|
130
|
-
version: 0.
|
130
|
+
version: 0.81.0
|
131
131
|
- !ruby/object:Gem::Dependency
|
132
132
|
name: simplecov
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
@@ -148,14 +148,14 @@ dependencies:
|
|
148
148
|
requirements:
|
149
149
|
- - "~>"
|
150
150
|
- !ruby/object:Gem::Version
|
151
|
-
version: 0.
|
151
|
+
version: 0.7.0
|
152
152
|
type: :development
|
153
153
|
prerelease: false
|
154
154
|
version_requirements: !ruby/object:Gem::Requirement
|
155
155
|
requirements:
|
156
156
|
- - "~>"
|
157
157
|
- !ruby/object:Gem::Version
|
158
|
-
version: 0.
|
158
|
+
version: 0.7.0
|
159
159
|
- !ruby/object:Gem::Dependency
|
160
160
|
name: sqlite3
|
161
161
|
requirement: !ruby/object:Gem::Requirement
|
@@ -174,8 +174,7 @@ description: " By default Dbee ships with no underlying SQL generator. This
|
|
174
174
|
will plug in ActiveRecord into Dbee and Dbee will use it for SQL generation.\n"
|
175
175
|
email:
|
176
176
|
- mruggio@bluemarblepayroll.com
|
177
|
-
executables:
|
178
|
-
- console
|
177
|
+
executables: []
|
179
178
|
extensions: []
|
180
179
|
extra_rdoc_files: []
|
181
180
|
files:
|
@@ -193,12 +192,13 @@ files:
|
|
193
192
|
- Rakefile
|
194
193
|
- bin/console
|
195
194
|
- dbee-active_record.gemspec
|
195
|
+
- exe/.gitkeep
|
196
196
|
- lib/dbee/providers/active_record_provider.rb
|
197
197
|
- lib/dbee/providers/active_record_provider/expression_builder.rb
|
198
|
-
- lib/dbee/providers/active_record_provider/expression_builder/
|
199
|
-
- lib/dbee/providers/active_record_provider/expression_builder/
|
200
|
-
- lib/dbee/providers/active_record_provider/expression_builder/
|
201
|
-
- lib/dbee/providers/active_record_provider/expression_builder/
|
198
|
+
- lib/dbee/providers/active_record_provider/expression_builder/constraint.rb
|
199
|
+
- lib/dbee/providers/active_record_provider/expression_builder/order.rb
|
200
|
+
- lib/dbee/providers/active_record_provider/expression_builder/select.rb
|
201
|
+
- lib/dbee/providers/active_record_provider/expression_builder/where.rb
|
202
202
|
- lib/dbee/providers/active_record_provider/obfuscated_alias_maker.rb
|
203
203
|
- lib/dbee/providers/active_record_provider/safe_alias_maker.rb
|
204
204
|
- lib/dbee/providers/active_record_provider/version.rb
|
@@ -217,12 +217,19 @@ files:
|
|
217
217
|
- spec/fixtures/active_record_snapshots/partitioner_example_2_query.yaml
|
218
218
|
- spec/fixtures/active_record_snapshots/reverse_polymorphic_query.yaml
|
219
219
|
- spec/fixtures/active_record_snapshots/two_table_query.yaml
|
220
|
+
- spec/fixtures/active_record_snapshots/two_table_query_with_aggregation.yaml
|
221
|
+
- spec/fixtures/active_record_snapshots/two_table_query_with_pivoting.yaml
|
220
222
|
- spec/fixtures/models.yaml
|
221
223
|
- spec/spec_helper.rb
|
222
224
|
homepage: https://github.com/bluemarblepayroll/dbee-active_record
|
223
225
|
licenses:
|
224
226
|
- MIT
|
225
|
-
metadata:
|
227
|
+
metadata:
|
228
|
+
bug_tracker_uri: https://github.com/bluemarblepayroll/dbee-active_record/issues
|
229
|
+
changelog_uri: https://github.com/bluemarblepayroll/dbee-active_record/blob/master/CHANGELOG.md
|
230
|
+
documentation_uri: https://www.rubydoc.info/gems/dbee-active_record
|
231
|
+
homepage_uri: https://github.com/bluemarblepayroll/dbee-active_record
|
232
|
+
source_code_uri: https://github.com/bluemarblepayroll/dbee-active_record
|
226
233
|
post_install_message:
|
227
234
|
rdoc_options: []
|
228
235
|
require_paths:
|
@@ -231,12 +238,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
231
238
|
requirements:
|
232
239
|
- - ">="
|
233
240
|
- !ruby/object:Gem::Version
|
234
|
-
version: 2.
|
241
|
+
version: '2.5'
|
235
242
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
236
243
|
requirements:
|
237
|
-
- - "
|
244
|
+
- - ">"
|
238
245
|
- !ruby/object:Gem::Version
|
239
|
-
version:
|
246
|
+
version: 1.3.1
|
240
247
|
requirements: []
|
241
248
|
rubygems_version: 3.0.3
|
242
249
|
signing_key:
|
@@ -258,5 +265,7 @@ test_files:
|
|
258
265
|
- spec/fixtures/active_record_snapshots/partitioner_example_2_query.yaml
|
259
266
|
- spec/fixtures/active_record_snapshots/reverse_polymorphic_query.yaml
|
260
267
|
- spec/fixtures/active_record_snapshots/two_table_query.yaml
|
268
|
+
- spec/fixtures/active_record_snapshots/two_table_query_with_aggregation.yaml
|
269
|
+
- spec/fixtures/active_record_snapshots/two_table_query_with_pivoting.yaml
|
261
270
|
- spec/fixtures/models.yaml
|
262
271
|
- spec/spec_helper.rb
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
#
|
4
|
-
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
-
#
|
6
|
-
# This source code is licensed under the MIT license found in the
|
7
|
-
# LICENSE file in the root directory of this source tree.
|
8
|
-
#
|
9
|
-
|
10
|
-
module Dbee
|
11
|
-
module Providers
|
12
|
-
class ActiveRecordProvider
|
13
|
-
class ExpressionBuilder
|
14
|
-
# Derives Arel#project predicates.
|
15
|
-
class SelectMaker
|
16
|
-
include Singleton
|
17
|
-
|
18
|
-
def make(column, arel_column, alias_maker)
|
19
|
-
column_alias = quote(alias_maker.make(column.display))
|
20
|
-
|
21
|
-
arel_column.as(column_alias)
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def quote(value)
|
27
|
-
ActiveRecord::Base.connection.quote(value)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
#
|
4
|
-
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
-
#
|
6
|
-
# This source code is licensed under the MIT license found in the
|
7
|
-
# LICENSE file in the root directory of this source tree.
|
8
|
-
#
|
9
|
-
|
10
|
-
module Dbee
|
11
|
-
module Providers
|
12
|
-
class ActiveRecordProvider
|
13
|
-
class ExpressionBuilder
|
14
|
-
# Derives Arel#where predicates.
|
15
|
-
class WhereMaker
|
16
|
-
include Singleton
|
17
|
-
|
18
|
-
FILTER_EVALUATORS = {
|
19
|
-
Query::Filters::Contains => ->(column, val) { column.matches("%#{val}%") },
|
20
|
-
Query::Filters::Equals => ->(column, val) { column.eq(val) },
|
21
|
-
Query::Filters::GreaterThan => ->(column, val) { column.gt(val) },
|
22
|
-
Query::Filters::GreaterThanOrEqualTo => ->(column, val) { column.gteq(val) },
|
23
|
-
Query::Filters::LessThan => ->(column, val) { column.lt(val) },
|
24
|
-
Query::Filters::LessThanOrEqualTo => ->(column, val) { column.lteq(val) },
|
25
|
-
Query::Filters::NotContain => ->(column, val) { column.does_not_match("%#{val}%") },
|
26
|
-
Query::Filters::NotEquals => ->(column, val) { column.not_eq(val) },
|
27
|
-
Query::Filters::NotStartWith => ->(column, val) { column.does_not_match("#{val}%") },
|
28
|
-
Query::Filters::StartsWith => ->(column, val) { column.matches("#{val}%") }
|
29
|
-
}.freeze
|
30
|
-
|
31
|
-
private_constant :FILTER_EVALUATORS
|
32
|
-
|
33
|
-
def make(filter, arel_column)
|
34
|
-
predicates = normalize(filter.value).map do |coerced_value|
|
35
|
-
method = FILTER_EVALUATORS[filter.class]
|
36
|
-
|
37
|
-
raise ArgumentError, "cannot compile filter: #{filter}" unless method
|
38
|
-
|
39
|
-
method.call(arel_column, coerced_value)
|
40
|
-
end
|
41
|
-
|
42
|
-
predicates.inject(predicates.shift) do |memo, predicate|
|
43
|
-
memo.or(predicate)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def normalize(value)
|
50
|
-
value ? Array(value).flatten : [nil]
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|