column_sync 0.1.0 → 0.2.0
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 +1 -1
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +4 -4
- data/README.md +57 -2
- data/lib/column_sync/migration.rb +3 -0
- data/lib/column_sync/model.rb +48 -0
- data/lib/column_sync/version.rb +1 -1
- data/lib/column_sync.rb +1 -0
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7f7eb5d8496290fa5def80e98ad2460c2c594138b0ee1742ec352cd26df5cab
|
4
|
+
data.tar.gz: 63d4bcc6b35668f914912912dcc1c46aff154aa8396d3a6297e01eb66c09da8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d1024c86f3847a7fd510abb2fb9cd9292204559ba7098c1ae04c1731e829f527b1a62104a9d13803cd954975ea3d2b993ee603494154d2f952404e91788ba8b
|
7
|
+
data.tar.gz: f7ca54ddd71c6e2e43dd1619e6530203f75eb2e597b1bb0a77f9d5df6434bc6d7167b07b3d86d699ef2ddf4dfa051c09068cf374943df18798956c2836e527aa
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
column_sync (0.
|
4
|
+
column_sync (0.2.0)
|
5
|
+
fx (~> 0.8.0)
|
6
|
+
pg (~> 1.5.4)
|
7
|
+
rails (>= 6.0.0)
|
5
8
|
|
6
9
|
GEM
|
7
10
|
remote: https://rubygems.org/
|
@@ -213,9 +216,6 @@ PLATFORMS
|
|
213
216
|
|
214
217
|
DEPENDENCIES
|
215
218
|
column_sync!
|
216
|
-
fx (~> 0.8.0)
|
217
|
-
pg (~> 1.5.4)
|
218
|
-
rails (>= 6.0.0)
|
219
219
|
rubocop
|
220
220
|
|
221
221
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -32,12 +32,67 @@ end
|
|
32
32
|
|
33
33
|
The migration above generates the functions and triggers needed to keep `subscriptions.country_code` in sync with `companies.country`.
|
34
34
|
|
35
|
+
You also need to update your models to reflect the syncroniaztion between their columns:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
class Company < ApplicationRecord
|
39
|
+
include ColumnSync::Model
|
40
|
+
|
41
|
+
has_one :subscription
|
42
|
+
|
43
|
+
sync_column :country, to: :subscription, column: :country_code
|
44
|
+
end
|
45
|
+
|
46
|
+
class Subscription < ApplicationRecord
|
47
|
+
include ColumnSync::Model
|
48
|
+
|
49
|
+
belongs_to :company
|
50
|
+
|
51
|
+
sync_column :country_code, to: :company, column: :country
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
## Example
|
56
|
+
|
57
|
+
Given the following scenario:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
Company.create!(country: "es")
|
61
|
+
Subscription.create!(country_code: "es", company: Company.first)
|
62
|
+
```
|
63
|
+
|
64
|
+
Changes are reflected in memory when the value is modified:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
company = Company.first
|
68
|
+
company.country = "fr"
|
69
|
+
company.subscription.country_code
|
70
|
+
# => "fr"
|
71
|
+
|
72
|
+
company.subscription.country_code = "ca"
|
73
|
+
company.country
|
74
|
+
# => "ca"
|
75
|
+
```
|
76
|
+
|
77
|
+
Changes are also reflected in the DB when the value is persisted:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
company = Company.first
|
81
|
+
company.update(country: "it")
|
82
|
+
company.subscription.country_code
|
83
|
+
# => "it"
|
84
|
+
|
85
|
+
company.subscription.update(country_code: "ma")
|
86
|
+
company.country
|
87
|
+
# => "ma"
|
88
|
+
```
|
89
|
+
|
35
90
|
## Limitations
|
36
91
|
|
37
92
|
- Each `sync_columns` statement can only sync a pair of columns. If the same column needs to be synchronized across multiple
|
38
93
|
tables, multiple such statements will be needed.
|
39
94
|
- The gem expects a `has_one` - `belongs_to` association between the models involved. It uses Rails reflections to understand
|
40
95
|
the table names and column names involved.
|
41
|
-
-
|
42
|
-
|
96
|
+
- It is assumed that the records are initially in sync, so it does **not** automatically sync values using any of the two
|
97
|
+
columns involved.
|
43
98
|
- It also does not sync values when a row is created, only when it is modified.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "active_support/concern"
|
2
|
+
|
3
|
+
module ColumnSync
|
4
|
+
module Model
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
scope :disabled, -> { where(disabled: true) }
|
9
|
+
|
10
|
+
before_update :propagate_changes
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def propagate_changes
|
15
|
+
changes.each do |attribute, (_before, after)|
|
16
|
+
propagate_changes_in_memory(attribute, after)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def propagate_changes_in_memory(attribute, value)
|
21
|
+
self.class.columns_to_sync[attribute]&.each do |sync|
|
22
|
+
object = public_send(sync[:to])
|
23
|
+
next unless object
|
24
|
+
|
25
|
+
current_value = object.attributes[sync[:column].to_s]
|
26
|
+
|
27
|
+
object.public_send("#{sync[:column]}=", value) if current_value.to_s != value.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class_methods do
|
33
|
+
attr_reader :columns_to_sync
|
34
|
+
|
35
|
+
def sync_column(column_name, to:, column:)
|
36
|
+
@columns_to_sync ||= {}
|
37
|
+
@columns_to_sync[column_name.to_s] ||= []
|
38
|
+
@columns_to_sync[column_name.to_s] << { to: to, column: column }
|
39
|
+
|
40
|
+
define_method("#{column_name}=") do |value|
|
41
|
+
super(value)
|
42
|
+
|
43
|
+
propagate_changes_in_memory(column_name.to_s, value)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/column_sync/version.rb
CHANGED
data/lib/column_sync.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: column_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manuel Bustillo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-12-
|
11
|
+
date: 2023-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fx
|
@@ -17,7 +17,7 @@ dependencies:
|
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.8.0
|
20
|
-
type: :
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 1.5.4
|
34
|
-
type: :
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
@@ -45,7 +45,7 @@ dependencies:
|
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 6.0.0
|
48
|
-
type: :
|
48
|
+
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- Rakefile
|
83
83
|
- lib/column_sync.rb
|
84
84
|
- lib/column_sync/migration.rb
|
85
|
+
- lib/column_sync/model.rb
|
85
86
|
- lib/column_sync/service.rb
|
86
87
|
- lib/column_sync/version.rb
|
87
88
|
- sig/column_sync.rbs
|