lib/dynamodb_framework/dynamodb_repository.rb
require 'date'
require 'hash_kit'
module DynamoDbFramework
class Repository
attr_reader :dynamodb
attr_accessor :table_name
def initialize(store)
@dynamodb = store
end
# Store the hash of an object to the dynamodb table
# *Note* : [DateTime] attributes will be stored as an ISO8601 string
# [Time] attributes will be stored as an Epoch Int
# The intent is that if you need to sort in dynamo by dates, then make sure you use a [Time] type. The Epoch int allows
# you to compare properly as comparing date strings are not reliable.
def put(item)
hash = to_hash(item)
clean_hash(hash)
params =
{
table_name: @table_name,
item: hash
}
dynamodb.client.put_item(params)
return true
end
def delete(keys)
params =
{
table_name: @table_name,
key: keys
}
dynamodb.client.delete_item(params)
return true
end
def delete_item(partition_key:, partition_key_value:, range_key: nil, range_key_value: nil)
keys = {
partition_key.to_s => clean_value(partition_key_value)
}
if range_key != nil
keys[range_key.to_s] = clean_value(range_key_value)
end
params =
{
table_name: @table_name,
key: keys
}
dynamodb.client.delete_item(params)
return true
end
def get_by_key(partition_key, partition_value, range_key = nil, range_value = nil)
key = {}
key[partition_key] = clean_value(partition_value)
if(range_key != nil)
key[range_key] = clean_value(range_value)
end
params = {
table_name: table_name,
key: key
}
result = dynamodb.client.get_item(params)
hash_helper.hash_kit.indifferent!(result.item)
return result.item
end
def all
result = dynamodb.client.scan({
:table_name => @table_name
})
output = []
result.items.each do |item|
hash_helper.hash_kit.indifferent!(item)
output.push(item)
end
return output
end
def scan(expression, expression_params, limit = nil, count = false)
params = {
:table_name => table_name
}
if expression != nil
params[:filter_expression] = expression
end
if expression_params != nil
params[:expression_attribute_names] = {}
params[:expression_attribute_values] = {}
expression_params.each do |key, value|
if key[0] == '#'
params[:expression_attribute_names][key] = value
elsif key[0] == ':'
params[:expression_attribute_values][key] = clean_value(value)
end
end
end
if limit != nil
params[:limit] = limit
end
if count
params[:select] = 'COUNT'
else
params[:select] = 'ALL_ATTRIBUTES'
end
result = dynamodb.client.scan(params)
if count
return result.count
else
output = []
result.items.each do |item|
hash_helper.hash_kit.indifferent!(item)
output.push(item)
end
return output
end
end
def query(partition_key_name, partition_key_value, range_key_name = nil, range_key_value = nil, expression = nil, expression_params = nil, index_name = nil, limit = nil, count = false)
params = {
table_name: table_name
}
if expression != nil
params[:filter_expression] = expression
end
if index_name != nil
params[:index_name] = index_name
end
if range_key_name != nil
params[:key_condition_expression] = '#partition_key = :partition_key and #range_key = :range_key'
params[:expression_attribute_names] = { '#partition_key' => partition_key_name, '#range_key' => range_key_name }
params[:expression_attribute_values] = { ':partition_key' => clean_value(partition_key_value), ':range_key' => clean_value(range_key_value) }
else
params[:key_condition_expression] = '#partition_key = :partition_key'
params[:expression_attribute_names] = { '#partition_key' => partition_key_name }
params[:expression_attribute_values] = { ':partition_key' => clean_value(partition_key_value) }
end
if expression_params != nil
expression_params.each do |key, value|
if key[0] == '#'
params[:expression_attribute_names][key] = clean_value(value)
elsif key[0] == ':'
params[:expression_attribute_values][key] = clean_value(value)
end
end
end
if limit != nil
params[:limit] = limit
end
if count
params[:select] = 'COUNT'
else
params[:select] = 'ALL_ATTRIBUTES'
end
result = dynamodb.client.query(params)
if count
return result.count
else
output = []
result.items.each do |item|
hash_helper.hash_kit.indifferent!(item)
output.push(item)
end
return output
end
end
private
def to_hash(obj)
hash_helper.to_hash(obj)
end
def hash_helper
@hash_helper ||= HashHelper.new
end
# Convert empty string values to nil, as well as convert DateTime and Time to appropriate storage formats.
def clean_hash(hash)
hash.each do |key, value|
if value == ''
hash[key] = nil
elsif value.is_a?(Array)
value.each do |item|
clean_hash(item) if item.is_a?(Hash)
end
elsif [DateTime, Time].include?(value.class)
hash[key] = convert_date(value)
elsif value.is_a?(Hash)
clean_hash(value)
end
end
end
def convert_date(value)
klass = value.class
return value.iso8601 if klass == DateTime
return value.to_i if klass == Time
end
def clean_value(value)
if value.is_a?(Time) || value.is_a?(DateTime)
convert_date(value)
else
value
end
end
end
end