module Dynamoid::Persistence
Persistence
is responsible for dumping objects to and marshalling objects from the datastore. It tries to reserialize values to be of the same type as when they were passed in, based on the fields in the class.
Attributes
Public Instance Methods
Delete this object from the datastore.
@since 0.2.0
# File lib/dynamoid/persistence.rb, line 228 def delete options = range_key ? {:range_key => dump_field(self.read_attribute(range_key), self.class.attributes[range_key])} : {} # Add an optimistic locking check if the lock_version column exists if(self.class.attributes[:lock_version]) conditions = {:if => {}} conditions[:if][:lock_version] = if changes[:lock_version].nil? self.lock_version else changes[:lock_version][0] end options[:conditions] = conditions end Dynamoid.adapter.delete(self.class.table_name, self.hash_key, options) rescue Dynamoid::Errors::ConditionalCheckFailedException raise Dynamoid::Errors::StaleObjectError.new(self, 'delete') end
Delete this object, but only after running callbacks for it.
@since 0.2.0
# File lib/dynamoid/persistence.rb, line 218 def destroy run_callbacks(:destroy) do self.delete end self end
Dump this object’s attributes into hash form, fit to be persisted into the datastore.
@since 0.2.0
# File lib/dynamoid/persistence.rb, line 250 def dump Hash.new.tap do |hash| self.class.attributes.each do |attribute, options| hash[attribute] = dump_field(self.read_attribute(attribute), options) end end end
Is this object persisted in the datastore? Required for some ActiveModel integration stuff.
@since 0.2.0
# File lib/dynamoid/persistence.rb, line 162 def persisted? !new_record? end
Run the callbacks and then persist this object in the datastore.
@since 0.2.0
# File lib/dynamoid/persistence.rb, line 169 def save(options = {}) self.class.create_table if new_record? conditions = { :unless_exists => [self.class.hash_key]} conditions[:unless_exists] << range_key if(range_key) run_callbacks(:create) { persist(conditions) } else persist end self end
Set updated_at and any passed in field to current DateTime. Useful for things like last_login_at, etc.
# File lib/dynamoid/persistence.rb, line 152 def touch(name = nil) now = DateTime.now self.updated_at = now attributes[name] = now if name save end
# File lib/dynamoid/persistence.rb, line 208 def update(conditions = {}, &block) update!(conditions, &block) true rescue Dynamoid::Errors::StaleObjectError false end
update!() will increment the lock_version if the table has the column, but will not check it. Thus, a concurrent save will never cause an update! to fail, but an update! may cause a concurrent save to fail.
# File lib/dynamoid/persistence.rb, line 189 def update!(conditions = {}, &block) run_callbacks(:update) do options = range_key ? {:range_key => dump_field(self.read_attribute(range_key), self.class.attributes[range_key])} : {} begin new_attrs = Dynamoid.adapter.update_item(self.class.table_name, self.hash_key, options.merge(:conditions => conditions)) do |t| if(self.class.attributes[:lock_version]) t.add(lock_version: 1) end yield t end load(new_attrs) rescue Dynamoid::Errors::ConditionalCheckFailedException raise Dynamoid::Errors::StaleObjectError.new(self, 'update') end end end
Private Instance Methods
Determine how to dump this field. Given a value, it’ll determine how to turn it into a value that can be persisted into the datastore.
@since 0.2.0
# File lib/dynamoid/persistence.rb, line 264 def dump_field(value, options) if (field_class = options[:type]).is_a?(Class) if value.respond_to?(:dynamoid_dump) value.dynamoid_dump elsif field_class.respond_to?(:dynamoid_dump) field_class.dynamoid_dump(value) else raise ArgumentError, "Neither #{field_class} nor #{value} support serialization for Dynamoid." end else case options[:type] when :string !value.nil? ? value.to_s : nil when :integer !value.nil? ? Integer(value) : nil when :number !value.nil? ? value : nil when :set !value.nil? ? Set.new(value) : nil when :array !value.nil? ? value : nil when :datetime !value.nil? ? value.to_time.to_f : nil when :serialized options[:serializer] ? options[:serializer].dump(value) : value.to_yaml when :boolean !value.nil? ? value.to_s[0] : nil else raise ArgumentError, "Unknown type #{options[:type]}" end end end
Persist the object into the datastore. Assign it an id first if it doesn’t have one.
@since 0.2.0
# File lib/dynamoid/persistence.rb, line 300 def persist(conditions = nil) run_callbacks(:save) do self.hash_key = SecureRandom.uuid if self.hash_key.nil? || self.hash_key.blank? # Add an exists check to prevent overwriting existing records with new ones if(new_record?) conditions ||= {} (conditions[:unless_exists] ||= []) << self.class.hash_key end # Add an optimistic locking check if the lock_version column exists if(self.class.attributes[:lock_version]) conditions ||= {} self.lock_version = (lock_version || 0) + 1 #Uses the original lock_version value from ActiveModel::Dirty in case user changed lock_version manually (conditions[:if] ||= {})[:lock_version] = changes[:lock_version][0] if(changes[:lock_version][0]) end begin Dynamoid.adapter.write(self.class.table_name, self.dump, conditions) @new_record = false true rescue Dynamoid::Errors::ConditionalCheckFailedException => e if new_record? raise Dynamoid::Errors::RecordNotUnique.new(e, self) else raise Dynamoid::Errors::StaleObjectError.new(self, 'persist') end end end end