From f2bc707c48cf9b1411314565348539f83fbfa762 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Tue, 14 Jan 2025 00:13:20 +0200 Subject: [PATCH 1/3] Prefer .dynamoid_dump over #dynamoid_dump for custom type field --- lib/dynamoid/dumping.rb | 6 +++--- spec/dynamoid/dumping_spec.rb | 15 +++++++++++++++ spec/fixtures/dumping.rb | 29 +++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/lib/dynamoid/dumping.rb b/lib/dynamoid/dumping.rb index 36e12bd5..50619e1b 100644 --- a/lib/dynamoid/dumping.rb +++ b/lib/dynamoid/dumping.rb @@ -323,10 +323,10 @@ class CustomTypeDumper < Base def process(value) field_class = @options[:type] - if value.respond_to?(:dynamoid_dump) - value.dynamoid_dump - elsif field_class.respond_to?(:dynamoid_dump) + if field_class.respond_to?(:dynamoid_dump) field_class.dynamoid_dump(value) + elsif value.respond_to?(:dynamoid_dump) + value.dynamoid_dump else raise ArgumentError, "Neither #{field_class} nor #{value} supports serialization for Dynamoid." end diff --git a/spec/dynamoid/dumping_spec.rb b/spec/dynamoid/dumping_spec.rb index 579c49da..2b238e7d 100644 --- a/spec/dynamoid/dumping_spec.rb +++ b/spec/dynamoid/dumping_spec.rb @@ -1449,6 +1449,21 @@ def self.load(str) end end + context 'Custom type with adapter interface provided' do + let(:klass) do + new_class do |_options| + field :user, DumpingSpecs::UserWithAdapterInterface + end + end + + it "prefers adapter's .dynamoid_dump method over #dynamoid_dump" do + user = DumpingSpecs::UserWithAdapterInterface.new('John') + obj = klass.create(user: user) + + expect(raw_attributes(obj)[:user]).to eql('John (dumped with .dynamoid_dump)') + end + end + context 'DynamoDB type specified' do let(:klass) do new_class do diff --git a/spec/fixtures/dumping.rb b/spec/fixtures/dumping.rb index df95a9c4..252bc588 100644 --- a/spec/fixtures/dumping.rb +++ b/spec/fixtures/dumping.rb @@ -25,6 +25,35 @@ def self.dynamoid_load(string) end end + # implements both #dynamoid_dump and .dynamoid_dump methods + class UserWithAdapterInterface + attr_accessor :name + + def initialize(name) + self.name = name + end + + def dynamoid_dump + name + ' (dumped with #dynamoid_dump)' + end + + def eql?(other) + name == other.name + end + + def hash + name.hash + end + + def self.dynamoid_dump(user) + user.name + ' (dumped with .dynamoid_dump)' + end + + def self.dynamoid_load(string) + new(string.to_s) + end + end + # doesn't implement #dynamoid_dump/#dynamoid_load methods so requires an adapter class UserValue attr_accessor :name From 33f1593d6784ba24b91e83fe9aa946dd08f5dca0 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Tue, 14 Jan 2025 00:57:45 +0200 Subject: [PATCH 2/3] Fix specs for dumping field of custom type --- spec/fixtures/dumping.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/fixtures/dumping.rb b/spec/fixtures/dumping.rb index 252bc588..5cb41325 100644 --- a/spec/fixtures/dumping.rb +++ b/spec/fixtures/dumping.rb @@ -34,7 +34,7 @@ def initialize(name) end def dynamoid_dump - name + ' (dumped with #dynamoid_dump)' + "#{name} (dumped with #dynamoid_dump)" end def eql?(other) @@ -46,7 +46,7 @@ def hash end def self.dynamoid_dump(user) - user.name + ' (dumped with .dynamoid_dump)' + "#{user.name} (dumped with .dynamoid_dump)" end def self.dynamoid_load(string) @@ -77,7 +77,7 @@ def self.dynamoid_dump(user) end def self.dynamoid_load(string) - User.new(string.to_s) + UserValue.new(string.to_s) end end @@ -87,8 +87,8 @@ def self.dynamoid_dump(user) end def self.dynamoid_load(array) - array = array.name.split if array.is_a?(User) - User.new(array.join(' ')) + array = array.name.split if array.is_a?(UserValue) + UserValue.new(array.join(' ')) end def self.dynamoid_field_type From 85111cf856c508299fd1019bc0f98da29118f901 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Tue, 14 Jan 2025 01:09:08 +0200 Subject: [PATCH 3/3] Run Rubocop on Ruby 3.4 on CI --- .github/workflows/style.yml | 2 +- .rubocop_thread_safety.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index c9059d4b..0478f11d 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -23,7 +23,7 @@ jobs: bundler: - latest ruby: - - "3.3" + - "3.4" runs-on: ubuntu-latest env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/style.gemfile diff --git a/.rubocop_thread_safety.yml b/.rubocop_thread_safety.yml index 93f386ff..8cf726fa 100644 --- a/.rubocop_thread_safety.yml +++ b/.rubocop_thread_safety.yml @@ -1,6 +1,6 @@ # It would be good to make the gem more thread safe, but at the moment it is not entirely. # TODO: Comment out the following to see code needing to be refactored for thread safety! -ThreadSafety/ClassAndModuleAttributes: - Enabled: false ThreadSafety/ClassInstanceVariable: Enabled: false +ThreadSafety/ClassAndModuleAttributes: + Enabled: false