require 'lotus/model/mapping/coercions'
require 'multi_json'
module Lotus
module Model
module Adapters
module Dynamodb
class Coercer < Lotus::Model::Mapping::Coercer
SKIPPED_KLASSES = [Float, Integer, Set, String]
SUPPORTED_KLASSES = [AWS::DynamoDB::Binary, Array, Boolean, Date, DateTime, Hash, Time]
def from_aws_dynamodb_binary(value)
return value if value.nil? || value.is_a?(AWS::DynamoDB::Binary)
AWS::DynamoDB::Binary.new(value)
end
alias_method :to_aws_dynamodb_binary, :from_aws_dynamodb_binary
def from_array(value)
_serialize(value)
end
def to_array(value)
_deserialize(value)
end
def from_boolean(value)
value ? 1 : 0
end
def to_boolean(value)
value.to_i == 1
end
def from_date(value)
value.to_time.to_i
end
def to_date(value)
Time.at(value.to_i).to_date
end
def from_datetime(value)
value.to_time.to_f
end
def to_datetime(value)
Time.at(value.to_f).to_datetime
end
def from_hash(value)
_serialize(value)
end
def to_hash(value)
_deserialize(value)
end
def from_time(value)
value.to_f
end
def to_time(value)
Time.at(value.to_f)
end
private
def _compile!
_compile_skipped!
_compile_record!
_compile_serialization!
end
def _compile_skipped!
instance_eval(SKIPPED_KLASSES.map do |klass|
%{
def from_#{_method_name(klass)}(value)
value
end
def to_#{_method_name(klass)}(value)
value
end
}
end.join("\n"))
end
def _compile_record!
instance_eval %{
def to_record(entity)
if entity.id
Hash[*[#{ @collection.attributes.map{|name,(klass,mapped)| ":#{mapped},from_#{_method_name(klass)}(entity.#{name})"}.join(',') }]]
else
Hash[*[#{ @collection.attributes.reject{|name,_| name == @collection.identity }.map{|name,(klass,mapped)| ":#{mapped},from_#{_method_name(klass)}(entity.#{name})"}.join(',') }]]
end
end
def from_record(record)
#{ @collection.entity }.new(
Hash[*[#{ @collection.attributes.map{|name,(klass,mapped)| ":#{name},#{coercions_wrap(klass) { "to_#{_method_name(klass)}(record[:#{mapped}])" }}"}.join(',') }]]
)
end
}
end
def _compile_serialization!
instance_eval(@collection.attributes.map do |_,(klass,mapped)|
%{
def deserialize_#{ mapped }(value)
#{coercions_wrap(klass) { "from_#{_method_name(klass)}(value)" }}
end
def serialize_#{ mapped }(value)
from_#{_method_name(klass)}(value)
end
}
end.join("\n"))
end
def coercions_wrap(klass)
if klass.to_s.include?("::")
yield
else
"Lotus::Model::Mapping::Coercions.#{klass}(#{yield})"
end
end
def _method_name(klass)
klass.to_s.downcase.gsub("::", "_")
end
def _serialize(value)
MultiJson.dump(value)
end
def _deserialize(value)
MultiJson.load(value)
end
end
end
end
end
end