Skip to content

Commit 4902a5c

Browse files
authored
Merge pull request #849 from Dynamoid/ak/fix-dumping-of-custom-type-that-mixes-adapter-interface
Fix dumping of custom type that mixes adapter interface
2 parents 30ab6b6 + 85111cf commit 4902a5c

File tree

5 files changed

+53
-9
lines changed

5 files changed

+53
-9
lines changed

.github/workflows/style.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
bundler:
2424
- latest
2525
ruby:
26-
- "3.3"
26+
- "3.4"
2727
runs-on: ubuntu-latest
2828
env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
2929
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/style.gemfile

.rubocop_thread_safety.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# It would be good to make the gem more thread safe, but at the moment it is not entirely.
22
# TODO: Comment out the following to see code needing to be refactored for thread safety!
3-
ThreadSafety/ClassAndModuleAttributes:
4-
Enabled: false
53
ThreadSafety/ClassInstanceVariable:
64
Enabled: false
5+
ThreadSafety/ClassAndModuleAttributes:
6+
Enabled: false

lib/dynamoid/dumping.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,10 @@ class CustomTypeDumper < Base
323323
def process(value)
324324
field_class = @options[:type]
325325

326-
if value.respond_to?(:dynamoid_dump)
327-
value.dynamoid_dump
328-
elsif field_class.respond_to?(:dynamoid_dump)
326+
if field_class.respond_to?(:dynamoid_dump)
329327
field_class.dynamoid_dump(value)
328+
elsif value.respond_to?(:dynamoid_dump)
329+
value.dynamoid_dump
330330
else
331331
raise ArgumentError, "Neither #{field_class} nor #{value} supports serialization for Dynamoid."
332332
end

spec/dynamoid/dumping_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,21 @@ def self.load(str)
14491449
end
14501450
end
14511451

1452+
context 'Custom type with adapter interface provided' do
1453+
let(:klass) do
1454+
new_class do |_options|
1455+
field :user, DumpingSpecs::UserWithAdapterInterface
1456+
end
1457+
end
1458+
1459+
it "prefers adapter's .dynamoid_dump method over #dynamoid_dump" do
1460+
user = DumpingSpecs::UserWithAdapterInterface.new('John')
1461+
obj = klass.create(user: user)
1462+
1463+
expect(raw_attributes(obj)[:user]).to eql('John (dumped with .dynamoid_dump)')
1464+
end
1465+
end
1466+
14521467
context 'DynamoDB type specified' do
14531468
let(:klass) do
14541469
new_class do

spec/fixtures/dumping.rb

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,35 @@ def self.dynamoid_load(string)
2525
end
2626
end
2727

28+
# implements both #dynamoid_dump and .dynamoid_dump methods
29+
class UserWithAdapterInterface
30+
attr_accessor :name
31+
32+
def initialize(name)
33+
self.name = name
34+
end
35+
36+
def dynamoid_dump
37+
"#{name} (dumped with #dynamoid_dump)"
38+
end
39+
40+
def eql?(other)
41+
name == other.name
42+
end
43+
44+
def hash
45+
name.hash
46+
end
47+
48+
def self.dynamoid_dump(user)
49+
"#{user.name} (dumped with .dynamoid_dump)"
50+
end
51+
52+
def self.dynamoid_load(string)
53+
new(string.to_s)
54+
end
55+
end
56+
2857
# doesn't implement #dynamoid_dump/#dynamoid_load methods so requires an adapter
2958
class UserValue
3059
attr_accessor :name
@@ -48,7 +77,7 @@ def self.dynamoid_dump(user)
4877
end
4978

5079
def self.dynamoid_load(string)
51-
User.new(string.to_s)
80+
UserValue.new(string.to_s)
5281
end
5382
end
5483

@@ -58,8 +87,8 @@ def self.dynamoid_dump(user)
5887
end
5988

6089
def self.dynamoid_load(array)
61-
array = array.name.split if array.is_a?(User)
62-
User.new(array.join(' '))
90+
array = array.name.split if array.is_a?(UserValue)
91+
UserValue.new(array.join(' '))
6392
end
6493

6594
def self.dynamoid_field_type

0 commit comments

Comments
 (0)