db_fuel 1.1.0.pre.alpha → 1.2.1.pre.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -1
- data/.tool-versions +1 -0
- data/CHANGELOG.md +2 -1
- data/README.md +149 -8
- data/db_fuel.gemspec +3 -3
- data/lib/db_fuel.rb +3 -0
- data/lib/db_fuel/db_provider.rb +82 -0
- data/lib/db_fuel/library.rb +10 -4
- data/lib/db_fuel/library/active_record/base.rb +9 -33
- data/lib/db_fuel/library/active_record/find_or_insert.rb +103 -0
- data/lib/db_fuel/library/active_record/insert.rb +9 -32
- data/lib/db_fuel/library/active_record/update.rb +25 -44
- data/lib/db_fuel/library/active_record/update_all.rb +96 -0
- data/lib/db_fuel/library/active_record/upsert.rb +210 -0
- data/lib/db_fuel/library/dbee/base.rb +11 -2
- data/lib/db_fuel/library/dbee/query.rb +35 -3
- data/lib/db_fuel/library/dbee/range.rb +17 -5
- data/lib/db_fuel/modeling.rb +1 -0
- data/lib/db_fuel/modeling/attribute_renderer_set.rb +83 -0
- data/lib/db_fuel/modeling/keyed_column.rb +2 -2
- data/lib/db_fuel/version.rb +1 -1
- metadata +15 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a93b59424a5cf6866f1061785f41a0c49c1bcc707ce84a6652f481a283aab64
|
4
|
+
data.tar.gz: 3b7a65c38a5cc24ee844412ef6cb1bc3b2bc2a33c9afd564196e1b1f739108b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5bc7c2644584e1f8e0412e0215bef34b6431b085e18fba822723e94ab0baea9c7a97a25d4970dc9169a2adc23f7818d618f48f8ab2f9d7ddb9f5a5914ecd356
|
7
|
+
data.tar.gz: 02d4f517420b8aa3331d99a69dadd39faa7b53382e89f153467eaea3d74a52141e75c000cba62c090e8e0aaa2fb2d293908160b016b242e35d483f396e37b542
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
AllCops:
|
2
2
|
TargetRubyVersion: 2.5
|
3
3
|
NewCops: enable
|
4
|
+
SuggestExtensions: false
|
4
5
|
|
5
6
|
Layout/LineLength:
|
6
7
|
Max: 100
|
@@ -8,7 +9,7 @@ Layout/LineLength:
|
|
8
9
|
- db_fuel.gemspec
|
9
10
|
|
10
11
|
Metrics/BlockLength:
|
11
|
-
|
12
|
+
IgnoredMethods:
|
12
13
|
- let
|
13
14
|
- it
|
14
15
|
- describe
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 2.6.6
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -24,13 +24,16 @@ Refer to the [Burner](https://github.com/bluemarblepayroll/burner) library for m
|
|
24
24
|
|
25
25
|
### ActiveRecord Jobs
|
26
26
|
|
27
|
-
* **db_fuel/active_record/
|
28
|
-
* **db_fuel/active_record/
|
27
|
+
* **db_fuel/active_record/find_or_insert** [name, table_name, attributes, debug, primary_key, register, separator, timestamps, unique_attributes]: An extension of the `db_fuel/active_record/insert` job that adds an existence check before SQL insertion. The `unique_attributes` will be converted to WHERE clauses for performing the existence check.
|
28
|
+
* **db_fuel/active_record/insert** [name, table_name, attributes, debug, primary_key, register, separator, timestamps]: This job can take the objects in a register and insert them into a database table. If primary_key is specified then its key will be set to the primary key. Note that composite primary keys are not supported. Attributes defines which object properties to convert to SQL. Refer to the class and constructor specification for more detail.
|
29
|
+
* **db_fuel/active_record/update_all** [name, table_name, attributes, debug, register, separator, timestamps, unique_attributes]: This job can take the objects in a register and updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while unique_attributes translate to WHERE clauses. One or more records may be updated at a time. Refer to the class and constructor specification for more detail.
|
30
|
+
* **db_fuel/active_record/update** [name, table_name, attributes, debug, register, primary_key, separator, timestamps, unique_attributes]: This job can take the unique objects in a register and updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while unique_attributes translate to WHERE clauses to find the records to update. The primary_key is used to update the unique record. Only one record will be updated per statement. Refer to the class and constructor specification for more detail.
|
31
|
+
* **db_fuel/active_record/upsert** [name, table_name, attributes, debug, primary_key, register, separator, timestamps, unique_attributes]: This job can take the objects in a register and either inserts or updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while each key in unique_attributes become a WHERE clause in order to check for the existence of a specific record. The updated record will use the primary_key specified to perform the UPDATE operation. Note that composite primary keys are not supported. Refer to the class and constructor specification for more detail.
|
29
32
|
|
30
33
|
### Dbee Jobs
|
31
34
|
|
32
|
-
* **db_fuel/dbee/query** [model, query, register]: Pass in a [Dbee](https://github.com/bluemarblepayroll/dbee) model and query and store the results in the specified register. Refer to the [Dbee](https://github.com/bluemarblepayroll/dbee) library directly on how to craft a model or query.
|
33
|
-
* **db_fuel/dbee/range** [key, key_path, model, query, register, separator]: Similar to `db_fuel/dbee/query` with the addition of being able to grab a list of values from the register to use as a Dbee EQUALS/IN filter. This helps to dynamically limit the resulting record set. The key is used to specify where to grab the list of values, while the key_path will be used to craft the [Dbee equal's filter](https://github.com/bluemarblepayroll/dbee/blob/master/lib/dbee/query/filters/equals.rb). Separator is exposed in case nested object support is necessary.
|
35
|
+
* **db_fuel/dbee/query** [model, query, register, debug]: Pass in a [Dbee](https://github.com/bluemarblepayroll/dbee) model and query and store the results in the specified register. Refer to the [Dbee](https://github.com/bluemarblepayroll/dbee) library directly on how to craft a model or query.
|
36
|
+
* **db_fuel/dbee/range** [key, key_path, model, query, register, separator, debug]: Similar to `db_fuel/dbee/query` with the addition of being able to grab a list of values from the register to use as a Dbee EQUALS/IN filter. This helps to dynamically limit the resulting record set. The key is used to specify where to grab the list of values, while the key_path will be used to craft the [Dbee equal's filter](https://github.com/bluemarblepayroll/dbee/blob/master/lib/dbee/query/filters/equals.rb). Separator is exposed in case nested object support is necessary.
|
34
37
|
|
35
38
|
## Examples
|
36
39
|
|
@@ -95,6 +98,10 @@ If we were to inspect the contents of `payload` we should see the patient's resu
|
|
95
98
|
payload['patients'] # array in form of: [ { "id" => 1, "first_name" => "Something" }, ... ]
|
96
99
|
````
|
97
100
|
|
101
|
+
Notes
|
102
|
+
|
103
|
+
* Set `debug: true` to print out SQL statement in the output (not for production use.)
|
104
|
+
|
98
105
|
### Limiting Result Sets
|
99
106
|
|
100
107
|
The `db_fuel/dbee/query` does not provide a way to dynamically connect the query to existing data. You are free to put any Dbee query filters in the query declaration, but what if you would like to further limit this based on the knowledge of a range of values? The `db_fuel/dbee/range` job is meant to do exactly this. On the surface it is mainly an extension of the `db_fuel/dbee/query` job.
|
@@ -148,6 +155,10 @@ payload['patients'] # array in form of: [ { "id" => 1, "first_name" => "Somethin
|
|
148
155
|
|
149
156
|
The only difference between the query and range jobs should be the latter is limited based on the incoming first names.
|
150
157
|
|
158
|
+
Notes
|
159
|
+
|
160
|
+
* Set `debug: true` to print out SQL statement in the output (not for production use.)
|
161
|
+
|
151
162
|
### Updating the Database
|
152
163
|
|
153
164
|
#### Inserting Records
|
@@ -193,11 +204,55 @@ There should now be two new patients, AB0 and AB1, present in the table `patient
|
|
193
204
|
Notes:
|
194
205
|
|
195
206
|
* Since we specified the `primary_key`, the records' `id` attributes should be set to their respective primary key values.
|
207
|
+
* Composite primary keys are not currently supported.
|
196
208
|
* Set `debug: true` to print out each INSERT statement in the output (not for production use.)
|
197
209
|
|
210
|
+
#### Inserting Only New Records
|
211
|
+
|
212
|
+
Another job `db_fuel/active_record/find_or_insert` allows for an existence check to performed each insertion. If a record is found then it will not insert the record. If `primary_key` is set then the existence check will also still set the primary key on the payload's respective object. Note that composite primary keys are not currently supported. We can build on the above insert example for only inserting new patients if their chart_number is unique:
|
213
|
+
|
214
|
+
````ruby
|
215
|
+
pipeline = {
|
216
|
+
jobs: [
|
217
|
+
{
|
218
|
+
name: :load_patients,
|
219
|
+
type: 'b/value/static',
|
220
|
+
register: :patients,
|
221
|
+
value: [
|
222
|
+
{ chart_number: 'B0001', first_name: 'Bugs', last_name: 'Bunny' },
|
223
|
+
{ chart_number: 'B0002', first_name: 'Babs', last_name: 'Bunny' }
|
224
|
+
]
|
225
|
+
},
|
226
|
+
{
|
227
|
+
name: 'insert_patients',
|
228
|
+
type: 'db_fuel/active_record/insert',
|
229
|
+
register: :patients,
|
230
|
+
attributes: [
|
231
|
+
{ key: :chart_number },
|
232
|
+
{ key: :first_name },
|
233
|
+
{ key: :last_name }
|
234
|
+
],
|
235
|
+
table_name: 'patients',
|
236
|
+
primary_key: {
|
237
|
+
key: :id
|
238
|
+
},
|
239
|
+
unique_attributes: [
|
240
|
+
{ key: :chart_number }
|
241
|
+
]
|
242
|
+
}
|
243
|
+
]
|
244
|
+
}
|
245
|
+
|
246
|
+
payload = Burner::Payload.new
|
247
|
+
|
248
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
249
|
+
````
|
250
|
+
|
251
|
+
Now only records where the chart_number does not match an existing record will be inserted.
|
252
|
+
|
198
253
|
#### Updating Records
|
199
254
|
|
200
|
-
Let's say we now want to update
|
255
|
+
Let's say we now want to update these unique records' last names:
|
201
256
|
|
202
257
|
````ruby
|
203
258
|
pipeline = {
|
@@ -219,7 +274,92 @@ pipeline = {
|
|
219
274
|
{ key: :last_name }
|
220
275
|
],
|
221
276
|
table_name: 'patients',
|
222
|
-
|
277
|
+
primary_key: {
|
278
|
+
key: :id
|
279
|
+
},
|
280
|
+
unique_attributes: [
|
281
|
+
{ key: :chart_number }
|
282
|
+
]
|
283
|
+
}
|
284
|
+
]
|
285
|
+
}
|
286
|
+
|
287
|
+
payload = Burner::Payload.new
|
288
|
+
|
289
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
290
|
+
````
|
291
|
+
|
292
|
+
Each database record should have been updated with their new respective last names based on the primary key specified.
|
293
|
+
|
294
|
+
#### Updating All Records
|
295
|
+
|
296
|
+
Let's say we want to update those records' midddle names:
|
297
|
+
|
298
|
+
````ruby
|
299
|
+
pipeline = {
|
300
|
+
jobs: [
|
301
|
+
{
|
302
|
+
name: :load_patients,
|
303
|
+
type: 'b/value/static',
|
304
|
+
register: :patients,
|
305
|
+
value: [
|
306
|
+
{ chart_number: 'B0001', middle_name: 'Rabbit' },
|
307
|
+
{ chart_number: 'C0001', middle_name: 'Elf' }
|
308
|
+
]
|
309
|
+
},
|
310
|
+
{
|
311
|
+
name: 'update_patients',
|
312
|
+
type: 'db_fuel/active_record/update_all',
|
313
|
+
register: :patients,
|
314
|
+
attributes: [
|
315
|
+
{ key: :last_name }
|
316
|
+
],
|
317
|
+
table_name: 'patients',
|
318
|
+
unique_attributes: [
|
319
|
+
{ key: :chart_number }
|
320
|
+
]
|
321
|
+
}
|
322
|
+
]
|
323
|
+
}
|
324
|
+
|
325
|
+
payload = Burner::Payload.new
|
326
|
+
|
327
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
328
|
+
````
|
329
|
+
|
330
|
+
Each database record should have been updated with their new respective middle names based on chart_number.
|
331
|
+
|
332
|
+
#### Upserting Records
|
333
|
+
|
334
|
+
Let's say we don't know if these chart_number values already exist or not.
|
335
|
+
So we want db_fuel to either insert a record if the chart_number doesn't exist or update the record if the chart_number already exists.
|
336
|
+
|
337
|
+
````ruby
|
338
|
+
pipeline = {
|
339
|
+
jobs: [
|
340
|
+
{
|
341
|
+
name: :load_patients,
|
342
|
+
type: 'b/value/static',
|
343
|
+
register: :patients,
|
344
|
+
value: [
|
345
|
+
{ chart_number: 'B0002', first_name: 'Babs', last_name: 'Bunny' },
|
346
|
+
{ chart_number: 'B0003', first_name: 'Daffy', last_name: 'Duck' }
|
347
|
+
]
|
348
|
+
},
|
349
|
+
{
|
350
|
+
name: 'update_patients',
|
351
|
+
type: 'db_fuel/active_record/upsert',
|
352
|
+
register: :patients,
|
353
|
+
attributes: [
|
354
|
+
{ key: :chart_number },
|
355
|
+
{ key: :first_name },
|
356
|
+
{ key: :last_name }
|
357
|
+
],
|
358
|
+
table_name: 'patients',
|
359
|
+
primary_key: {
|
360
|
+
key: :id
|
361
|
+
},
|
362
|
+
unique_attributes: [
|
223
363
|
{ key: :chart_number }
|
224
364
|
]
|
225
365
|
}
|
@@ -231,11 +371,12 @@ payload = Burner::Payload.new
|
|
231
371
|
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
232
372
|
````
|
233
373
|
|
234
|
-
Each database record should have been updated with their
|
374
|
+
Each database record should have been either inserted or updated with their corresponding values. In this case Babs' last name
|
375
|
+
was switched back to Bunny and a new record was created for Daffy Duck.
|
235
376
|
|
236
377
|
Notes:
|
237
378
|
|
238
|
-
* The
|
379
|
+
* The `unique_attributes` translate to WHERE clauses.
|
239
380
|
* Set `debug: true` to print out each UPDATE statement in the output (not for production use.)
|
240
381
|
## Contributing
|
241
382
|
|
data/db_fuel.gemspec
CHANGED
@@ -11,8 +11,8 @@ Gem::Specification.new do |s|
|
|
11
11
|
This library adds database-centric jobs to the Burner library. Burner does not ship with database jobs out of the box.
|
12
12
|
DESCRIPTION
|
13
13
|
|
14
|
-
s.authors = ['Matthew Ruggio']
|
15
|
-
s.email = ['mruggio@bluemarblepayroll.com']
|
14
|
+
s.authors = ['Matthew Ruggio', 'John Bosko']
|
15
|
+
s.email = ['mruggio@bluemarblepayroll.com', 'jbosko@bluemarblepayroll.com']
|
16
16
|
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
17
|
s.bindir = 'exe'
|
18
18
|
s.executables = %w[]
|
@@ -51,7 +51,7 @@ Gem::Specification.new do |s|
|
|
51
51
|
s.add_development_dependency('pry', '~>0')
|
52
52
|
s.add_development_dependency('rake', '~> 13')
|
53
53
|
s.add_development_dependency('rspec', '~> 3.8')
|
54
|
-
s.add_development_dependency('rubocop', '~>
|
54
|
+
s.add_development_dependency('rubocop', '~>1.7.0')
|
55
55
|
s.add_development_dependency('simplecov', '~>0.18.5')
|
56
56
|
s.add_development_dependency('simplecov-console', '~>0.7.0')
|
57
57
|
s.add_development_dependency('sqlite3', '~>1')
|
data/lib/db_fuel.rb
CHANGED
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-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 DbFuel
|
11
|
+
# Intermediate internal API for Arel/ActiveRecord. There is some overlap in job needs when
|
12
|
+
# it comes to the Arel interface so this class condenses down those needs into this class.
|
13
|
+
class DbProvider # :nodoc: all
|
14
|
+
attr_reader :arel_table
|
15
|
+
|
16
|
+
def initialize(table_name)
|
17
|
+
raise ArgumentError, 'table_name is required' if table_name.to_s.empty?
|
18
|
+
|
19
|
+
@arel_table = ::Arel::Table.new(table_name.to_s)
|
20
|
+
|
21
|
+
freeze
|
22
|
+
end
|
23
|
+
|
24
|
+
def first(object)
|
25
|
+
sql = first_sql(object)
|
26
|
+
|
27
|
+
::ActiveRecord::Base.connection.exec_query(sql).first
|
28
|
+
end
|
29
|
+
|
30
|
+
def first_sql(object)
|
31
|
+
relation = arel_table.project(Arel.star).take(1)
|
32
|
+
manager = apply_where(object, relation)
|
33
|
+
|
34
|
+
manager.to_sql
|
35
|
+
end
|
36
|
+
|
37
|
+
def insert_sql(object)
|
38
|
+
insert_manager(object).to_sql
|
39
|
+
end
|
40
|
+
|
41
|
+
def insert(object)
|
42
|
+
manager = insert_manager(object)
|
43
|
+
|
44
|
+
::ActiveRecord::Base.connection.insert(manager)
|
45
|
+
end
|
46
|
+
|
47
|
+
def update(set_object, where_object)
|
48
|
+
manager = update_manager(set_object, where_object)
|
49
|
+
|
50
|
+
::ActiveRecord::Base.connection.update(manager)
|
51
|
+
end
|
52
|
+
|
53
|
+
def update_sql(set_object, where_object)
|
54
|
+
update_manager(set_object, where_object).to_sql
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def update_manager(set_object, where_object)
|
60
|
+
arel_row = make_arel_row(set_object)
|
61
|
+
update_manager = ::Arel::UpdateManager.new.set(arel_row).table(arel_table)
|
62
|
+
|
63
|
+
apply_where(where_object, update_manager)
|
64
|
+
end
|
65
|
+
|
66
|
+
def apply_where(hash, manager)
|
67
|
+
(hash || {}).inject(manager) do |memo, (key, value)|
|
68
|
+
memo.where(arel_table[key].eq(value))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def insert_manager(object)
|
73
|
+
arel_row = make_arel_row(object)
|
74
|
+
|
75
|
+
::Arel::InsertManager.new.insert(arel_row)
|
76
|
+
end
|
77
|
+
|
78
|
+
def make_arel_row(row)
|
79
|
+
row.map { |key, value| [arel_table[key], value] }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/db_fuel/library.rb
CHANGED
@@ -7,8 +7,11 @@
|
|
7
7
|
# LICENSE file in the root directory of this source tree.
|
8
8
|
#
|
9
9
|
|
10
|
+
require_relative 'library/active_record/find_or_insert'
|
10
11
|
require_relative 'library/active_record/insert'
|
11
12
|
require_relative 'library/active_record/update'
|
13
|
+
require_relative 'library/active_record/update_all'
|
14
|
+
require_relative 'library/active_record/upsert'
|
12
15
|
|
13
16
|
require_relative 'library/dbee/query'
|
14
17
|
require_relative 'library/dbee/range'
|
@@ -16,10 +19,13 @@ require_relative 'library/dbee/range'
|
|
16
19
|
module Burner
|
17
20
|
# Open up Burner::Jobs and add registrations for this libraries jobs.
|
18
21
|
class Jobs
|
19
|
-
register 'db_fuel/active_record/
|
20
|
-
register 'db_fuel/active_record/
|
22
|
+
register 'db_fuel/active_record/find_or_insert', DbFuel::Library::ActiveRecord::FindOrInsert
|
23
|
+
register 'db_fuel/active_record/insert', DbFuel::Library::ActiveRecord::Insert
|
24
|
+
register 'db_fuel/active_record/update', DbFuel::Library::ActiveRecord::Update
|
25
|
+
register 'db_fuel/active_record/update_all', DbFuel::Library::ActiveRecord::UpdateAll
|
26
|
+
register 'db_fuel/active_record/upsert', DbFuel::Library::ActiveRecord::Upsert
|
21
27
|
|
22
|
-
register 'db_fuel/dbee/query',
|
23
|
-
register 'db_fuel/dbee/range',
|
28
|
+
register 'db_fuel/dbee/query', DbFuel::Library::Dbee::Query
|
29
|
+
register 'db_fuel/dbee/range', DbFuel::Library::Dbee::Range
|
24
30
|
end
|
25
31
|
end
|
@@ -19,10 +19,11 @@ module DbFuel
|
|
19
19
|
NOW_TYPE = 'r/value/now'
|
20
20
|
UPDATED_AT = :updated_at
|
21
21
|
|
22
|
-
attr_reader :
|
23
|
-
:
|
22
|
+
attr_reader :attribute_renderers,
|
23
|
+
:db_provider,
|
24
24
|
:debug,
|
25
|
-
:resolver
|
25
|
+
:resolver,
|
26
|
+
:attribute_renderers_set
|
26
27
|
|
27
28
|
def initialize(
|
28
29
|
name:,
|
@@ -34,45 +35,20 @@ module DbFuel
|
|
34
35
|
)
|
35
36
|
super(name: name, register: register)
|
36
37
|
|
37
|
-
@arel_table = ::Arel::Table.new(table_name.to_s)
|
38
|
-
@debug = debug || false
|
39
|
-
|
40
|
-
# set resolver first since make_attribute_renderers needs it.
|
41
38
|
@resolver = Objectable.resolver(separator: separator)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
@attribute_renderers_set = Modeling::AttributeRendererSet.new(attributes: attributes,
|
40
|
+
resolver: resolver)
|
41
|
+
@db_provider = DbProvider.new(table_name)
|
42
|
+
@debug = debug || false
|
46
43
|
end
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
def timestamp_attribute(key)
|
51
|
-
Burner::Modeling::Attribute.make(
|
52
|
-
key: key,
|
53
|
-
transformers: [
|
54
|
-
{ type: NOW_TYPE }
|
55
|
-
]
|
56
|
-
)
|
57
|
-
end
|
45
|
+
protected
|
58
46
|
|
59
47
|
def debug_detail(output, message)
|
60
48
|
return unless debug
|
61
49
|
|
62
50
|
output.detail(message)
|
63
51
|
end
|
64
|
-
|
65
|
-
def make_arel_row(row)
|
66
|
-
row.map { |key, value| [arel_table[key], value] }
|
67
|
-
end
|
68
|
-
|
69
|
-
def transform(row, time)
|
70
|
-
attribute_renderers.each_with_object({}) do |attribute_renderer, memo|
|
71
|
-
value = attribute_renderer.transform(row, time)
|
72
|
-
|
73
|
-
resolver.set(memo, attribute_renderer.key, value)
|
74
|
-
end
|
75
|
-
end
|
76
52
|
end
|
77
53
|
end
|
78
54
|
end
|