class AWS::Record::HashModel

Public Class Methods

[](id, options = {})
Alias for: find_by_id
all(options = {}) click to toggle source

Returns an enumerable scope object represents all records.

Book.all.each do |book|
  # ...
end

This method is equivalent to +find(:all)+, and therefore you can also pass aditional options.

Book.all(:where => { :author' => 'me' }).each do |my_book|
  # ...
end

@return [Scope] Returns an enumerable scope object.

# File lib/aws/record/hash_model/finder_methods.rb, line 109
def all options = {}
  new_scope.find(:all, options)
end
binary_attr(name, options = {}) click to toggle source

Adds a DynamoDB binary attribute to this class. A binary attribute acts the same as a string attribute, except

@param [Symbol] name The name of the attribute.

@param [Hash] options

@option options [Boolean] :set (false) When true this attribute

can have multiple values.

@note This should not be used for large objects.

# File lib/aws/record/hash_model/attributes.rb, line 171
def binary_attr name, options = {}
end
boolean_attr(name, options = {}) click to toggle source

Adds a boolean attribute to this class.

@example

class Book < AWS::Record::HashModel
  boolean_attr :read
end

b = Book.new
b.read? # => false
b.read = true
b.read? # => true

listing = Listing.new(:score => '123.456'
listing.score # => 123.456

@param [Symbol] name The name of the attribute.

# File lib/aws/record/hash_model/attributes.rb, line 100
def boolean_attr name, options = {}

  attr = add_attribute(Attributes::BooleanAttr.new(name, options))

  # add the boolean question mark method
  define_method("#{attr.name}?") do
    !!__send__(attr.name)
  end

end
count(options = {}) click to toggle source

Counts records Amazon DynamoDB.

class Product < AWS::Record::HashModel
end

# returns the count of records in the 'Product' table
Product.count

You can specify the table via shard

# returns the count of records in the 'products-1' table
Product.shard('products-1').count

You can also specify the shard as an option to count.

Product.count(:shard => 'table-name')

Chaining count with limit has no effect on the count.

Product.limit(10).count # same as Product.count, limit ignored

@param [Hash] options

@option [String] :shard Which shard to count records in.

@return [Integer] The count of records in the table.

# File lib/aws/record/hash_model/finder_methods.rb, line 145
def count options = {}
  new_scope.count(options)
end
Also aliased as: size
create_table(read_capacity_units, write_capacity_units, options = {}) click to toggle source

Creates the DynamoDB table that is configured for this class.

class Product < AWS::Record::HashModel
end

# create the table 'Product' with 10 read/write capacity units
Product.create_table 10, 10

If you shard you data across multiple tables, you can specify the shard name:

# create two tables, with the given names
Product.create_table 500, 10, :shard_name => 'products-1'
Product.create_table 500, 10, :shard_name => 'products-2'

If you share a single AWS account with multiple applications, you can provide a table prefix to group tables and to avoid name collisions:

AWS::Record.table_prefix = 'myapp-'

# creates the table 'myapp-Product'
Product.create_table 250, 50

# creates the table 'myapp-products-1'
Product.create_table 250, 50, :shard_name => 'products-1'

@param [Integer] read_capacity_units

See {DynamoDB::TableCollection#create} for more information.

@param [Integer] write_capacity_units

See {DynamoDB::TableCollection#create} for more information.

@param [Hash] options

@option options [String] :shard_name Defaults to the class name. The

shard name will be prefixed with {AWS::Record.table_prefix},
and that becomes the table name.

@return [DynamoDB::Table]

# File lib/aws/record/hash_model.rb, line 68
def create_table read_capacity_units, write_capacity_units, options = {}

  table_name = dynamo_db_table_name(options[:shard_name])

  create_opts = {}
  create_opts[:hash_key] = { :id => :string }

  dynamo_db.tables.create(
    table_name, 
    read_capacity_units, 
    write_capacity_units, 
    create_opts)

end
date_attr(name, options = {}) click to toggle source

Adds a date attribute to this class.

@example A standard date attribute

class Person < AWS::Record::HashModel
  date_attr :birthdate
end

baby = Person.new
baby.birthdate = Time.now
baby.birthdate #=> <Date: ....>

@param [Symbol] name The name of the attribute.

@param [Hash] options

@option options [Boolean] :set (false) When true this attribute

can have multiple dates.
# File lib/aws/record/hash_model/attributes.rb, line 155
def date_attr name, options = {}
  add_attribute(Attributes::DateAttr.new(name, options))
end
datetime_attr(name, options = {}) click to toggle source

Adds a datetime attribute to this class.

@example A standard datetime attribute

class Recipe < AWS::Record::HashModel
  datetime_attr :invented
end

recipe = Recipe.new(:invented => Time.now)
recipe.invented #=> <DateTime ...>

If you add a ::datetime_attr for :created_at and/or :updated_at those will be automanaged.

@param [Symbol] name The name of the attribute.

@param [Hash] options

@option options [Boolean] :set (false) When true this attribute

can have multiple date times.
# File lib/aws/record/hash_model/attributes.rb, line 132
def datetime_attr name, options = {}
  add_attribute(Attributes::DateTimeAttr.new(name, options))
end
domain(shard_name)
Alias for: shard
dynamo_db_table(shard_name = nil) click to toggle source

@return [DynamoDB::Table] @private

# File lib/aws/record/hash_model.rb, line 85
def dynamo_db_table shard_name = nil
  table = dynamo_db.tables[dynamo_db_table_name(shard_name)]
  table.hash_key = [:id, :string]
  table
end
each(&block) click to toggle source

Yields once for each record.

# File lib/aws/record/hash_model/finder_methods.rb, line 114
def each &block
  all.each(&block)
end
find(*args) click to toggle source

Finds records in Amazon DynamoDB and returns them as objects of the current class.

Finding :all returns an enumerable scope object

People.find(:all, :limit => 10).each do |person|
  puts person.name
end

Finding :first returns a single record (or nil)

boss = People.find(:first)

Find accepts a hash of find modifiers (:shard and :limit). You can also choose to omit these modifiers and chain them on the scope object returned. In the following example only one request is made to SimpleDB (when each is called)

people = People.find(:all, :limit => 10)

people = people.limit(10).find(:all)

@overload find(id)

@param id The record to find, raises an exception if the record is
  not found.

@overload find(mode, options = {})

@param [:all,:first] mode (:all) When finding +:all+ matching records
  and array is returned of records.  When finding +:first+ then
  +nil+ or a single record will be returned.
@param [Hash] options
@option options [Integer] :shard The shard name of the Amazon 
  DynamoDB table to search.
@option options [Integer] :limit The max number of records to fetch.
# File lib/aws/record/hash_model/finder_methods.rb, line 76
def find *args
  new_scope.find(*args)
end
find_by_id(id, options = {}) click to toggle source

@param [String] id The id of the record to load. @param [Hash] options @option options [String] :shard Specifies what shard (i.e. table)

should be searched.

@raise [RecordNotFound] Raises a record not found exception if there

was no data found for the given id.

@return [Record::HashModel] Returns the record with the given id.

# File lib/aws/record/hash_model/finder_methods.rb, line 26
def find_by_id id, options = {}
  
  table = dynamo_db_table(options[:shard])

  data = table.items[id].attributes.to_h
  
  raise RecordNotFound, "no data found for id: #{id}" if data.empty?
  
  obj = self.new(:shard => table)
  obj.send(:hydrate, id, data)
  obj
  
end
Also aliased as: []
first(options = {}) click to toggle source

@return [Object,nil] Returns the first record found. If there were

no records found, nil is returned.
# File lib/aws/record/hash_model/finder_methods.rb, line 152
def first options = {}
  new_scope.first(options)
end
float_attr(name, options = {}) click to toggle source

Adds a float attribute to this class.

class Listing < AWS::Record::HashModel
  float_attr :score
end

listing = Listing.new(:score => '123.456')
listing.score # => 123.456

@param [Symbol] name The name of the attribute. @param [Hash] options @option options [Boolean] :set (false) When true this attribute

can have multiple values.
# File lib/aws/record/hash_model/attributes.rb, line 79
def float_attr name, options = {}
  add_attribute(Attributes::FloatAttr.new(name, options))
end
integer_attr(name, options = {}) click to toggle source

Adds an integer attribute to this class.

class Recipe < AWS::Record::HashModel
  integer_attr :servings
end

recipe = Recipe.new(:servings => '10')
recipe.servings #=> 10

@param [Symbol] name The name of the attribute. @param [Hash] options @option options [Boolean] :set (false) When true this attribute

can have multiple values.
# File lib/aws/record/hash_model/attributes.rb, line 62
def integer_attr name, options = {}
  add_attribute(Attributes::IntegerAttr.new(name, options))
end
limit(limit) click to toggle source

The maximum number of records to return. By default, all records matching the where conditions will be returned from a find.

People.limit(10).each {|person| ... }

Limit can be chained with other scope modifiers:

People.where(:age => 40).limit(10).each {|person| ... }
# File lib/aws/record/hash_model/finder_methods.rb, line 165
def limit limit
  new_scope.limit(limit)
end
shard(shard_name) click to toggle source

Returns a chainable scope object that restricts further scopes to a particular table.

Book.shard('books-2').each do |book|
  # ...
end

@param [String] shard_name @return [Scope] Returns a scope for restricting the table searched.

# File lib/aws/record/hash_model/finder_methods.rb, line 89
def shard shard_name
  new_scope.shard(shard_name)
end
Also aliased as: domain
size(options = {})
Alias for: count
string_attr(name, options = {}) click to toggle source

Adds a string attribute to this class.

@example A standard string attribute

class Recipe < AWS::Record::HashModel
  string_attr :name
end

recipe = Recipe.new(:name => "Buttermilk Pancakes")
recipe.name #=> 'Buttermilk Pancakes'

@example A string attribute with :set set to true

class Recipe < AWS::Record::HashModel
  string_attr :tags, :set => true
end

recipe = Recipe.new(:tags => %w(popular dessert))
recipe.tags #=> #<Set: {"popular", "desert"}>

@param [Symbol] name The name of the attribute. @param [Hash] options @option options [Boolean] :set (false) When true this attribute

can have multiple values.
# File lib/aws/record/hash_model/attributes.rb, line 45
def string_attr name, options = {}
  add_attribute(Attributes::StringAttr.new(name, options))
end
timestamps() click to toggle source

A convenience method for adding the standard two datetime attributes :created_at and :updated_at.

@example

class Recipe < AWS::Record::HashModel
  timestamps
end

recipe = Recipe.new
recipe.save
recipe.created_at #=> <DateTime ...>
recipe.updated_at #=> <DateTime ...>
# File lib/aws/record/hash_model/attributes.rb, line 188
def timestamps
  c = datetime_attr :created_at
  u = datetime_attr :updated_at
  [c, u]
end

Protected Class Methods

dynamo_db() click to toggle source
# File lib/aws/record/hash_model.rb, line 97
def dynamo_db
  AWS::DynamoDB.new
end
dynamo_db_table_name(shard_name = nil) click to toggle source
# File lib/aws/record/hash_model.rb, line 92
def dynamo_db_table_name shard_name = nil
  "#{Record.table_prefix}#{self.shard_name(shard_name)}"
end

Private Instance Methods

create_storage() click to toggle source
# File lib/aws/record/hash_model.rb, line 119
def create_storage
  attributes = serialize_attributes.merge('id' => @_id)
  dynamo_db_table.items.create(attributes, opt_lock_conditions)
end
delete_storage() click to toggle source
# File lib/aws/record/hash_model.rb, line 142
def delete_storage
  dynamo_db_item.delete(opt_lock_conditions)
end
deserialize_item_data(data) click to toggle source
# File lib/aws/record/hash_model.rb, line 147
def deserialize_item_data data
  data.inject({}) do |hash,(attr_name,value)|
    if attribute = self.class.attributes[attr_name]
      hash[attr_name] = value.is_a?(Set) ?
        value.map{|v| attribute.deserialize(v) } :
        attribute.deserialize(value)
    end
    hash
  end
end
dynamo_db_item() click to toggle source

@return [DynamoDB::Item] Returns a reference to the item as stored in

simple db.

@private

# File lib/aws/record/hash_model.rb, line 107
def dynamo_db_item
  dynamo_db_table.items[id]
end
dynamo_db_table() click to toggle source

@return [SimpleDB::Domain] Returns the domain this record is

persisted to or will be persisted to.
# File lib/aws/record/hash_model.rb, line 114
def dynamo_db_table
  self.class.dynamo_db_table(shard)
end
update_storage() click to toggle source
# File lib/aws/record/hash_model.rb, line 125
def update_storage
  # Only enumerating dirty (i.e. changed) attributes.  Empty
  # (nil and empty set) values are deleted, the others are replaced.
  dynamo_db_item.attributes.update(opt_lock_conditions) do |u|
    changed.each do |attr_name|
      attribute = self.class.attribute_for(attr_name)
      value = serialize_attribute(attribute, @_data[attr_name])
      if value.nil? or value == []
        u.delete(attr_name)
      else
        u.set(attr_name => value)
      end
    end
  end
end