lib/dynamoid/persistence/save.rb in dynamoid-3.8.0 vs lib/dynamoid/persistence/save.rb in dynamoid-3.9.0
- old
+ new
@@ -2,29 +2,49 @@
module Dynamoid
module Persistence
# @private
class Save
- def self.call(model)
- new(model).call
+ def self.call(model, **options)
+ new(model, **options).call
end
- def initialize(model)
+ def initialize(model, touch: nil)
@model = model
+ @touch = touch # touch=false means explicit disabling of updating the `updated_at` attribute
end
def call
@model.hash_key = SecureRandom.uuid if @model.hash_key.blank?
+ return true unless @model.changed?
+
+ @model.created_at ||= DateTime.now.in_time_zone(Time.zone) if @model.class.timestamps_enabled?
+
+ if @model.class.timestamps_enabled? && !@model.updated_at_changed? && !(@touch == false && @model.persisted?)
+ @model.updated_at = DateTime.now.in_time_zone(Time.zone)
+ end
+
# 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)
+ if @model.new_record?
+ attributes_dumped = Dumping.dump_attributes(@model.attributes, @model.class.attributes)
+ Dynamoid.adapter.write(@model.class.table_name, attributes_dumped, conditions_for_write)
+ else
+ attributes_to_persist = @model.attributes.slice(*@model.changed.map(&:to_sym))
+ Dynamoid.adapter.update_item(@model.class.table_name, @model.hash_key, options_to_update_item) do |t|
+ attributes_to_persist.each do |name, value|
+ value_dumped = Dumping.dump_field(value, @model.class.attributes[name])
+ t.set(name => value_dumped)
+ end
+ end
+ end
+
@model.new_record = false
true
rescue Dynamoid::Errors::ConditionalCheckFailedException => e
if @model.new_record?
raise Dynamoid::Errors::RecordNotUnique.new(e, @model)
@@ -56,9 +76,36 @@
conditions[:if][:lock_version] = @model.changes[:lock_version][0]
end
end
conditions
+ end
+
+ def options_to_update_item
+ options = {}
+
+ if @model.class.range_key
+ value_dumped = Dumping.dump_field(@model.range_value, @model.class.attributes[@model.class.range_key])
+ options[:range_key] = value_dumped
+ end
+
+ conditions = {}
+ conditions[:if_exists] ||= {}
+ conditions[:if_exists][@model.class.hash_key] = @model.hash_key
+
+ # 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
+
+ options[:conditions] = conditions
+
+ options
end
end
end
end