module Aws::Record::ItemOperations
Public Class Methods
@api private
# File lib/aws-record/record/item_operations.rb, line 19 def self.included(sub_class) sub_class.extend(ItemOperationsClassMethods) end
Public Instance Methods
Assigns the attributes provided onto the model.
@example Usage Example
class MyModel include Aws::Record integer_attr :uuid, hash_key: true string_attr :name, range_key: true integer_attr :age float_attr :height end model = MyModel.new(id: 4, name: "John", age: 4, height: 70.5) model.age # => 4 model.height # => 70.5 model.save model.dirty? # => false model.assign_attributes(age: 5, height: 150.75) model.age # => 5 model.height # => 150.75 model.dirty? # => true
@param [Hash] opts
# File lib/aws-record/record/item_operations.rb, line 109 def assign_attributes(opts) opts.each do |field, new_value| field = field.to_sym setter = "#{field}=" raise ArgumentError.new "Invalid field: #{field} for model" unless respond_to?(setter) public_send(setter, new_value) end end
Deletes the item instance that matches the key values of this item instance in Amazon DynamoDB. Uses the {docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_item-instance_method Aws::DynamoDB::Client#delete_item} API.
# File lib/aws-record/record/item_operations.rb, line 190 def delete! dynamodb_client.delete_item( table_name: self.class.table_name, key: key_values ) self.instance_variable_get("@data").destroyed = true end
Saves this instance of an item to Amazon DynamoDB. If this item is “new” as defined by having new or altered key attributes, will attempt a conditional {docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#put_item-instance_method Aws::DynamoDB::Client#put_item} call, which will not overwrite an existing item. If the item only has altered non-key attributes, will perform an {docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method Aws::DynamoDB::Client#update_item} call. Uses this item instance's attributes in order to build the request on your behalf.
You can use the :force
option to perform a simple put/overwrite without conditional validation or update logic.
@param [Hash] opts @option opts [Boolean] :force if true, will save as a put operation and
overwrite any existing item on the remote end. Otherwise, and by default, will either perform a conditional put or an update call.
@return false if the record is invalid as defined by an attempt to call
+valid?+ on this item, if that method exists. Otherwise, returns client call return value.
# File lib/aws-record/record/item_operations.rb, line 76 def save(opts = {}) if _invalid_record?(opts) false else _perform_save(opts) end end
Saves this instance of an item to Amazon DynamoDB. If this item is “new” as defined by having new or altered key attributes, will attempt a conditional {docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#put_item-instance_method Aws::DynamoDB::Client#put_item} call, which will not overwrite an existing item. If the item only has altered non-key attributes, will perform an {docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method Aws::DynamoDB::Client#update_item} call. Uses this item instance's attributes in order to build the request on your behalf.
You can use the :force
option to perform a simple put/overwrite without conditional validation or update logic.
@param [Hash] opts @option opts [Boolean] :force if true, will save as a put operation and
overwrite any existing item on the remote end. Otherwise, and by default, will either perform a conditional put or an update call.
@raise [Aws::Record::Errors::KeyMissing] if a required key attribute
does not have a value within this item instance.
@raise [Aws::Record::Errors::ConditionalWriteFailed] if a conditional
put fails because the item exists on the remote end.
@raise [Aws::Record::Errors::ValidationError] if the item responds to
+:valid?+ and that call returned false. In such a case, checking root cause is dependent on the validation library you are using.
# File lib/aws-record/record/item_operations.rb, line 47 def save!(opts = {}) ret = save(opts) if ret ret else raise Errors::ValidationError.new("Validation hook returned false!") end end
Mass assigns the attributes to the model and then performs a save
You can use the :force
option to perform a simple put/overwrite without conditional validation or update logic.
Note that aws-record allows you to change your model's key values, but this will be interpreted as persisting a new item to your DynamoDB table
@example Usage Example
class MyModel include Aws::Record integer_attr :uuid, hash_key: true string_attr :name, range_key: true integer_attr :age float_attr :height end model = MyModel.new(id: 4, name: "John", age: 4, height: 70.5) model.age # => 4 model.height # => 70.5 model.save model.dirty? # => false model.update(age: 5, height: 150.75) model.age # => 5 model.height # => 150.75 model.dirty? # => false
@param [Hash] new_param, contains the new parameters for the model
@param [Hash] opts @option opts [Boolean] :force if true, will save as a put operation and
overwrite any existing item on the remote end. Otherwise, and by default, will either perform a conditional put or an update call.
@return false if the record is invalid as defined by an attempt to call
+valid?+ on this item, if that method exists. Otherwise, returns client call return value.
# File lib/aws-record/record/item_operations.rb, line 157 def update(new_params, opts = {}) assign_attributes(new_params) save(opts) end
Updates model attributes and validates new values
You can use the :force
option to perform a simple put/overwrite without conditional validation or update logic.
Note that aws-record allows you to change your model's key values, but this will be interpreted as persisting a new item to your DynamoDB table
@param [Hash] new_param, contains the new parameters for the model
@param [Hash] opts @option opts [Boolean] :force if true, will save as a put operation and
overwrite any existing item on the remote end. Otherwise, and by default, will either perform a conditional put or an update call.
@return The update mode if the update is successful
@raise [Aws::Record::Errors::ValidationError] if any new values
violate the models validations.
# File lib/aws-record/record/item_operations.rb, line 181 def update!(new_params, opts = {}) assign_attributes(new_params) save!(opts) end
Private Instance Methods
# File lib/aws-record/record/item_operations.rb, line 262 def _build_item_for_save validate_key_values @data.populate_default_values @data.build_save_hash end
# File lib/aws-record/record/item_operations.rb, line 320 def _dirty_changes_for_update attributes = self.class.attributes ret = dirty.inject({}) do |acc, attr_name| acc[attr_name] = @data.raw_value(attr_name) acc end ret end
# File lib/aws-record/record/item_operations.rb, line 199 def _invalid_record?(opts) if self.respond_to?(:valid?) if !self.valid? true else false end else false end end
# File lib/aws-record/record/item_operations.rb, line 211 def _perform_save(opts) force = opts[:force] expect_new = expect_new_item? if force dynamodb_client.put_item( table_name: self.class.table_name, item: _build_item_for_save ) elsif expect_new put_opts = { table_name: self.class.table_name, item: _build_item_for_save }.merge(prevent_overwrite_expression) begin dynamodb_client.put_item(put_opts) rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e raise Errors::ConditionalWriteFailed.new( "Conditional #put_item call failed! Check that conditional write"\ " conditions are met, or include the :force option to clobber"\ " the remote item." ) end else update_pairs = _dirty_changes_for_update update_tuple = self.class.send( :_build_update_expression, update_pairs ) if update_tuple uex, exp_attr_names, exp_attr_values = update_tuple request_opts = { table_name: self.class.table_name, key: key_values, update_expression: uex, expression_attribute_names: exp_attr_names, } request_opts[:expression_attribute_values] = exp_attr_values unless exp_attr_values.empty? dynamodb_client.update_item(request_opts) else dynamodb_client.update_item( table_name: self.class.table_name, key: key_values ) end end data = self.instance_variable_get("@data") data.destroyed = false data.new_record = false true end
# File lib/aws-record/record/item_operations.rb, line 295 def expect_new_item? # Algorithm: Are keys dirty? If so, we treat as new. self.class.keys.any? do |_, attr_name| attribute_dirty?(attr_name) end end
# File lib/aws-record/record/item_operations.rb, line 268 def key_values validate_key_values attributes = self.class.attributes self.class.keys.inject({}) do |acc, (_, attr_name)| db_name = attributes.storage_name_for(attr_name) acc[db_name] = attributes.attribute_for(attr_name). serialize(@data.raw_value(attr_name)) acc end end
# File lib/aws-record/record/item_operations.rb, line 288 def missing_key_values self.class.keys.inject([]) do |acc, key| acc << key.last if @data.raw_value(key.last).nil? acc end end
# File lib/aws-record/record/item_operations.rb, line 302 def prevent_overwrite_expression conditions = [] expression_attribute_names = {} keys = self.class.instance_variable_get("@keys") # Hash Key conditions << "attribute_not_exists(#H)" expression_attribute_names["#H"] = keys.hash_key_attribute.database_name # Range Key if self.class.range_key conditions << "attribute_not_exists(#R)" expression_attribute_names["#R"] = keys.range_key_attribute.database_name end { condition_expression: conditions.join(" and "), expression_attribute_names: expression_attribute_names } end
# File lib/aws-record/record/item_operations.rb, line 279 def validate_key_values missing = missing_key_values unless missing.empty? raise Errors::KeyMissing.new( "Missing required keys: #{missing.join(', ')}" ) end end