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
         |