quickery 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +150 -21
- data/lib/generators/quickery/migration/migration_generator.rb +44 -0
- data/lib/generators/quickery/migration/templates/migration.rb.erb +15 -0
- data/lib/quickery/active_record_extensions/callbacks.rb +37 -16
- data/lib/quickery/active_record_extensions/dsl.rb +20 -1
- data/lib/quickery/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef98d8559e4364a5532777fc264d895dab630d914475bf663978798f5fce932c
|
4
|
+
data.tar.gz: ab4eda789c789b451d68a7839e508aef9a4178c039c250207a79d85e09b97ccf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62d2462169148384f2bdd6675bfbbc70a0fc5908b63be6c0e14726f75ac678c083e8c9fa8621f4decb857074d130724c9e7ff7b417f0d5e32e2f92a815ee33e5
|
7
|
+
data.tar.gz: 57f167d27cf38b2b4e1753f3ec6fbf81843d6f67e452310041f16acf63daba26ca9202ccc64bda393cca3e1ea30f3acbe6da57ec6b1a6e46b7cb7eedbcd7d1ba
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@
|
|
26
26
|
bundle install
|
27
27
|
```
|
28
28
|
|
29
|
-
## Usage Example 1
|
29
|
+
## Usage Example 1 - Mapped Attribute
|
30
30
|
|
31
31
|
```ruby
|
32
32
|
# app/models/employee.rb
|
@@ -63,7 +63,8 @@ end
|
|
63
63
|
|
64
64
|
```bash
|
65
65
|
# bash
|
66
|
-
rails generate migration
|
66
|
+
rails generate quickery:migration employee branch_company_name:string
|
67
|
+
# or: rails generate migration add_branch_company_name_to_employees branch_company_name:string
|
67
68
|
bundle exec rake db:migrate
|
68
69
|
```
|
69
70
|
|
@@ -100,7 +101,10 @@ puts employee.branch_company_name
|
|
100
101
|
# => 'McDonalds'
|
101
102
|
```
|
102
103
|
|
103
|
-
If you already have "old" records before you've integrated quickery or if you have new quickery-defined attributes, you can update these stale records
|
104
|
+
If you already have "old" records before you've integrated quickery or if you have new quickery-defined attributes, you can update these stale records...
|
105
|
+
|
106
|
+
1. by using `autoload_unsynced_quickery_attributes!` (see Usage Example 3 below), or...
|
107
|
+
2. by using `recreate_quickery_cache!`. See example below:
|
104
108
|
|
105
109
|
```ruby
|
106
110
|
# rails console
|
@@ -109,9 +113,9 @@ Employee.find_each do |employee|
|
|
109
113
|
end
|
110
114
|
```
|
111
115
|
|
112
|
-
## Usage Example 2
|
116
|
+
## Usage Example 2 - Association via Mapped Attribute
|
113
117
|
|
114
|
-
* let `Branch` and `Company`
|
118
|
+
* let `Branch` and `Company` models be the same as the Usage Example 1 above
|
115
119
|
|
116
120
|
```ruby
|
117
121
|
# app/models/employee.rb
|
@@ -125,7 +129,8 @@ end
|
|
125
129
|
|
126
130
|
```bash
|
127
131
|
# bash
|
128
|
-
rails generate migration
|
132
|
+
rails generate quickery:migration employee branch_company_id:bigint:index
|
133
|
+
# or: rails generate migration add_branch_company_id_to_employees branch_company_id:bigint:index
|
129
134
|
bundle exec rake db:migrate
|
130
135
|
```
|
131
136
|
|
@@ -150,6 +155,54 @@ puts Employee.joins(branch: :company).where(companies: { id: company.id })
|
|
150
155
|
# => [#<Employee id: 1>]
|
151
156
|
```
|
152
157
|
|
158
|
+
## Usage Example 3 - Autoloading Quickery Attributes
|
159
|
+
|
160
|
+
> `autoload_unsynced_quickery_attributes!` below is **ONLY** compatible with optional `*_is_synced` attributes, which can be done by passing `--add_is_synced_attributes` to the `quickery:migration` generator. See example below.
|
161
|
+
|
162
|
+
* let `Branch` and `Company` models be the same as the Usage Example 1 above
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
# app/models/employee.rb
|
166
|
+
class Employee < ApplicationRecord
|
167
|
+
belongs_to :branch
|
168
|
+
|
169
|
+
quickery { branch: { company: { id: :branch_company_name } } }
|
170
|
+
|
171
|
+
after_find :autoload_unsynced_quickery_attributes!
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
```bash
|
176
|
+
# bash
|
177
|
+
rails generate quickery:migration employee branch_company_name:string --add_is_synced_attributes
|
178
|
+
bundle exec rake db:migrate
|
179
|
+
```
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
# rails console
|
183
|
+
company = Company.create!(name: 'Jollibee')
|
184
|
+
branch = Branch.create!(company: company)
|
185
|
+
employee_created_before_quickery_integration = Employee.create!(branch: branch)
|
186
|
+
|
187
|
+
puts employee_created_before_quickery_integration.branch_company_name
|
188
|
+
# => NoMethodError: undefined method `branch_company_name'
|
189
|
+
|
190
|
+
# Let's say the employee record above was created long time ago before Quickery was integrated,
|
191
|
+
# and then right now, you added the new quickery-attribute `branch_company_name`.
|
192
|
+
|
193
|
+
# Employee record above now then will have "stale" value for `branch_company_name`,
|
194
|
+
# because it will have a value of `nil`.
|
195
|
+
# But using `after_find :autoload_unsynced_quickery_attributes!` above, all records will
|
196
|
+
# then be guaranteed to have up-to-date quickery attributes even if new quickery-attributes
|
197
|
+
# will be defined in the future.
|
198
|
+
|
199
|
+
puts employee_created_before_quickery_integration.branch_company_name
|
200
|
+
# => 'Employee'
|
201
|
+
|
202
|
+
# if without `after_find :autoload_unsynced_quickery_attributes!`, the puts just above will instead show
|
203
|
+
# => nil
|
204
|
+
```
|
205
|
+
|
153
206
|
## Other Usage Examples
|
154
207
|
|
155
208
|
```ruby
|
@@ -281,19 +334,17 @@ class Employee < ApplicationRecord
|
|
281
334
|
|
282
335
|
# example (you can rename this method):
|
283
336
|
def self.quickery_format_values(values)
|
284
|
-
formatted_values = {}
|
285
|
-
|
286
337
|
:branch_company_name.tap do |attr|
|
287
338
|
# remove trailing white spaces and force-single-space between words, and then capitalise all characters
|
288
|
-
|
339
|
+
values[attr] = values[attr].squish.upcase if values.has_key? attr
|
289
340
|
end
|
290
341
|
|
291
342
|
:user_first_name.tap do |attr|
|
292
343
|
# only save the first 30 characters of user_first_name string
|
293
|
-
|
344
|
+
values[attr] = values[attr][0...30] if values.has_key? attr
|
294
345
|
end
|
295
346
|
|
296
|
-
|
347
|
+
values
|
297
348
|
end
|
298
349
|
end
|
299
350
|
```
|
@@ -310,6 +361,8 @@ class Employee < ApplicationRecord
|
|
310
361
|
employee.assign_attributes(quickery_with_computed_values(employee, new_values))
|
311
362
|
end
|
312
363
|
|
364
|
+
# IMPORTANT: for big tables, `find_each` below can be slow (consider moving into a background job or if possible use the default behaviour which is `update_all`)
|
365
|
+
|
313
366
|
def self.quickery_before_association_update(employees, record_to_be_updated, new_values)
|
314
367
|
employee.find_each do |employee|
|
315
368
|
employee.update!(quickery_with_computed_values(employee, new_values))
|
@@ -326,22 +379,22 @@ class Employee < ApplicationRecord
|
|
326
379
|
|
327
380
|
# example (you can rename this method):
|
328
381
|
def self.quickery_with_computed_values(employee, values)
|
329
|
-
with_computed_values = {}
|
330
|
-
|
331
382
|
if values.has_key?(:user_first_name) || values.has_key?(:user_last_name)
|
383
|
+
employee.user_first_name = values[:user_first_name] if values.has_key?(:user_first_name)
|
384
|
+
employee.user_last_name = values[:user_last_name] if values.has_key?(:user_last_name)
|
332
385
|
# concatenate first name and last name
|
333
|
-
|
386
|
+
values[:user_full_name] = "#{employee.user_first_name} #{employee.user_last_name}".strip
|
334
387
|
end
|
335
388
|
|
336
389
|
# you can add logic that specifically depends on the record like the following:
|
337
390
|
if employee.is_current_employee?
|
338
|
-
if values.has_key? :
|
391
|
+
if values.has_key? :branch_company_id
|
339
392
|
# concatenate a unique code for the employee: i.e. a value of "11-5-1239"
|
340
|
-
|
393
|
+
values[:unique_codename] = "#{employee.branch.company.id}-#{employee.branch.id}-#{employee.id}"
|
341
394
|
end
|
342
395
|
end
|
343
396
|
|
344
|
-
|
397
|
+
values
|
345
398
|
end
|
346
399
|
end
|
347
400
|
```
|
@@ -352,6 +405,56 @@ end
|
|
352
405
|
|
353
406
|
## DSL
|
354
407
|
|
408
|
+
### Quickery Migration Generator:
|
409
|
+
|
410
|
+
`rails generate quickery:migration ...` acts as if you are doing a `rails generate model ...` except that it's ONLY going to generate a migration file, therefore:
|
411
|
+
|
412
|
+
* Usage format: `rails generate quickery:migration model_name attribute_name_1:type attribute_name_2:type ...`
|
413
|
+
* Optional `--add_is_synced_attributes` can be passed to the command to support "autoloading". See Usage Example 3 above.
|
414
|
+
|
415
|
+
#### Example 1
|
416
|
+
```
|
417
|
+
rails generate quickery:migration employee branch_company_name:string branch_company_id:bigint:index
|
418
|
+
```
|
419
|
+
|
420
|
+
...will generate:
|
421
|
+
|
422
|
+
```
|
423
|
+
# db/migrate/TIMESTAMP_add_quickery_branch_company_name_branch_company_id_to_employees.rb
|
424
|
+
class AddQuickeryBranchCompanyNameBranchCompanyIdToEmployees < ActiveRecord::Migration[5.2]
|
425
|
+
def change
|
426
|
+
change_table :employees do |t|
|
427
|
+
t.string :branch_company_name
|
428
|
+
t.integer :branch_company_id
|
429
|
+
end
|
430
|
+
add_index :employees, :branch_company_id
|
431
|
+
end
|
432
|
+
end
|
433
|
+
```
|
434
|
+
|
435
|
+
#### Example 2
|
436
|
+
|
437
|
+
```
|
438
|
+
rails generate quickery:migration employee branch_company_name:string branch_company_id:bigint:index --add_is_synced_attributes
|
439
|
+
```
|
440
|
+
|
441
|
+
...will generate:
|
442
|
+
|
443
|
+
```
|
444
|
+
# db/migrate/TIMESTAMP_add_quickery_branch_company_name_branch_company_id_to_employees.rb
|
445
|
+
class AddQuickeryBranchCompanyNameBranchCompanyIdToEmployees < ActiveRecord::Migration[5.2]
|
446
|
+
def change
|
447
|
+
change_table :employees do |t|
|
448
|
+
t.string :branch_company_name
|
449
|
+
t.boolean :branch_company_name_is_synced, null: false, default: false
|
450
|
+
t.integer :branch_company_id
|
451
|
+
t.boolean :branch_company_id_is_synced, null: false, default: false
|
452
|
+
end
|
453
|
+
add_index :employees, :branch_company_id
|
454
|
+
end
|
455
|
+
end
|
456
|
+
```
|
457
|
+
|
355
458
|
### For any subclass of `ActiveRecord::Base`:
|
356
459
|
|
357
460
|
* defines a set of "hidden" Quickery `before_create`, `before_update`, and `before_destroy` callbacks needed by Quickery to perform the "syncing" of attribute values
|
@@ -362,17 +465,17 @@ end
|
|
362
465
|
|
363
466
|
##### `quickery(mappings)`
|
364
467
|
* mappings (Hash)
|
365
|
-
* each mapping will create a `Quickery::QuickeryBuilder` object. i.e:
|
468
|
+
* each mapping will create a `Quickery::QuickeryBuilder` object. i.e:s
|
366
469
|
* `{ branch: { name: :branch_name }` will create one `Quickery::QuickeryBuilder`, while
|
367
470
|
* `{ branch: { name: :branch_name, id: :branch_id }` will create two `Quickery::QuickeryBuilder`
|
368
471
|
* In this particular example, you are required to specify `belongs_to :branch` in this model
|
369
|
-
* Similarly, you
|
370
|
-
* quickery-defined attributes such as say `:branch_company_country_category_name` are updated by Quickery automatically whenever any of it's dependent records across models have been changed. Note that updates in this way do not trigger model callbacks,
|
472
|
+
* Similarly, depending on your defined mappings, i.e. `{ branch: { company: { country: { name: :branch_company_country_name } } } }`, you would be required to specify `belongs_to :company` inside `Branch` model, `belongs_to :country` inside `Company` model; etc...
|
473
|
+
* quickery-defined attributes such as say `:branch_company_country_category_name` are updated by Quickery automatically whenever any of it's dependent records / dependee-attribute across models have been changed or destroyed. Note that updates in this way do not trigger model callbacks, unless you manually overrode the quickery model methods: `self.quickery_before_association_update` or `self.quickery_before_association_destroy`, and changed the default behaviour to no longer use `update_all`. I use `update_all` by default to improve speed and to bypass validations because attributes that will be updated are just your quickery-defined attributes anyway, and chances are you would not want any validations for these attributes.
|
371
474
|
* quickery-defined attributes such as say `:branch_company_country_category_name` are READ-only! Do not update these attributes manually. You can, but it will not automatically update the other end, and thus will break data integrity. If you want to re-update these attributes to match the other end, see `recreate_quickery_cache!` below.
|
372
475
|
|
373
476
|
##### `quickery_builders`
|
374
477
|
* returns an `Array` of `Quickery::QuickeryBuilder` objects that have already been defined
|
375
|
-
* for more info, see `quickery(
|
478
|
+
* for more info, see `quickery(mappings)` above
|
376
479
|
* you normally do not need to use this method
|
377
480
|
|
378
481
|
#### Instance Methods:
|
@@ -408,10 +511,34 @@ end
|
|
408
511
|
# => { branch_company_country_id: 1, branch_compnay_country_name: 'Ireland' }
|
409
512
|
```
|
410
513
|
|
514
|
+
##### `autoload_unsynced_quickery_attributes!`
|
515
|
+
* only works in conjuction with `*_is_synced` attributes.
|
516
|
+
* this will update the record's "still unsynced" quickery-attributes.
|
517
|
+
* if all of the record's quickery-attributes are already "synced", then this method does nothing more
|
518
|
+
* intended to be used as callback method for `after_find` to automatically support both 1) "old-records" that before quickery has been integrated, and 2) new quickery-attributes to be defined in the future
|
519
|
+
* i.e. you can do something like the following:
|
520
|
+
|
521
|
+
```ruby
|
522
|
+
class Employee < ApplicationRecord
|
523
|
+
belongs_to :branch
|
524
|
+
quickery branch: { company: { name: :branch_company_name } }
|
525
|
+
after_find :autoload_unsynced_quickery_attributes!
|
526
|
+
end
|
527
|
+
|
528
|
+
an_employee_long_time_ago_before_quickery_was_even_integrated = Employee.first
|
529
|
+
|
530
|
+
puts an_employee_long_time_ago_before_quickery_was_even_integrated.branch_company_name
|
531
|
+
# => 'Jollibee'
|
532
|
+
|
533
|
+
# otherwise, if there is no `after_find :autoload_unsynced_quickery_attributes!`, the `puts` above will instead return
|
534
|
+
# => nil
|
535
|
+
```
|
536
|
+
|
411
537
|
## TODOs
|
412
538
|
* Possibly support two-way mapping of attributes? So that you can do, say... `employee.update!(branch_company_name: 'somenewcompanyname')`
|
413
539
|
* Support `has_many` as currently only `belongs_to` is supported. This would then allow us to cache Array of values.
|
414
540
|
* Support custom-methods-values like [`persistize`](https://github.com/bebanjo/persistize), if it's easy enough to integrate something similar
|
541
|
+
* Provide a better DSL for "Computed Values" and also probably "Formatted Values" as the current example above, though flexible, looks like it has too much code and the method can potentially grow very big; probably separate into a defined method per computed/formatted value?
|
415
542
|
|
416
543
|
## Other Similar Gems
|
417
544
|
See [my detailed comparisons](other_similar_gems_comparison.md)
|
@@ -436,6 +563,8 @@ See [my detailed comparisons](other_similar_gems_comparison.md)
|
|
436
563
|
5. Create new Pull Request
|
437
564
|
|
438
565
|
## Changelog
|
566
|
+
* 1.3.0
|
567
|
+
* implemented tracking of which quickery-attributes have already been synced / not yet via additional optional `*_is_synced` attributes; used in conjuction with [`autoload_unsynced_quickery_attributes!`](#autoload_unsynced_quickery_attributes) intentionally to be declared as callback method for `after_find`, which will make sure that new quickery-attributes defined in the future will work immediately for the record, and that the developer won't worry about doing the `recreate_quickery_cache!` anymore, as the record is guaranteed to be always up-to-date.
|
439
568
|
* 1.2.0
|
440
569
|
* DONE: (TODO) added overrideable methods for custom callback logic (i.e. move update logic instead into a background job)
|
441
570
|
* 1.1.0
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
module Quickery
|
4
|
+
module Generators
|
5
|
+
class MigrationGenerator < ActiveRecord::Generators::Base
|
6
|
+
desc 'Generate migration for quickery attributes'
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
|
9
|
+
argument :attributes, required: true, type: :array, desc: 'The quickery-attributes',
|
10
|
+
banner: 'company_name:string company_country_id:integer company_country_name:string ...'
|
11
|
+
|
12
|
+
class_option :add_is_synced_attributes, desc: 'Add extra `*_is_synced` attribute per quickery-attribute', default: nil
|
13
|
+
|
14
|
+
def generate_migration
|
15
|
+
migration_template("migration.rb.erb",
|
16
|
+
"db/migrate/#{migration_file_name}.rb",
|
17
|
+
migration_version: migration_version)
|
18
|
+
end
|
19
|
+
|
20
|
+
def migration_name
|
21
|
+
"add_quickery_#{attributes.map(&:name).join("_")}_to_#{name.underscore.pluralize}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def migration_file_name
|
25
|
+
"#{migration_name}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def migration_class_name
|
29
|
+
migration_name.camelize
|
30
|
+
end
|
31
|
+
|
32
|
+
def migration_version
|
33
|
+
if Rails.version.start_with? "5"
|
34
|
+
"[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# https://github.com/rails/rails/blob/v5.2.1/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb#L62
|
39
|
+
def attributes_with_index
|
40
|
+
attributes.select { |a| !a.reference? && a.has_index? }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
|
2
|
+
def change
|
3
|
+
change_table :<%= table_name %> do |t|
|
4
|
+
<% attributes.each do |attribute| -%>
|
5
|
+
t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
|
6
|
+
<% if options[:add_is_synced_attributes] -%>
|
7
|
+
t.boolean :<%= attribute.name %>_is_synced, null: false, default: false
|
8
|
+
<% end -%>
|
9
|
+
<% end -%>
|
10
|
+
end
|
11
|
+
<% attributes_with_index.each do |attribute| -%>
|
12
|
+
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
13
|
+
<% end -%>
|
14
|
+
end
|
15
|
+
end
|
@@ -41,6 +41,9 @@ module Quickery
|
|
41
41
|
|
42
42
|
new_values[depender_column_name] = new_value
|
43
43
|
end
|
44
|
+
|
45
|
+
# set to true because on-create, all quickery-attributes are evaluated and assigned
|
46
|
+
new_values[:"#{depender_column_name}_is_synced"] = true if has_attribute? :"#{depender_column_name}_is_synced"
|
44
47
|
end
|
45
48
|
|
46
49
|
self.class.quickery_before_create_or_update(self, new_values)
|
@@ -68,6 +71,7 @@ module Quickery
|
|
68
71
|
end
|
69
72
|
|
70
73
|
new_values[depender_column_name] = new_value
|
74
|
+
new_values[:"#{depender_column_name}_is_synced"] = true if has_attribute? :"#{depender_column_name}_is_synced"
|
71
75
|
end
|
72
76
|
end
|
73
77
|
|
@@ -87,10 +91,14 @@ module Quickery
|
|
87
91
|
|
88
92
|
dependent_records = association_chain_dependee.dependent_records(self)
|
89
93
|
# use the SQL as the uniqueness identifier, so that multiple quickery-attributes dependent-records are updated in one go, instead of updating each
|
90
|
-
|
91
|
-
dependent_records_attributes_to_be_updated[
|
92
|
-
dependent_records_attributes_to_be_updated[
|
93
|
-
dependent_records_attributes_to_be_updated[
|
94
|
+
records_sql_identifier = dependent_records.to_sql.to_sym
|
95
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier] ||= {}.with_indifferent_access
|
96
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:dependent_records] ||= dependent_records
|
97
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values] ||= {}.with_indifferent_access
|
98
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values][depender_column_name.to_sym] = new_value
|
99
|
+
if dependent_records.model.column_names.include? "#{depender_column_name}_is_synced"
|
100
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values][:"#{depender_column_name}_is_synced"] = true
|
101
|
+
end
|
94
102
|
end
|
95
103
|
end
|
96
104
|
end
|
@@ -111,10 +119,15 @@ module Quickery
|
|
111
119
|
|
112
120
|
dependent_records = association_chain_intermediary.dependent_records(self)
|
113
121
|
# use the SQL as the uniqueness identifier, so that multiple quickery-attributes dependent-records are updated in one go, instead of updating each
|
114
|
-
|
115
|
-
dependent_records_attributes_to_be_updated[
|
116
|
-
dependent_records_attributes_to_be_updated[
|
117
|
-
dependent_records_attributes_to_be_updated[
|
122
|
+
records_sql_identifier = dependent_records.to_sql.to_sym
|
123
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier] ||= {}.with_indifferent_access
|
124
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:dependent_records] ||= dependent_records
|
125
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values] ||= {}.with_indifferent_access
|
126
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values][depender_column_name.to_sym] = new_value
|
127
|
+
|
128
|
+
if dependent_records.model.column_names.include? "#{depender_column_name}_is_synced"
|
129
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values][:"#{depender_column_name}_is_synced"] = true
|
130
|
+
end
|
118
131
|
end
|
119
132
|
end
|
120
133
|
end
|
@@ -143,10 +156,14 @@ module Quickery
|
|
143
156
|
|
144
157
|
dependent_records = association_chain_dependee.dependent_records(self)
|
145
158
|
# use the SQL as the uniqueness identifier, so that multiple quickery-attributes dependent-records are updated in one go, instead of updating each
|
146
|
-
|
147
|
-
dependent_records_attributes_to_be_updated[
|
148
|
-
dependent_records_attributes_to_be_updated[
|
149
|
-
dependent_records_attributes_to_be_updated[
|
159
|
+
records_sql_identifier = dependent_records.to_sql.to_sym
|
160
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier] ||= {}.with_indifferent_access
|
161
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:dependent_records] ||= dependent_records
|
162
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values] ||= {}.with_indifferent_access
|
163
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values][depender_column_name.to_sym] = new_value
|
164
|
+
if dependent_records.model.column_names.include? "#{depender_column_name}_is_synced"
|
165
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values][:"#{depender_column_name}_is_synced"] = true
|
166
|
+
end
|
150
167
|
end
|
151
168
|
end
|
152
169
|
end
|
@@ -162,10 +179,14 @@ module Quickery
|
|
162
179
|
|
163
180
|
dependent_records = association_chain_intermediary.dependent_records(self)
|
164
181
|
# use the SQL as the uniqueness identifier, so that multiple quickery-attributes dependent-records are updated in one go, instead of updating each
|
165
|
-
|
166
|
-
dependent_records_attributes_to_be_updated[
|
167
|
-
dependent_records_attributes_to_be_updated[
|
168
|
-
dependent_records_attributes_to_be_updated[
|
182
|
+
records_sql_identifier = dependent_records.to_sql.to_sym
|
183
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier] ||= {}.with_indifferent_access
|
184
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:dependent_records] ||= dependent_records
|
185
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values] ||= {}.with_indifferent_access
|
186
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values][depender_column_name.to_sym] = new_value
|
187
|
+
if dependent_records.model.column_names.include? "#{depender_column_name}_is_synced"
|
188
|
+
dependent_records_attributes_to_be_updated[records_sql_identifier][:new_values][:"#{depender_column_name}_is_synced"] = true
|
189
|
+
end
|
169
190
|
end
|
170
191
|
end
|
171
192
|
end
|
@@ -19,6 +19,8 @@ module Quickery
|
|
19
19
|
mappings_builder.map_attributes
|
20
20
|
end
|
21
21
|
|
22
|
+
private
|
23
|
+
|
22
24
|
# subclass overrideable
|
23
25
|
def quickery_before_create_or_update(dependent_record, new_values)
|
24
26
|
dependent_record.assign_attributes(new_values)
|
@@ -44,7 +46,7 @@ module Quickery
|
|
44
46
|
end
|
45
47
|
|
46
48
|
def determine_quickery_value(depender_column_name)
|
47
|
-
quickery_builder = self.class.quickery_builders[depender_column_name]
|
49
|
+
quickery_builder = self.class.quickery_builders[depender_column_name.to_sym]
|
48
50
|
|
49
51
|
raise ArgumentError, "No defined quickery builder for #{depender_column_name}. Defined values are #{self.class.quickery_builders.keys}" unless quickery_builder
|
50
52
|
|
@@ -59,6 +61,23 @@ module Quickery
|
|
59
61
|
end
|
60
62
|
quickery_values
|
61
63
|
end
|
64
|
+
|
65
|
+
# only considers quickery-defined attributes that has corresponding *_is_synced attribute
|
66
|
+
def autoload_unsynced_quickery_attributes!
|
67
|
+
model = self.class
|
68
|
+
new_values = {}.with_indifferent_access
|
69
|
+
|
70
|
+
defined_quickery_attribute_names = model.quickery_builders.keys
|
71
|
+
|
72
|
+
defined_quickery_attribute_names.each do |defined_quickery_attribute_name|
|
73
|
+
if has_attribute?(:"#{defined_quickery_attribute_name}_is_synced") && !send(:"#{defined_quickery_attribute_name}_is_synced")
|
74
|
+
new_values[defined_quickery_attribute_name] = determine_quickery_value(defined_quickery_attribute_name)
|
75
|
+
new_values[:"#{defined_quickery_attribute_name}_is_synced"] = true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
update_columns(new_values) if new_values.present?
|
80
|
+
end
|
62
81
|
end
|
63
82
|
end
|
64
83
|
end
|
data/lib/quickery/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quickery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jules Roman Polidario
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -247,6 +247,8 @@ files:
|
|
247
247
|
- gemfiles/.bundle/config
|
248
248
|
- gemfiles/rails_4.gemfile
|
249
249
|
- gemfiles/rails_5.gemfile
|
250
|
+
- lib/generators/quickery/migration/migration_generator.rb
|
251
|
+
- lib/generators/quickery/migration/templates/migration.rb.erb
|
250
252
|
- lib/quickery.rb
|
251
253
|
- lib/quickery/active_record_extensions.rb
|
252
254
|
- lib/quickery/active_record_extensions/callbacks.rb
|