module AWS::Record::AbstractBase::InstanceMethods
Public Class Methods
Constructs a new record.
@param [Hash] attributes Attributes
that should be bulk assigned
to this record. You can also specify the shard (i.e. domain or table) this record should persist to via +:shard+).
@option attributes [String] :shard The domain/table this record
should persist to. If this is omitted, it will persist to the class default shard (which defaults to the class name).
@return [Model,HashModel] Returns a new (non-persisted) record.
Call {#save} to persist changes to AWS.
# File lib/aws/record/abstract_base.rb, line 58 def initialize attributes = {} attributes = attributes.dup # supporting :domain for backwards compatability, :shard is prefered @_shard = attributes.delete(:domain) @_shard ||= attributes.delete('domain') @_shard ||= attributes.delete(:shard) @_shard ||= attributes.delete('shard') @_shard = self.class.shard_name(@_shard) @_data = {} assign_default_values bulk_assign(attributes) end
Public Instance Methods
@return [Hash] A hash with attribute names as hash keys (strings) and
attribute values (of mixed types) as hash values.
# File lib/aws/record/abstract_base.rb, line 93 def attributes attributes = Core::IndifferentHash.new attributes['id'] = id if persisted? self.class.attributes.keys.inject(attributes) do |hash,attr_name| hash.merge(attr_name => __send__(attr_name)) end end
Acts like {#update} but does not call {#save}.
record.attributes = { :name => 'abc', :age => 20 }
@param [Hash] attributes A hash of attributes to set on this record
without calling save.
@return [Hash] Returns the attribute hash that was passed in.
# File lib/aws/record/abstract_base.rb, line 110 def attributes= attributes bulk_assign(attributes) end
Deletes the record. @return [true]
# File lib/aws/record/abstract_base.rb, line 194 def delete if persisted? if deleted? raise 'unable to delete, this object has already been deleted' else delete_storage @_deleted = true end else raise 'unable to delete, this object has not been saved yet' end end
@return [Boolean] Returns true if this instance object has been deleted.
# File lib/aws/record/abstract_base.rb, line 209 def deleted? persisted? ? !!@_deleted : false end
# File lib/aws/record/abstract_base.rb, line 142 def errors @errors ||= Errors.new end
The id for each record is auto-generated. The default strategy generates uuid strings. @return [String] Returns the id string (uuid) for this record. Retuns
nil if this is a new record that has not been persisted yet.
# File lib/aws/record/abstract_base.rb, line 87 def id @_id end
@return [Boolean] Returns true if this record has not been persisted
to SimpleDB.
# File lib/aws/record/abstract_base.rb, line 129 def new_record? !persisted? end
Persistence indicates if the record has been saved previously or not.
@example
@recipe = Recipe.new(:name => 'Buttermilk Pancackes') @recipe.persisted? #=> false @recipe.save! @recipe.persisted? #=> true
@return [Boolean] Returns true if this record has been persisted.
# File lib/aws/record/abstract_base.rb, line 123 def persisted? !!@_persisted end
Creates new records, updates existing records. @param [Hash] opts Pass :validate => false to skip validations @return [Boolean] Returns true if the record saved without errors,
false otherwise.
# File lib/aws/record/abstract_base.rb, line 150 def save opts = {} if valid?(opts) persisted? ? update : create clear_changes! true else false end end
Creates new records, updates exsting records. If there is a validation error then an exception is raised. @raise [InvalidRecordError] Raised when the record has validation
errors and can not be saved.
@return [true] Returns true after a successful save.
# File lib/aws/record/abstract_base.rb, line 165 def save! raise InvalidRecordError.new(self) unless save true end
@return [String] Returns the name of the shard this record
is persisted to or will be persisted to. Defaults to the domain/table named after this record class.
# File lib/aws/record/abstract_base.rb, line 78 def shard @_shard end
Bulk assigns the attributes and then saves the record. @param [Hash] attribute_hash A hash of attribute names (keys) and
attribute values to assign to this record.
@return (see save
)
# File lib/aws/record/abstract_base.rb, line 174 def update_attributes attribute_hash bulk_assign(attribute_hash) save end
Bulk assigns the attributes and then saves the record. Raises an exception (AWS::Record::InvalidRecordError
) if the record is not valid. @param (see update_attributes
) @return [true]
# File lib/aws/record/abstract_base.rb, line 184 def update_attributes! attribute_hash if update_attributes(attribute_hash) true else raise InvalidRecordError.new(self) end end
@param [Hash] opts Pass :validate => false to skip validations @return [Boolean] Returns true if this record has no validation errors.
# File lib/aws/record/abstract_base.rb, line 135 def valid? opts = {} opts = {} if opts.nil? opts = {:validate => true}.merge(opts) run_validations if opts[:validate] errors.empty? end
Protected Instance Methods
Returns the typecasted value for the named attribute.
book = Book.new(:title => 'My Book') book['title'] #=> 'My Book' book.title #=> 'My Book'
Intended Use¶ ↑
This method’s primary use is for getting/setting the value for an attribute inside a custom method:
class Book < AWS::Record::Model string_attr :title def title self['title'] ? self['title'].upcase : nil end end book = Book.new(:title => 'My Book') book.title #=> 'MY BOOK'
@param [String,Symbol] attribute_name The name of the attribute to fetch
a value for.
@return The current type-casted value for the named attribute.
# File lib/aws/record/abstract_base.rb, line 276 def [] attribute_name self.class.attribute_for(attribute_name) do |attribute| type_cast(attribute, @_data[attribute.name]) end end
If you define a custom setter, you use []=
to set the value on the record.
class Book < AWS::Record::Model string_attr :name # replace the default #author= method def author= name self['author'] = name.blank? ? 'Anonymous' : name end end
@param [String,Symbol] The attribute name to set a value for @param attribute_value The value to assign.
# File lib/aws/record/abstract_base.rb, line 230 def []= attribute_name, new_value self.class.attribute_for(attribute_name) do |attribute| if_tracking_changes do original_value = type_cast(attribute, attribute_was(attribute.name)) incoming_value = type_cast(attribute, new_value) if original_value == incoming_value clear_change!(attribute.name) else attribute_will_change!(attribute.name) end end @_data[attribute.name] = new_value end end
# File lib/aws/record/abstract_base.rb, line 283 def create populate_id touch_timestamps('created_at', 'updated_at') increment_optimistic_lock_value create_storage @_persisted = true end
# File lib/aws/record/abstract_base.rb, line 483 def create_storage raise NotImplementedError end
# File lib/aws/record/abstract_base.rb, line 493 def delete_storage raise NotImplementedError end
@private
# File lib/aws/record/abstract_base.rb, line 461 def hydrate id, data # @todo need to do something about partial hyrdation of attributes @_id = id # New objects are populated with default values, but we don't # want these values to hang around when hydrating persisted values # (those values may have been blanked out before save). self.class.attributes.values.each do |attribute| @_data[attribute.name] = nil end ignore_changes do bulk_assign(deserialize_item_data(data)) end @_persisted = true end
# File lib/aws/record/abstract_base.rb, line 330 def if_locks_optimistically &block if opt_lock_attr = self.class.optimistic_locking_attr yield(opt_lock_attr) end end
# File lib/aws/record/abstract_base.rb, line 319 def increment_optimistic_lock_value if_locks_optimistically do |lock_attr| if value = self[lock_attr.name] self[lock_attr.name] = value + 1 else self[lock_attr.name] = 1 end end end
# File lib/aws/record/abstract_base.rb, line 337 def opt_lock_conditions conditions = {} if_locks_optimistically do |lock_attr| if was = attribute_was(lock_attr.name) conditions[:if] = { lock_attr.name => lock_attr.serialize(was) } else conditions[:unless_exists] = lock_attr.name end end conditions end
# File lib/aws/record/abstract_base.rb, line 300 def populate_id @_id = UUIDTools::UUID.random_create.to_s.downcase end
# File lib/aws/record/abstract_base.rb, line 305 def touch_timestamps *attributes now = Time.now attributes.each do |attr_name| if self.class.attributes[attr_name] and !attribute_changed?(attr_name) # don't touch timestamps the user modified then __send__("#{attr_name}=", now) end end end
# File lib/aws/record/abstract_base.rb, line 488 def update_storage raise NotImplementedError end
Private Instance Methods
# File lib/aws/record/abstract_base.rb, line 350 def assign_default_values # populate default attribute values ignore_changes do self.class.attributes.values.each do |attribute| begin # copy default values down so methods like #gsub! don't # modify the default values for other objects @_data[attribute.name] = attribute.default_value.clone rescue TypeError @_data[attribute.name] = attribute.default_value end end end end
# File lib/aws/record/abstract_base.rb, line 366 def bulk_assign hash flatten_date_parts(hash).each_pair do |attr_name, attr_value| __send__("#{attr_name}=", attr_value) end end
Rails
date and time select helpers split date and time attributes into multiple values for form submission. These attributes get named things like ‘created_at(1i)’ and represent year/month/day/hour/min/sec parts of the date/time.
This method converts these attributes back into a single value and converts them to Date and DateTime objects.
# File lib/aws/record/abstract_base.rb, line 381 def flatten_date_parts attributes multi_attributes = Set.new hash = attributes.inject({}) do |hash,(key,value)| # collects attribuets like "created_at(1i)" into an array of parts if key =~ /\(/ key, index = key.to_s.split(/\(|i\)/) hash[key] ||= [] hash[key][index.to_i - 1] = value.to_i multi_attributes << key else hash[key] = value end hash end # convert multiattribute values into date/time objects multi_attributes.each do |key| values = hash[key] hash[key] = case values.size when 0 then nil when 2 now = Time.now Time.local(now.year, now.month, now.day, values[0], values[1], 0, 0) when 3 then Date.new(*values) else DateTime.new(*values) end end hash end
# File lib/aws/record/abstract_base.rb, line 450 def serialize_attribute attribute, raw_value type_casted_value = type_cast(attribute, raw_value) case type_casted_value when nil then nil when Set then type_casted_value.map{|v| attribute.serialize(v) } else attribute.serialize(type_casted_value) end end
# File lib/aws/record/abstract_base.rb, line 432 def serialize_attributes hash = {} self.class.attributes.each_pair do |attribute_name,attribute| value = serialize_attribute(attribute, @_data[attribute_name]) unless [nil, []].include?(value) hash[attribute_name] = value end end # simple db does not support persisting items without attribute values raise EmptyRecordError.new(self) if hash.empty? hash end
# File lib/aws/record/abstract_base.rb, line 419 def type_cast attribute, raw if attribute.set? values = Record.as_array(raw).inject([]) do |values,value| values << attribute.type_cast(value) values end Set.new(values.compact) else attribute.type_cast(raw) end end
# File lib/aws/record/abstract_base.rb, line 292 def update return unless changed? touch_timestamps('updated_at') increment_optimistic_lock_value update_storage end