shiftable 0.5.0 → 0.7.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/CHANGELOG.md +33 -1
- data/README.md +76 -14
- data/lib/shiftable/collection.rb +9 -4
- data/lib/shiftable/mod_signature.rb +22 -12
- data/lib/shiftable/shifting.rb +31 -2
- data/lib/shiftable/shifting_polymorphic_relation.rb +4 -2
- data/lib/shiftable/shifting_record.rb +24 -2
- data/lib/shiftable/shifting_relation.rb +4 -2
- data/lib/shiftable/single.rb +6 -5
- data/lib/shiftable/version.rb +1 -1
- metadata +30 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 5307ad9f6d83499df06dcd5b57745dfeed1522f5701708018c61e5b3a3b6bfba
         | 
| 4 | 
            +
              data.tar.gz: 5452233e37e38c732340e1f7f825da3c020799b2600b5b692087af44969c2c73
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: d7ed429d81143625afb5717143a877b8de5da2729be8519ed87246353051aa26a8f94f9d33765a9b158b7fc6fa21ed35c2017cadf84e26b669c399d61992f627
         | 
| 7 | 
            +
              data.tar.gz: ba888b498d8da4a6070f29346426b0ea05a23f959ff208400b5c1067394d5d7301850f99dce3cf0a90b712fd57b6dc397d5b871f7d81723901fd0b60d270329f
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -12,6 +12,26 @@ | |
| 12 12 | 
             
            ### Removed
         | 
| 13 13 |  | 
| 14 14 |  | 
| 15 | 
            +
            ## [0.7.0] - 2021-11-15
         | 
| 16 | 
            +
            ### Changed
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            - Make the `Shifting` Relation available to the `each` wrapper, as a block parameter
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            ## [0.6.1] - 2021-11-14
         | 
| 21 | 
            +
            ### Added
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            - Support for using save with bang (`save!`) to raise error when ActiveRecord save fails.
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            ## [0.6.0] - 2021-11-12
         | 
| 26 | 
            +
            ### Added
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            - Support for wrappers/hooks around each record shift, and around the entire set (see examples in specs or README)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            ## [0.5.1] - 2021-11-12
         | 
| 31 | 
            +
            ### Fixed
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            - Documentation typos in README
         | 
| 34 | 
            +
             | 
| 15 35 | 
             
            ## [0.5.0] - 2021-11-12
         | 
| 16 36 | 
             
            ### Added
         | 
| 17 37 |  | 
| @@ -76,4 +96,16 @@ | |
| 76 96 |  | 
| 77 97 | 
             
            [0.3.0]: https://github.com/pboling/shiftable/releases/tag/v0.3.0
         | 
| 78 98 |  | 
| 79 | 
            -
            [0.4.0]: https://github.com/pboling/shiftable/releases/tag/v0.4.0
         | 
| 99 | 
            +
            [0.4.0]: https://github.com/pboling/shiftable/releases/tag/v0.4.0
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            [0.4.1]: https://github.com/pboling/shiftable/releases/tag/v0.4.1
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            [0.5.0]: https://github.com/pboling/shiftable/releases/tag/v0.5.0
         | 
| 104 | 
            +
             | 
| 105 | 
            +
            [0.5.1]: https://github.com/pboling/shiftable/releases/tag/v0.5.1
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            [0.6.0]: https://github.com/pboling/shiftable/releases/tag/v0.6.0
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            [0.6.1]: https://github.com/pboling/shiftable/releases/tag/v0.6.1
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            [0.7.0]: https://github.com/pboling/shiftable/releases/tag/v0.7.0
         | 
    
        data/README.md
    CHANGED
    
    | @@ -80,7 +80,7 @@ But how can you accomplish this? If you used the `shiftable` gem, won't take but | |
| 80 80 | 
             
            class Spaceship < ActiveRecord::Base
         | 
| 81 81 | 
             
              belongs_to :captain
         | 
| 82 82 | 
             
              extend Shiftable::Single.new belongs_to: :captain, has_one: :spaceship, precheck: true,
         | 
