From b59e760b15969671ea9c8cfcbd119fe626aa389e Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Tue, 2 Jun 2015 16:17:46 -0700 Subject: [PATCH 1/2] Don't Read IO Objects in Attribute Value Marshal Resolves Issue #831 Running the following code exercised the problem, and now works with this change: ``` dynamodb.put_item( table_name: "foo", item: { id: 1, contents: StringIO.new("bar") } ) ``` The issue appeared to be that #read was called twice on the StringIO or IO object, and the second call would fail as String#read does not exist. --- aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb | 2 +- aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb b/aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb index c8dc9a07dbc..de4d4e248e9 100644 --- a/aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb +++ b/aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb @@ -34,7 +34,7 @@ def format(obj) end when String then { s: obj } when Numeric then { n: obj.to_s } - when StringIO, IO then { b: obj.read } + when StringIO, IO then { b: obj } when Set then format_set(obj) when true, false then { bool: obj } when nil then { null: true } diff --git a/aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb b/aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb index e0a5d6ff5bb..65a3e70561e 100644 --- a/aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb +++ b/aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb @@ -26,6 +26,12 @@ module DynamoDB ]) end + it 'converts IO objects to :b (blob)' do + io = StringIO.new('bar') + formatted = value.marshal(foo: io) + expect(formatted[:m]["foo"][:b].read).to eq('bar') + end + it 'converts string sets to :ss (string set)' do formatted = value.marshal(Set.new(%w(abc mno))) expect(formatted).to eq(ss: %w(abc mno)) From 2e23d3508a1d8af9b4bc08691cb7232a1b272d52 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Wed, 3 Jun 2015 14:10:24 -0700 Subject: [PATCH 2/2] Fix IO Handling in DynamoDB Sets The hash and array logic used the format method changed in the previous diff, so those worked correctly from the outset. Sets, however, had special logic which required a second change. --- aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb | 2 +- aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb b/aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb index de4d4e248e9..161ff881724 100644 --- a/aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb +++ b/aws-sdk-core/lib/aws-sdk-core/dynamodb/attribute_value.rb @@ -51,7 +51,7 @@ def format_set(set) case set.first when String then { ss: set.map(&:to_s) } when Numeric then { ns: set.map(&:to_s) } - when StringIO, IO then { bs: set.map(&:read) } + when StringIO, IO then { bs: set.to_a } else msg = "set types only support String, Numeric, or IO objects" raise ArgumentError, msg diff --git a/aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb b/aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb index 65a3e70561e..cb9384b0794 100644 --- a/aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb +++ b/aws-sdk-core/spec/aws/dynamodb/attribute_value_spec.rb @@ -26,7 +26,7 @@ module DynamoDB ]) end - it 'converts IO objects to :b (blob)' do + it 'converts IO objects to :b (binary)' do io = StringIO.new('bar') formatted = value.marshal(foo: io) expect(formatted[:m]["foo"][:b].read).to eq('bar') @@ -43,8 +43,9 @@ module DynamoDB end it 'converts binary sets to :bs (binary set)' do - formatted = value.marshal(Set.new([StringIO.new('data')])) - expect(formatted).to eq(bs: ['data']) + io_obj = StringIO.new('data') + formatted = value.marshal(Set.new([io_obj])) + expect(formatted).to eq(bs: [io_obj]) end it 'converts numerics to :n (number)' do