Skip to content

Commit

Permalink
Merge pull request #283 from Dynamoid/fix-table-creation
Browse files Browse the repository at this point in the history
Fix table creation
  • Loading branch information
pboling committed Aug 5, 2018
2 parents 2744fa5 + 9b23ae7 commit 99cd84b
Show file tree
Hide file tree
Showing 11 changed files with 407 additions and 34 deletions.
1 change: 1 addition & 0 deletions lib/dynamoid.rb
Expand Up @@ -22,6 +22,7 @@
require 'dynamoid/dumping'
require 'dynamoid/undumping'
require 'dynamoid/type_casting'
require 'dynamoid/primary_key_type_mapping'
require 'dynamoid/dirty'
require 'dynamoid/validations'
require 'dynamoid/criteria'
Expand Down
2 changes: 2 additions & 0 deletions lib/dynamoid/errors.rb
Expand Up @@ -73,5 +73,7 @@ def initialize(document)
end

class InvalidQuery < Error; end

class UnsupportedKeyType < Error; end
end
end
4 changes: 2 additions & 2 deletions lib/dynamoid/indexes.rb
Expand Up @@ -228,7 +228,7 @@ def validate_range_key
range_key_type = range_field_attributes[:type]
if Dynamoid::Fields::PERMITTED_KEY_TYPES.include?(range_key_type)
@range_key_schema = {
@range_key => @dynamoid_class.dynamo_type(range_key_type)
@range_key => PrimaryKeyTypeMapping.dynamodb_type(range_key_type, range_field_attributes)
}
else
errors.add(:range_key, 'Index :range_key is not a valid key type')
Expand All @@ -245,7 +245,7 @@ def validate_hash_key
hash_field_type = hash_field_attributes[:type]
if Dynamoid::Fields::PERMITTED_KEY_TYPES.include?(hash_field_type)
@hash_key_schema = {
@hash_key => @dynamoid_class.dynamo_type(hash_field_type)
@hash_key => PrimaryKeyTypeMapping.dynamodb_type(hash_field_type, hash_field_attributes)
}
else
errors.add(:hash_key, 'Index :hash_key is not a valid key type')
Expand Down
20 changes: 3 additions & 17 deletions lib/dynamoid/persistence.rb
Expand Up @@ -36,15 +36,16 @@ def table_name
# @since 0.4.0
def create_table(options = {})
range_key_hash = if range_key
{ range_key => dynamo_type(attributes[range_key][:type]) }
{ range_key => PrimaryKeyTypeMapping.dynamodb_type(attributes[range_key][:type], attributes[range_key]) }
end

options = {
id: hash_key,
table_name: table_name,
write_capacity: write_capacity,
read_capacity: read_capacity,
range_key: range_key_hash,
hash_key_type: dynamo_type(attributes[hash_key][:type]),
hash_key_type: PrimaryKeyTypeMapping.dynamodb_type(attributes[hash_key][:type], attributes[hash_key]),
local_secondary_indexes: local_secondary_indexes.values,
global_secondary_indexes: global_secondary_indexes.values
}.merge(options)
Expand All @@ -63,21 +64,6 @@ def from_database(attrs = {})
clazz.new(attrs_undumped).tap { |r| r.new_record = false }
end

def dynamo_type(type)
if type.is_a?(Class)
type.respond_to?(:dynamoid_field_type) ? type.dynamoid_field_type : :string
else
case type
when :integer, :number, :datetime, :date
:number
when :string, :serialized
:string
else
raise 'unknown type'
end
end
end

# Creates several models at once.
# Neither callbacks nor validations run.
# It works efficiently because of using BatchWriteItem.
Expand Down
34 changes: 34 additions & 0 deletions lib/dynamoid/primary_key_type_mapping.rb
@@ -0,0 +1,34 @@
# frozen_string_literal: true

module Dynamoid
class PrimaryKeyTypeMapping
def self.dynamodb_type(type, options)
if Class === type
type = type.respond_to?(:dynamoid_field_type) ? type.dynamoid_field_type : :string
end

case type
when :string, :serialized
:string
when :integer, :number
:number
when :datetime
string_format = if options[:store_as_string].nil?
Dynamoid::Config.store_datetime_as_string
else
options[:store_as_string]
end
string_format ? :string : :number
when :date
string_format = if options[:store_as_string].nil?
Dynamoid::Config.store_date_as_string
else
options[:store_as_string]
end
string_format ? :string : :number
else
raise Errors::UnsupportedKeyType, "#{type} cannot be used as a type of table key attribute"
end
end
end
end
6 changes: 3 additions & 3 deletions spec/dynamoid/dumping_spec.rb
Expand Up @@ -173,7 +173,7 @@
end
end

it 'loads time in local time zone if config.application_timezone == :local', application_timezone: :local do
it 'loads time in local time zone if config.application_timezone == :local', config: { application_timezone: :local } do
time = Time.now
obj = klass.create(last_logged_in_at: time)
obj = klass.find(obj.id)
Expand All @@ -182,14 +182,14 @@
expect(obj.last_logged_in_at.to_s).to eql time.to_datetime.to_s
end

it 'loads time in specified time zone if config.application_timezone == time zone name', application_timezone: 'Hawaii' do
it 'loads time in specified time zone if config.application_timezone == time zone name', config: { application_timezone: 'Hawaii' } do
time = '2017-06-20 08:00:00 +0300'.to_time
obj = klass.create(last_logged_in_at: time)
obj = klass.find(obj.id)
expect(obj.last_logged_in_at).to eql '2017-06-19 19:00:00 -1000'.to_datetime # Hawaii UTC-10
end

it 'loads time in UTC if config.application_timezone = :utc', application_timezone: :utc do
it 'loads time in UTC if config.application_timezone = :utc', config: { application_timezone: :utc } do
time = '2017-06-20 08:00:00 +0300'.to_time
obj = klass.create(last_logged_in_at: time)
obj = klass.find(obj.id)
Expand Down

0 comments on commit 99cd84b

Please sign in to comment.