| 83 | 
            -
                                           before_shift: ->( | 
| 83 | 
            +
                                           before_shift: ->(shifting_rel) { shifting_rel.result.ownership_changes += 1 }
         | 
| 84 84 | 
             
            end
         | 
| 85 85 | 
             
            ```
         | 
| 86 86 |  | 
| @@ -111,11 +111,10 @@ federation!  And in a run-in with their arch-Nemesis the Plinth-inth, | |
| 111 111 | 
             
            all federation spaceships are commandeered!  You are ruined!
         | 
| 112 112 |  | 
| 113 113 | 
             
            ```ruby
         | 
| 114 | 
            -
             | 
| 115 114 | 
             
            class Spaceship < ActiveRecord::Base
         | 
| 116 115 | 
             
              belongs_to :space_federation
         | 
| 117 116 | 
             
              extend Shiftable::Collection.new belongs_to: :space_federation, has_many: :spaceships,
         | 
| 118 | 
            -
                                               before_shift: lambda { |shifting_rel | 
| 117 | 
            +
                                               before_shift: lambda { |shifting_rel|
         | 
| 119 118 | 
             
                                                 shifting_rel.each { |spaceship| spaceship.federation_changes += 1 }
         | 
| 120 119 | 
             
                                               }
         | 
| 121 120 | 
             
            end
         | 
| @@ -153,9 +152,9 @@ class SpaceTreatySignature < ActiveRecord::Base | |
| 153 152 | 
             
              #   )
         | 
| 154 153 | 
             
              extend Shiftable::Collection.new(
         | 
| 155 154 | 
             
                belongs_to: :signatory, has_many: :space_treaty_signature,
         | 
| 156 | 
            -
                 | 
| 155 | 
            +
                polymorphic: { type: "SpaceFederation", as: :signatory },
         | 
| 157 156 | 
             
                method_prefix: "space_federation_",
         | 
| 158 | 
            -
                before_shift: lambda { |shifting_rel | 
| 157 | 
            +
                before_shift: lambda { |shifting_rel|
         | 
| 159 158 | 
             
                  # Each item in shifting_rel is an instance of the class where Shiftable::Collection is defined,
         | 
| 160 159 | 
             
                  #   in this case: SpaceTreatySignature
         | 
| 161 160 | 
             
                  # And each of them has a signatory which is of type "SpaceFederation",
         | 
| @@ -171,7 +170,7 @@ class SpaceFederation < ActiveRecord::Base | |
| 171 170 | 
             
              has_many :treaty_planets, class_name: "Planet", through: :space_treaty_signatures, as: :signatory
         | 
| 172 171 | 
             
              has_many :treaty_stations, class_name: "SpaceStation", through: :space_treaty_signatures, as: :signatory
         | 
| 173 172 | 
             
              def assimilate_from(other_federation)
         | 
| 174 | 
            -
                SpaceTreatySignature. | 
| 173 | 
            +
                SpaceTreatySignature.space_federation_shift_pcx(shift_to: self, shift_from: other_federation)
         | 
| 175 174 | 
             
              end
         | 
| 176 175 | 
             
            end
         | 
| 177 176 |  | 
| @@ -189,7 +188,51 @@ class SpaceStation < ActiveRecord::Base | |
| 189 188 | 
             
              has_many :treaty_federations, class_name: "SpaceFederation", through: :space_treaty_signatures, as: :signatory
         | 
| 190 189 | 
             
              has_many :treaty_planets, class_name: "Planet", through: :space_treaty_signatures, as: :signatory
         | 
| 191 190 | 
             
            end
         | 
| 192 | 
            -
             | 
| 191 | 
            +
            ```
         | 
| 192 | 
            +
             | 
| 193 | 
            +
            ### Wrapping a shift
         | 
| 194 | 
            +
             | 
| 195 | 
            +
            For example, in a transaction.  Let's update the nemesis foundation example from above with a transaction shift_each_wrapper,
         | 
| 196 | 
            +
            which we'll pull from the [`activerecord-transactionable`](https://github.com/pboling/activerecord-transactionable) gem, which provides best practice framing around transactions.
         | 
| 197 | 
            +
             | 
| 198 | 
            +
            ```ruby
         | 
| 199 | 
            +
            class Spaceship < ActiveRecord::Base
         | 
| 200 | 
            +
              belongs_to :space_federation
         | 
| 201 | 
            +
              extend Shiftable::Collection.new(
         | 
| 202 | 
            +
                belongs_to: :space_federation,
         | 
| 203 | 
            +
                has_many: :spaceships,
         | 
| 204 | 
            +
                before_shift: lambda { |shifting_rel|
         | 
| 205 | 
            +
                                shifting_rel.each { |spaceship| spaceship.federation_changes += 1 }
         | 
| 206 | 
            +
                              },
         | 
| 207 | 
            +
                wrapper: {
         | 
| 208 | 
            +
                  each: lambda { |rel, record, &block|
         | 
| 209 | 
            +
                          tresult = record.transaction_wrapper(outside_rescued_errors: ActiveRecord::RecordNotUnique) do
         | 
| 210 | 
            +
                            puts "melon #{record.name} honey #{rel.count}"
         | 
| 211 | 
            +
                            block.call # does the actual saving!
         | 
| 212 | 
            +
                          end
         | 
| 213 | 
            +
                          # NOTE: The value returned by the wrapper will also be returned by the call to `shift_cx`.
         | 
| 214 | 
            +
                          #       You could return the whole tresult object here, instead of just true/false!
         | 
| 215 | 
            +
                          tresult.success?
         | 
| 216 | 
            +
                        },
         | 
| 217 | 
            +
                  all: lambda { |rel, &block|
         | 
| 218 | 
            +
                         tresult = Spaceship.transaction_wrapper do
         | 
| 219 | 
            +
                           puts "can you eat #{rel.count} shoes"
         | 
| 220 | 
            +
                           block.call
         | 
| 221 | 
            +
                         end
         | 
| 222 | 
            +
                         tresult.success?
         | 
| 223 | 
            +
                       }
         | 
| 224 | 
            +
                }
         | 
| 225 | 
            +
              )
         | 
| 226 | 
            +
            end
         | 
| 227 | 
            +
             | 
| 228 | 
            +
            class SpaceFederation < ActiveRecord::Base
         | 
| 229 | 
            +
              has_many :spaceships
         | 
| 230 | 
            +
             | 
| 231 | 
            +
              def all_spaceships_commandeered_by(nemesis_federation)
         | 
| 232 | 
            +
                Spaceship.shift_cx(shift_to: nemesis_federation, shift_from: self)
         | 
| 233 | 
            +
              end
         | 
| 234 | 
            +
            end
         | 
| 235 | 
            +
            ```
         | 
| 193 236 |  | 
| 194 237 | 
             
            ### Complete example
         | 
| 195 238 |  | 
| @@ -207,13 +250,32 @@ end | |
| 207 250 | 
             
            class Spaceship < ActiveRecord::Base
         | 
| 208 251 | 
             
              belongs_to :captain
         | 
| 209 252 | 
             
              extend Shiftable::Single.new belongs_to: :captain, has_one: :spaceship, precheck: true,
         | 
| 210 | 
            -
                                           before_shift: ->( | 
| 253 | 
            +
                                           before_shift: ->(shifting_rel) { shifting_rel.result.ownership_changes += 1 }
         | 
| 211 254 |  | 
| 212 255 | 
             
              belongs_to :space_federation
         | 
| 213 | 
            -
              extend Shiftable::Collection.new | 
| 214 | 
            -
             | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 256 | 
            +
              extend Shiftable::Collection.new(
         | 
| 257 | 
            +
                belongs_to: :space_federation,
         | 
| 258 | 
            +
                has_many: :spaceships,
         | 
| 259 | 
            +
                before_shift: lambda { |shifting_rel|
         | 
| 260 | 
            +
                  shifting_rel.each { |spaceship| spaceship.federation_changes += 1 }
         | 
| 261 | 
            +
                },
         | 
| 262 | 
            +
                wrapper: {
         | 
| 263 | 
            +
                  each: lambda { |rel, record, &block|
         | 
| 264 | 
            +
                          tresult = record.transaction_wrapper(outside_rescued_errors: ActiveRecord::RecordNotUnique) do
         | 
| 265 | 
            +
                            puts "melon #{record.name} honey #{rel.count}"
         | 
| 266 | 
            +
                            block.call # does the actual saving!
         | 
| 267 | 
            +
                          end
         | 
| 268 | 
            +
                          tresult.success?
         | 
| 269 | 
            +
                        },
         | 
| 270 | 
            +
                  all: lambda { |rel, &block|
         | 
| 271 | 
            +
                         tresult = Spaceship.transaction_wrapper do
         | 
| 272 | 
            +
                           puts "can you eat #{rel.count} shoes"
         | 
| 273 | 
            +
                           block.call
         | 
| 274 | 
            +
                         end
         | 
| 275 | 
            +
                         tresult.success?
         | 
| 276 | 
            +
                       }
         | 
| 277 | 
            +
                }
         | 
| 278 | 
            +
              )
         | 
| 217 279 | 
             
            end
         | 
| 218 280 |  | 
| 219 281 | 
             
            class SpaceFederation < ActiveRecord::Base
         | 
| @@ -241,7 +303,7 @@ class SpaceTreatySignature < ActiveRecord::Base | |
| 241 303 | 
             
              belongs_to :signatory, polymorphic: true
         | 
| 242 304 | 
             
              extend Shiftable::Collection.new(
         | 
| 243 305 | 
             
                belongs_to: :signatory, has_many: :space_treaty_signatures,
         | 
| 244 | 
            -
                 | 
| 306 | 
            +
                polymorphic: { type: "SpaceFederation", as: :signatory },
         | 
| 245 307 | 
             
                method_prefix: "space_federation_"
         | 
| 246 308 | 
             
              )
         | 
| 247 309 | 
             
            end
         | 
| @@ -311,7 +373,7 @@ the [Pessimistic Version Constraint][pvc] with two digits of precision. | |
| 311 373 | 
             
            For example:
         | 
| 312 374 |  | 
| 313 375 | 
             
            ```ruby
         | 
| 314 | 
            -
            spec.add_dependency "shiftable", "~> 0. | 
| 376 | 
            +
            spec.add_dependency "shiftable", "~> 0.7"
         | 
| 315 377 | 
             
            ```
         | 
| 316 378 |  | 
| 317 379 | 
             
            ## Contact
         | 
    
        data/lib/shiftable/collection.rb
    CHANGED
    
    | @@ -16,7 +16,7 @@ module Shiftable | |
| 16 16 | 
             
              class Collection < Module
         | 
| 17 17 | 
             
                # associations: belongs_to, has_many
         | 
| 18 18 | 
             
                # options: method_prefix, before_shift
         | 
| 19 | 
            -
                def initialize(belongs_to:, has_many:, polymorphic: nil, method_prefix: nil, before_shift: nil)
         | 
| 19 | 
            +
                def initialize(belongs_to:, has_many:, polymorphic: nil, method_prefix: nil, before_shift: nil, wrapper: nil)
         | 
| 20 20 | 
             
                  # Ruby's Module initializer doesn't take any arguments
         | 
| 21 21 | 
             
                  super()
         | 
| 22 22 |  | 
| @@ -39,7 +39,12 @@ module Shiftable | |
| 39 39 | 
             
                      method_prefix: method_prefix,
         | 
| 40 40 | 
             
                      # will prevent the save if it returns false
         | 
| 41 41 | 
             
                      # allows for any custom logic to be run, such as setting attributes, prior to the shift (save).
         | 
| 42 | 
            -
                      before_shift: before_shift
         | 
| 42 | 
            +
                      before_shift: before_shift,
         | 
| 43 | 
            +
                      # wrapper: {
         | 
| 44 | 
            +
                      #   all: ->() { klass.transaction_wrapper { yield } },
         | 
| 45 | 
            +
                      #   each: ->() { klass.transaction_wrapper { yield } },
         | 
| 46 | 
            +
                      # }
         | 
| 47 | 
            +
                      wrapper: wrapper
         | 
| 43 48 | 
             
                    },
         | 
| 44 49 | 
             
                    type: polymorphic ? :pcx : :cx
         | 
| 45 50 | 
             
                  )
         | 
| @@ -68,8 +73,8 @@ module Shiftable | |
| 68 73 | 
             
                      define_method(:"#{prefix}shift_#{type}_column") do
         | 
| 69 74 | 
             
                        signature.send("shift_#{type}_column")
         | 
| 70 75 | 
             
                      end
         | 
| 71 | 
            -
                      define_method(:"#{prefix}shift_#{type}") do |shift_to:, shift_from | 
| 72 | 
            -
                        signature.shift_data!(shift_to: shift_to, shift_from: shift_from)
         | 
| 76 | 
            +
                      define_method(:"#{prefix}shift_#{type}") do |shift_to:, shift_from:, bang: false|
         | 
| 77 | 
            +
                        signature.shift_data!(shift_to: shift_to, shift_from: shift_from, bang: bang)
         | 
| 73 78 | 
             
                      end
         | 
| 74 79 | 
             
                    end
         | 
| 75 80 | 
             
                  end
         | 
| @@ -24,6 +24,10 @@ module Shiftable | |
| 24 24 | 
             
                  raise ArgumentError, "exactly two distinct associations must be provided" if invalid_number_of_associations?
         | 
| 25 25 | 
             
                end
         | 
| 26 26 |  | 
| 27 | 
            +
                def wrapper
         | 
| 28 | 
            +
                  options[:wrapper] || {}
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 27 31 | 
             
                def polymorphic_type
         | 
| 28 32 | 
             
                  options.dig(:polymorphic, :type)
         | 
| 29 33 | 
             
                end
         | 
| @@ -71,16 +75,18 @@ module Shiftable | |
| 71 75 | 
             
                    associations[:has_many]
         | 
| 72 76 | 
             
                  end
         | 
| 73 77 |  | 
| 74 | 
            -
                  def shift_data!(shift_to:, shift_from:)
         | 
| 78 | 
            +
                  def shift_data!(shift_to:, shift_from:, bang: false)
         | 
| 75 79 | 
             
                    validate_relationships
         | 
| 76 80 | 
             
                    shifting_rel = ShiftingRelation.new(
         | 
| 77 81 | 
             
                      to: shift_to,
         | 
| 78 82 | 
             
                      from: shift_from,
         | 
| 79 83 | 
             
                      column: shift_column,
         | 
| 80 | 
            -
                      base: base
         | 
| 84 | 
            +
                      base: base,
         | 
| 85 | 
            +
                      wrapper: wrapper,
         | 
| 86 | 
            +
                      bang: bang
         | 
| 81 87 | 
             
                    )
         | 
| 82 | 
            -
                    shifting_rel.shift do | 
| 83 | 
            -
                      before_shift&.call(shifting_rel | 
| 88 | 
            +
                    shifting_rel.shift do
         | 
| 89 | 
            +
                      before_shift&.call(shifting_rel)
         | 
| 84 90 | 
             
                    end
         | 
| 85 91 | 
             
                  end
         | 
| 86 92 | 
             
                end
         | 
| @@ -91,7 +97,7 @@ module Shiftable | |
| 91 97 | 
             
                  #   associations[:has_many]
         | 
| 92 98 | 
             
                  # end
         | 
| 93 99 |  | 
| 94 | 
            -
                  def shift_data!(shift_to:, shift_from:)
         | 
| 100 | 
            +
                  def shift_data!(shift_to:, shift_from:, bang: false)
         | 
| 95 101 | 
             
                    validate_relationships
         | 
| 96 102 | 
             
                    shifting_rel = ShiftingPolymorphicRelation.new(
         | 
| 97 103 | 
             
                      to: shift_to,
         | 
| @@ -101,10 +107,12 @@ module Shiftable | |
| 101 107 | 
             
                        as: polymorphic_as,
         | 
| 102 108 | 
             
                        id_column: shift_pcx_column
         | 
| 103 109 | 
             
                      },
         | 
| 104 | 
            -
                      base: base
         | 
| 110 | 
            +
                      base: base,
         | 
| 111 | 
            +
                      wrapper: wrapper,
         | 
| 112 | 
            +
                      bang: bang
         | 
| 105 113 | 
             
                    )
         | 
| 106 | 
            -
                    shifting_rel.shift do | 
| 107 | 
            -
                      before_shift&.call(shifting_rel | 
| 114 | 
            +
                    shifting_rel.shift do
         | 
| 115 | 
            +
                      before_shift&.call(shifting_rel)
         | 
| 108 116 | 
             
                    end
         | 
| 109 117 | 
             
                  end
         | 
| 110 118 | 
             
                end
         | 
| @@ -119,18 +127,20 @@ module Shiftable | |
| 119 127 | 
             
                    options[:precheck]
         | 
| 120 128 | 
             
                  end
         | 
| 121 129 |  | 
| 122 | 
            -
                  def shift_data!(shift_to:, shift_from:)
         | 
| 130 | 
            +
                  def shift_data!(shift_to:, shift_from:, bang: false)
         | 
| 123 131 | 
             
                    validate_relationships
         | 
| 124 132 | 
             
                    shifting = ShiftingRecord.new(
         | 
| 125 133 | 
             
                      to: shift_to,
         | 
| 126 134 | 
             
                      from: shift_from,
         | 
| 127 135 | 
             
                      column: shift_column,
         | 
| 128 | 
            -
                      base: base
         | 
| 136 | 
            +
                      base: base,
         | 
| 137 | 
            +
                      wrapper: wrapper,
         | 
| 138 | 
            +
                      bang: bang
         | 
| 129 139 | 
             
                    ) do
         | 
| 130 140 | 
             
                      !precheck || !shift_to.send(has_rel)
         | 
| 131 141 | 
             
                    end
         | 
| 132 | 
            -
                    shifting.shift do | 
| 133 | 
            -
                      before_shift&.call(shifting | 
| 142 | 
            +
                    shifting.shift do
         | 
| 143 | 
            +
                      before_shift&.call(shifting)
         | 
| 134 144 | 
             
                    end
         | 
| 135 145 | 
             
                  end
         | 
| 136 146 | 
             
                end
         | 
    
        data/lib/shiftable/shifting.rb
    CHANGED
    
    | @@ -3,9 +3,13 @@ | |
| 3 3 | 
             
            module Shiftable
         | 
| 4 4 | 
             
              # Gets data to be shifted
         | 
| 5 5 | 
             
              class Shifting
         | 
| 6 | 
            -
                 | 
| 6 | 
            +
                # Public API
         | 
| 7 | 
            +
                attr_accessor :result, :bang, :shift_all_wrapper, :shift_each_wrapper
         | 
| 8 | 
            +
                attr_reader :to, :from
         | 
| 9 | 
            +
                # Internal API
         | 
| 10 | 
            +
                attr_reader :column, :base, :run_save
         | 
| 7 11 |  | 
| 8 | 
            -
                def initialize(to:, from:, column:, base:)
         | 
| 12 | 
            +
                def initialize(to:, from:, column:, base:, wrapper:, bang:)
         | 
| 9 13 | 
             
                  @to = to
         | 
| 10 14 | 
             
                  @from = from
         | 
| 11 15 | 
             
                  @column = column
         | 
| @@ -14,6 +18,9 @@ module Shiftable | |
| 14 18 | 
             
                  do_query = block_given? ? yield : true
         | 
| 15 19 | 
             
                  @result = do_query ? query : nil
         | 
| 16 20 | 
             
                  @run_save = true
         | 
| 21 | 
            +
                  @shift_all_wrapper = wrapper[:all]
         | 
| 22 | 
            +
                  @shift_each_wrapper = wrapper[:each]
         | 
| 23 | 
            +
                  @bang = bang
         | 
| 17 24 | 
             
                end
         | 
| 18 25 |  | 
| 19 26 | 
             
                # def found?
         | 
| @@ -31,6 +38,28 @@ module Shiftable | |
| 31 38 | 
             
                  raise ArgumentError, "shift_from must have an id (primary key) value, but is: #{from&.id}" unless from&.id
         | 
| 32 39 | 
             
                end
         | 
| 33 40 |  | 
| 41 | 
            +
                def run_save!
         | 
| 42 | 
            +
                  if shift_all_wrapper
         | 
| 43 | 
            +
                    shift_all_wrapper.call(self) do
         | 
| 44 | 
            +
                      do_saves
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  else
         | 
| 47 | 
            +
                    do_saves
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def do_saves
         | 
| 52 | 
            +
                  if shift_each_wrapper
         | 
| 53 | 
            +
                    each do |rec|
         | 
| 54 | 
            +
                      shift_each_wrapper.call(self, rec) do
         | 
| 55 | 
            +
                        bang ? rec.save! : rec.save
         | 
| 56 | 
            +
                      end
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                  else
         | 
| 59 | 
            +
                    bang ? each(&:save!) : each(&:save)
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 34 63 | 
             
                # def query
         | 
| 35 64 | 
             
                #   raise "query must be defined in a subclass"
         | 
| 36 65 | 
             
                # end
         | 
| @@ -28,8 +28,10 @@ module Shiftable | |
| 28 28 | 
             
                  each do |record|
         | 
| 29 29 | 
             
                    record.send("#{polymorphic_id_column}=", to.id)
         | 
| 30 30 | 
             
                  end
         | 
| 31 | 
            -
                  @run_save = yield  | 
| 32 | 
            -
                   | 
| 31 | 
            +
                  @run_save = yield if block_given?
         | 
| 32 | 
            +
                  return result unless run_save
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  run_save!
         | 
| 33 35 | 
             
                  result
         | 
| 34 36 | 
             
                end
         | 
| 35 37 |  | 
| @@ -12,12 +12,34 @@ module Shiftable | |
| 12 12 | 
             
                  return false unless found?
         | 
| 13 13 |  | 
| 14 14 | 
             
                  result.send("#{column}=", to.id)
         | 
| 15 | 
            -
                  @run_save = yield  | 
| 16 | 
            -
                   | 
| 15 | 
            +
                  @run_save = yield if block_given?
         | 
| 16 | 
            +
                  return nil unless run_save
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  run_save!
         | 
| 17 19 | 
             
                end
         | 
| 18 20 |  | 
| 19 21 | 
             
                private
         | 
| 20 22 |  | 
| 23 | 
            +
                def run_save!
         | 
| 24 | 
            +
                  if shift_all_wrapper
         | 
| 25 | 
            +
                    shift_all_wrapper.call(self) do
         | 
| 26 | 
            +
                      do_save
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  else
         | 
| 29 | 
            +
                    do_save
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def do_save
         | 
| 34 | 
            +
                  if shift_each_wrapper
         | 
| 35 | 
            +
                    shift_each_wrapper.call(self, result) do
         | 
| 36 | 
            +
                      bang ? result.save! : result.save
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  else
         | 
| 39 | 
            +
                    bang ? result.save! : result.save
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 21 43 | 
             
                def query
         | 
| 22 44 | 
             
                  base.find_by(column => from.id)
         | 
| 23 45 | 
             
                end
         | 
| @@ -20,8 +20,10 @@ module Shiftable | |
| 20 20 | 
             
                  each do |record|
         | 
| 21 21 | 
             
                    record.send("#{column}=", to.id)
         | 
| 22 22 | 
             
                  end
         | 
| 23 | 
            -
                  @run_save = yield  | 
| 24 | 
            -
                   | 
| 23 | 
            +
                  @run_save = yield if block_given?
         | 
| 24 | 
            +
                  return result unless run_save
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  run_save!
         | 
| 25 27 | 
             
                  result
         | 
| 26 28 | 
             
                end
         | 
| 27 29 |  | 
    
        data/lib/shiftable/single.rb
    CHANGED
    
    | @@ -14,14 +14,14 @@ | |
| 14 14 | 
             
            #             belongs_to: :captain,
         | 
| 15 15 | 
             
            #             has_one: :spaceship,
         | 
| 16 16 | 
             
            #             precheck: true,
         | 
| 17 | 
            -
            #             before_shift: ->( | 
| 17 | 
            +
            #             before_shift: ->(shifting_rel) { shifting_rel.result..ownership_changes += 1 }
         | 
| 18 18 | 
             
            #           )
         | 
| 19 19 | 
             
            #   end
         | 
| 20 20 | 
             
            #
         | 
| 21 21 | 
             
            module Shiftable
         | 
| 22 22 | 
             
              # Inheriting from Module is a powerful pattern. If you like it checkout the debug_logging gem!
         | 
| 23 23 | 
             
              class Single < Module
         | 
| 24 | 
            -
                def initialize(belongs_to:, has_one:, method_prefix: nil, precheck: true, before_shift: nil)
         | 
| 24 | 
            +
                def initialize(belongs_to:, has_one:, method_prefix: nil, precheck: true, before_shift: nil, wrapper: nil)
         | 
| 25 25 | 
             
                  # Ruby's Module initializer doesn't take any arguments
         | 
| 26 26 | 
             
                  super()
         | 
| 27 27 |  | 
| @@ -44,7 +44,8 @@ module Shiftable | |
| 44 44 | 
             
                      method_prefix: method_prefix,
         | 
| 45 45 | 
             
                      # will prevent the save if it returns false
         | 
| 46 46 | 
             
                      # allows for any custom logic to be run, such as setting attributes, prior to the shift (save).
         | 
| 47 | 
            -
                      before_shift: before_shift
         | 
| 47 | 
            +
                      before_shift: before_shift,
         | 
| 48 | 
            +
                      wrapper: wrapper
         | 
| 48 49 | 
             
                    },
         | 
| 49 50 | 
             
                    type: :sg
         | 
| 50 51 | 
             
                  )
         | 
| @@ -72,8 +73,8 @@ module Shiftable | |
| 72 73 | 
             
                      define_method(:"#{prefix}shift_column") do
         | 
| 73 74 | 
             
                        signature.send("shift_#{signature.type}_column")
         | 
| 74 75 | 
             
                      end
         | 
| 75 | 
            -
                      define_method(:"#{prefix}shift_single") do |shift_to:, shift_from | 
| 76 | 
            -
                        signature.shift_data!(shift_to: shift_to, shift_from: shift_from)
         | 
| 76 | 
            +
                      define_method(:"#{prefix}shift_single") do |shift_to:, shift_from:, bang: false|
         | 
| 77 | 
            +
                        signature.shift_data!(shift_to: shift_to, shift_from: shift_from, bang: bang)
         | 
| 77 78 | 
             
                      end
         | 
| 78 79 | 
             
                    end
         | 
| 79 80 | 
             
                  end
         | 
    
        data/lib/shiftable/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: shiftable
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.7.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Peter Boling
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021-11- | 
| 11 | 
            +
            date: 2021-11-15 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activerecord
         | 
| @@ -24,6 +24,20 @@ dependencies: | |
| 24 24 | 
             
                - - ">="
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 26 | 
             
                    version: '5'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: activerecord-transactionable
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - ">="
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '3'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - ">="
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '3'
         | 
| 27 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 42 | 
             
              name: byebug
         | 
| 29 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -136,6 +150,20 @@ dependencies: | |
| 136 150 | 
             
                - - "~>"
         | 
| 137 151 | 
             
                  - !ruby/object:Gem::Version
         | 
| 138 152 | 
             
                    version: '1.0'
         | 
| 153 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 154 | 
            +
              name: silent_stream
         | 
| 155 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 156 | 
            +
                requirements:
         | 
| 157 | 
            +
                - - "~>"
         | 
| 158 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 159 | 
            +
                    version: '1'
         | 
| 160 | 
            +
              type: :development
         | 
| 161 | 
            +
              prerelease: false
         | 
| 162 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 163 | 
            +
                requirements:
         | 
| 164 | 
            +
                - - "~>"
         | 
| 165 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 166 | 
            +
                    version: '1'
         | 
| 139 167 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 140 168 | 
             
              name: sqlite3
         | 
| 141 169 | 
             
              requirement: !ruby/object:Gem::Requirement
         |