Skip to content

Commit ba039e7

Browse files
authored
Merge pull request #458 from Dynamoid/add-binary-type
Add binary type
2 parents 83fa232 + 43d12a2 commit ba039e7

File tree

8 files changed

+83
-18
lines changed

8 files changed

+83
-18
lines changed

.document

Lines changed: 0 additions & 5 deletions
This file was deleted.

README.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -212,16 +212,17 @@ each field. Every field on the object must be included here; if you miss
212212
any they'll be completely bypassed during DynamoDB's initialization and
213213
will not appear on the model objects.
214214

215-
By default, fields are assumed to be of type `:string`. Other built-in
216-
types are `:integer`, `:number`, `:set`, `:array`, `:map`, `:datetime`,
217-
`date`, `:boolean`, `:raw` and `:serialized`. `array` and `map` match
218-
List and Map DynamoDB types respectively. `raw` type means you can store
219-
Ruby Array, Hash, String and numbers. If built-in types do not suit you,
220-
you can use a custom field type represented by an arbitrary class,
221-
provided that the class supports a compatible serialization interface.
222-
The primary use case for using a custom field type is to represent your
223-
business logic with high-level types, while ensuring portability or
224-
backward-compatibility of the serialized representation.
215+
By default, fields are assumed to be of type `string`. Other built-in
216+
types are `integer`, `number`, `set`, `array`, `map`, `datetime`,
217+
`date`, `boolean`, `binary`, `raw` and `serialized`. `array` and
218+
`map` match List and Map DynamoDB types respectively. `raw` type means
219+
you can store Ruby Array, Hash, String and numbers. If built-in types do
220+
not suit you, you can use a custom field type represented by an
221+
arbitrary class, provided that the class supports a compatible
222+
serialization interface. The primary use case for using a custom field
223+
type is to represent your business logic with high-level types, while
224+
ensuring portability or backward-compatibility of the serialized
225+
representation.
225226

226227
#### Note on boolean type
227228

lib/dynamoid/dumping.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def self.find_dumper(options)
3636
when :serialized then SerializedDumper
3737
when :raw then RawDumper
3838
when :boolean then BooleanDumper
39+
when :binary then BinaryDumper
3940
when Class then CustomTypeDumper
4041
end
4142

@@ -288,6 +289,13 @@ def process(value)
288289
end
289290
end
290291

292+
# string -> string
293+
class BinaryDumper < Base
294+
def process(value)
295+
Base64.strict_encode64(value)
296+
end
297+
end
298+
291299
# any object -> string
292300
class CustomTypeDumper < Base
293301
def process(value)

lib/dynamoid/fields.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ module ClassMethods
4444
#
4545
# Its type determines how it is coerced when read in and out of the
4646
# datastore. You can specify +string+, +integer+, +number+, +set+, +array+,
47-
# +map+, +datetime+, +date+, +serialized+, +raw+ and +boolean+ or specify a
48-
# class that defines a serialization strategy.
47+
# +map+, +datetime+, +date+, +serialized+, +raw+, +boolean+ and +binary+
48+
# or specify a class that defines a serialization strategy.
49+
#
50+
# By default field type is +string+.
4951
#
5052
# Set can store elements of the same type only (it's a limitation of
5153
# DynamoDB itself). If a set should store elements only some particular
@@ -71,7 +73,7 @@ module ClassMethods
7173
#
7274
# field :published_on, :datetime, store_as_string: true
7375
#
74-
# Boolean field by default is stored as a string +t+ or 'f'. But DynamoDB
76+
# Boolean field by default is stored as a string +t+ or +f+. But DynamoDB
7577
# supports boolean type natively. In order to switch to the native
7678
# boolean type an option +store_as_native_boolean+ should be specified:
7779
#

lib/dynamoid/type_casting.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def self.find_type_caster(options)
3636
when :raw then RawTypeCaster
3737
when :serialized then SerializedTypeCaster
3838
when :boolean then BooleanTypeCaster
39+
when :binary then BinaryTypeCaster
3940
when Class then CustomTypeCaster
4041
end
4142

@@ -284,6 +285,16 @@ def process(value)
284285
end
285286
end
286287

288+
class BinaryTypeCaster < Base
289+
def process(value)
290+
if value.is_a? String
291+
value.dup
292+
else
293+
value.to_s
294+
end
295+
end
296+
end
297+
287298
class CustomTypeCaster < Base
288299
end
289300
end

lib/dynamoid/undumping.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def self.find_undumper(options)
3939
when :raw then RawUndumper
4040
when :serialized then SerializedUndumper
4141
when :boolean then BooleanUndumper
42+
when :binary then BinaryUndumper
4243
when Class then CustomTypeUndumper
4344
end
4445

@@ -263,6 +264,12 @@ def process(value)
263264
end
264265
end
265266

267+
class BinaryUndumper < Base
268+
def process(value)
269+
Base64.strict_decode64(value)
270+
end
271+
end
272+
266273
class CustomTypeUndumper < Base
267274
def process(value)
268275
field_class = @options[:type]

spec/dynamoid/dumping_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,4 +1491,21 @@ def self.dynamoid_field_type
14911491
end
14921492
end
14931493
end
1494+
1495+
describe 'Binary field' do
1496+
let(:klass) do
1497+
new_class do
1498+
field :image, :binary
1499+
end
1500+
end
1501+
1502+
let(:binary_value) { "\x00\x88\xFF".dup.force_encoding('ASCII-8BIT') }
1503+
1504+
it "encodes a string in base64-encoded format" do
1505+
obj = klass.create(image: binary_value)
1506+
1507+
expect(reload(obj).image).to eql(binary_value)
1508+
expect(raw_attributes(obj)[:image]).to eql(Base64.strict_encode64(binary_value))
1509+
end
1510+
end
14941511
end

spec/dynamoid/type_casting_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,30 @@ def settings.to_hash
653653
end
654654
end
655655

656+
describe 'Binary field' do
657+
let(:klass) do
658+
new_class do
659+
field :image, :binary
660+
end
661+
end
662+
663+
it 'converts to string with #to_s method' do
664+
value = double('object')
665+
allow(value).to receive(:to_s).and_return('string representation')
666+
667+
obj = klass.new(image: value)
668+
expect(obj.image).to eql('string representation')
669+
end
670+
671+
it 'dups a string' do
672+
value = 'foo'
673+
obj = klass.new(image: value)
674+
675+
expect(obj.image).to eql(value)
676+
expect(obj.image).not_to equal(value)
677+
end
678+
end
679+
656680
describe 'Serialized field' do
657681
end
658682

0 commit comments

Comments
 (0)