Sha256: 2fa2d5b8fd06c67c0d0755fd859e5110eb8b4e1166ff10a6d083e1b51e3a4ee5

Contents?: true

Size: 1.89 KB

Versions: 4

Compression:

Stored size: 1.89 KB

Contents

# frozen_string_literal: true

module Dynamoid
  module Persistence
    # @private
    class Save
      def self.call(model)
        new(model).call
      end

      def initialize(model)
        @model = model
      end

      def call
        @model.hash_key = SecureRandom.uuid if @model.hash_key.blank?

        # Add an optimistic locking check if the lock_version column exists
        if @model.class.attributes[:lock_version]
          @model.lock_version = (@model.lock_version || 0) + 1
        end

        attributes_dumped = Dumping.dump_attributes(@model.attributes, @model.class.attributes)
        Dynamoid.adapter.write(@model.class.table_name, attributes_dumped, conditions_for_write)

        @model.new_record = false
        true
      rescue Dynamoid::Errors::ConditionalCheckFailedException => e
        if @model.new_record?
          raise Dynamoid::Errors::RecordNotUnique.new(e, @model)
        else
          raise Dynamoid::Errors::StaleObjectError.new(@model, 'persist')
        end
      end

      private

      # Should be called after incrementing `lock_version` attribute
      def conditions_for_write
        conditions = {}

        # Add an 'exists' check to prevent overwriting existing records with new ones
        if @model.new_record?
          conditions[:unless_exists] = [@model.class.hash_key]
          if @model.range_key
            conditions[:unless_exists] << @model.range_key
          end
        end

        # Add an optimistic locking check if the lock_version column exists
        if @model.class.attributes[:lock_version]
          # Uses the original lock_version value from Dirty API
          # in case user changed 'lock_version' manually
          if @model.changes[:lock_version][0]
            conditions[:if] ||= {}
            conditions[:if][:lock_version] = @model.changes[:lock_version][0]
          end
        end

        conditions
      end
    end
  end
end

Version data entries

4 entries across 4 versions & 1 rubygems

Version Path
dynamoid-3.8.0 lib/dynamoid/persistence/save.rb
dynamoid-3.7.1 lib/dynamoid/persistence/save.rb
dynamoid-3.7.0 lib/dynamoid/persistence/save.rb
dynamoid-3.6.0 lib/dynamoid/persistence/save.rb