From fadc632b915c08de24260432b6a978229f6729e6 Mon Sep 17 00:00:00 2001 From: Ryan Jackson Date: Tue, 3 Sep 2024 22:44:55 -0700 Subject: [PATCH 1/6] Add default for deserializer values --- Gemfile.lock | 6 ++ ledger_sync.gemspec | 1 + lib/ledger_sync.rb | 1 + lib/ledger_sync/resource_attribute.rb | 18 +++-- .../resource_attribute/reference/many.rb | 9 ++- lib/ledger_sync/serialization/attribute.rb | 2 + .../serialization/deserializer_attribute.rb | 4 +- lib/ledger_sync/serialization/mixin.rb | 4 +- .../type/deserializer_references_many_type.rb | 3 +- lib/ledger_sync/type/reference_many.rb | 4 +- lib/ledger_sync/type/value_mixin.rb | 4 +- spec/deserializer_spec.rb | 65 ++++++++++++++++++- spec/support/resource_helpers.rb | 12 ++-- 13 files changed, 115 insertions(+), 18 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index ed568f4e..bd2fd904 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,6 +36,7 @@ GEM byebug (11.1.3) childprocess (4.1.0) climate_control (1.2.0) + coderay (1.1.3) colorize (1.1.0) concurrent-ruby (1.2.2) coveralls_reborn (0.27.0) @@ -115,6 +116,7 @@ GEM i18n (1.14.1) concurrent-ruby (~> 1.0) iniparse (1.5.0) + method_source (1.1.0) mini_portile2 (2.8.2) minitest (5.18.1) multipart-post (2.3.0) @@ -133,6 +135,9 @@ GEM racc pd_ruby (0.2.3) colorize + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) public_suffix (5.0.1) racc (1.7.1) rack (3.0.8) @@ -205,6 +210,7 @@ DEPENDENCIES factory_bot (~> 6.1.0) ledger_sync! overcommit (~> 0.57.0) + pry rake (~> 13.0) rspec (~> 3.2) rubocop (= 1.0.0) diff --git a/ledger_sync.gemspec b/ledger_sync.gemspec index 959dce96..2b17a5bc 100644 --- a/ledger_sync.gemspec +++ b/ledger_sync.gemspec @@ -38,6 +38,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency('coveralls_reborn') spec.add_development_dependency('factory_bot', '~> 6.1.0') spec.add_development_dependency('overcommit', '~> 0.57.0') + spec.add_development_dependency('pry') spec.add_development_dependency('rake', '~> 13.0') spec.add_development_dependency('rspec', '~> 3.2') spec.add_development_dependency('rubocop', '1.0.0') diff --git a/lib/ledger_sync.rb b/lib/ledger_sync.rb index 142eff8f..d630c61b 100644 --- a/lib/ledger_sync.rb +++ b/lib/ledger_sync.rb @@ -15,6 +15,7 @@ require 'faraday' require 'tempfile' require 'pd_ruby' +require 'pry' # Version require 'ledger_sync/version' diff --git a/lib/ledger_sync/resource_attribute.rb b/lib/ledger_sync/resource_attribute.rb index f9a75ce9..88778746 100644 --- a/lib/ledger_sync/resource_attribute.rb +++ b/lib/ledger_sync/resource_attribute.rb @@ -20,13 +20,15 @@ class ResourceAttribute :reference, :resource_class, :type, - :value + :value, + :default def initialize(args = {}) @name = args.fetch(:name).to_sym @resource_class = args.fetch(:resource_class) @type = args.fetch(:type) @value = args.fetch(:value, nil) + @default = args.fetch(:default, nil) # Default if nil value @type = type.new if type.respond_to?(:new) && !type.is_a?(Type::Value) @@ -34,7 +36,9 @@ def initialize(args = {}) end def assert_valid(args = {}) - value = args.fetch(:value) + # pd args + # pd default + value = args.fetch(:value, default) type.assert_valid(value: value) rescue Error::TypeError::ValueClassError @@ -46,7 +50,7 @@ def assert_valid(args = {}) end def cast(value) - type.cast(value: value) + cast_val(value) end # This is for ActiveModel::Dirty, since we define @attributes @@ -65,12 +69,16 @@ def valid_with?(value:) end def value=(val) - @value = type.cast(value: val) + @value = cast_val(val) end def will_change?(val) assert_valid(value: val) - value != type.cast(value: val) + value != cast_val(val) + end + + def cast_val(val) + type.cast(value: val, default: default) end end end diff --git a/lib/ledger_sync/resource_attribute/reference/many.rb b/lib/ledger_sync/resource_attribute/reference/many.rb index b4035837..499f061c 100644 --- a/lib/ledger_sync/resource_attribute/reference/many.rb +++ b/lib/ledger_sync/resource_attribute/reference/many.rb @@ -47,11 +47,16 @@ def self.included(base) end module ClassMethods - def references_many(name, to:) + def references_many(name, args = {}) + if name == :objs && args[:to] != LedgerSync::Ledgers::TestLedger::Subsidiary + pd name + pd args + raise "asdf" + end resource_attribute = ResourceAttribute::Reference::Many.new( name: name, resource_class: self, - to: to + **args ) resource_attributes.add resource_attribute _define_attribute_methods(name) diff --git a/lib/ledger_sync/serialization/attribute.rb b/lib/ledger_sync/serialization/attribute.rb index 6140770b..dc6a962e 100644 --- a/lib/ledger_sync/serialization/attribute.rb +++ b/lib/ledger_sync/serialization/attribute.rb @@ -6,6 +6,7 @@ module LedgerSync module Serialization class Attribute attr_reader :block, + :default, :hash_attribute, :if_method, :resource_attribute, @@ -14,6 +15,7 @@ class Attribute def initialize(args = {}) @block = args.fetch(:block, nil) + @default = args.fetch(:default, nil) @hash_attribute = args.fetch(:hash_attribute, nil).try(:to_s) @resource_attribute = args.fetch(:resource_attribute, nil).try(:to_s) @resource_class = args.fetch(:resource_class, nil) diff --git a/lib/ledger_sync/serialization/deserializer_attribute.rb b/lib/ledger_sync/serialization/deserializer_attribute.rb index 789c1e89..d8e174eb 100644 --- a/lib/ledger_sync/serialization/deserializer_attribute.rb +++ b/lib/ledger_sync/serialization/deserializer_attribute.rb @@ -31,9 +31,9 @@ def value_from_hash(hash:, resource:) value = hash.dig(*hash_attribute.split('.')) if type.is_a?(Type::DeserializerType) - type.cast(deserializer_attribute: self, resource: resource, value: value) + type.cast(deserializer_attribute: self, resource: resource, value: value, default: default) else - value = type.cast(value: value) + value = type.cast(value: value, default: default) return value if resource_attribute_dot_parts.count <= 1 nested_resource = resource.send(resource_attribute_dot_parts.first) diff --git a/lib/ledger_sync/serialization/mixin.rb b/lib/ledger_sync/serialization/mixin.rb index d7fc546c..6217be97 100644 --- a/lib/ledger_sync/serialization/mixin.rb +++ b/lib/ledger_sync/serialization/mixin.rb @@ -47,6 +47,7 @@ def _build_attribute(args) serializer = args.fetch(:serializer, nil) type = args.fetch(:type, nil) if_method = args.fetch(:if, nil) + default = args.fetch(:default, nil) attribute_class.new( block: block, @@ -55,7 +56,8 @@ def _build_attribute(args) resource_attribute: resource_attribute, resource_class: resource_class, serializer: serializer, - type: type + type: type, + default: default ) end end diff --git a/lib/ledger_sync/serialization/type/deserializer_references_many_type.rb b/lib/ledger_sync/serialization/type/deserializer_references_many_type.rb index 828d0f5a..15099d69 100644 --- a/lib/ledger_sync/serialization/type/deserializer_references_many_type.rb +++ b/lib/ledger_sync/serialization/type/deserializer_references_many_type.rb @@ -10,8 +10,9 @@ def cast_value(args = {}) deserializer_attribute = args.fetch(:deserializer_attribute) value = args.fetch(:value) resource = args.fetch(:resource) + default = args.fetch(:default, nil) - return if value.nil? + return default if value.nil? first_dot = deserializer_attribute.resource_attribute_dot_parts.first.to_sym nested_resource = resource.class.resource_attributes[first_dot].type.resource_class.new diff --git a/lib/ledger_sync/type/reference_many.rb b/lib/ledger_sync/type/reference_many.rb index 626f66a6..6c44b368 100644 --- a/lib/ledger_sync/type/reference_many.rb +++ b/lib/ledger_sync/type/reference_many.rb @@ -16,7 +16,8 @@ def initialize(resource_class:) def cast(args = {}) value = args.fetch(:value) - return if value.nil? + default = args.fetch(:default, nil) + return default if value.nil? many_array_class = LedgerSync::ResourceAttribute::Reference::Many::ManyArray @@ -34,6 +35,7 @@ def type def valid?(args = {}) value = args.fetch(:value) + # binding.pry return false unless value.is_a?(Array) return true if (resource_classes & value.map(&:class)).any? return true if value.is_a?(Array) && value.empty? diff --git a/lib/ledger_sync/type/value_mixin.rb b/lib/ledger_sync/type/value_mixin.rb index 937108b4..4bd5396a 100644 --- a/lib/ledger_sync/type/value_mixin.rb +++ b/lib/ledger_sync/type/value_mixin.rb @@ -9,6 +9,8 @@ def self.included(base) end def assert_valid(args = {}) + # pd args + args[:value] = args.fetch(:default, nil) if args.fetch(:value).nil? return if valid?(args) value = args.fetch(:value) @@ -22,7 +24,6 @@ def assert_valid(args = {}) # Do not override this method. Override private method cast_value def cast(args = {}) assert_valid(args) - return nil if args.fetch(:value).nil? cast_value(args) end @@ -36,6 +37,7 @@ def valid?(args = {}) # Override this method to handle different types of casting. def cast_value(args = {}) value = args.fetch(:value) + return args.fetch(:default, nil) if args.fetch(:value).nil? super(value) end diff --git a/spec/deserializer_spec.rb b/spec/deserializer_spec.rb index 6cf219b0..330c938e 100644 --- a/spec/deserializer_spec.rb +++ b/spec/deserializer_spec.rb @@ -11,6 +11,26 @@ end end + let(:references_many_deserializer_class) do + Class.new(LedgerSync::Deserializer) do + references_many :objs, deserializer: LedgerSync::Ledgers::TestLedger::Subsidiary::Deserializer + end + end + + let(:references_many_deserializer) do + references_many_deserializer_class.new + end + + let(:references_many_with_default_deserializer_class) do + Class.new(LedgerSync::Deserializer) do + references_many :objs, deserializer: LedgerSync::Ledgers::TestLedger::Subsidiary::Deserializer, default: [] + end + end + + let(:references_many_with_default_deserializer) do + references_many_with_default_deserializer_class.new + end + let(:custom_deserializer_class) do Class.new(LedgerSync::Deserializer) do attribute :foo, @@ -38,10 +58,40 @@ name phone_number type - ] + ], + references_many: [ + [:objs] + ], + reference_class: LedgerSync::Ledgers::TestLedger::Subsidiary ) end + # let(:custom_references_nany_resource_class) do + # Object.const_set( + # test_resource_class_name, + # Class.new(LedgerSync::Resource) do + # references_many :objs, to: LedgerSync::Ledgers::TestLedger::Subsidiary::Deserializer + # end + # ) + # end + + # let(:test_references_many_resource) do + # custom_references_nany_resource_class.new + # end + + # let(:custom_references_nany_with_default_resource_class) do + # Object.const_set( + # test_resource_class_name, + # Class.new(LedgerSync::Resource) do + # references_many :objs, to: LedgerSync::Ledgers::TestLedger::Subsidiary::Deserializer, default: [] + # end + # ) + # end + + # let(:test_references_many_with_default_resource) do + # custom_references_nany_resource_class.new + # end + it { expect(described_class).to respond_to(:attribute) } it { expect(described_class).to respond_to(:references_many) } it { expect(described_class).to respond_to(:references_one) } @@ -142,5 +192,18 @@ expect(dresource.foo).to eq('asdf') end end + + context 'with references_many' do + it do + dresource = references_many_deserializer.deserialize(hash: {}, resource: test_resource) + expect(dresource.objs).to eq(nil) + end + + it do + # binding.pry + dresource = references_many_with_default_deserializer.deserialize(hash: {}, resource: test_resource) + expect(dresource.objs).to eq([]) + end + end end end diff --git a/spec/support/resource_helpers.rb b/spec/support/resource_helpers.rb index b4a58c15..4b47bfc6 100644 --- a/spec/support/resource_helpers.rb +++ b/spec/support/resource_helpers.rb @@ -1,8 +1,12 @@ # frozen_string_literal: true module ResourceHelpers + def test_resource_class_name + "#{test_run_id}TestCustomResource#{test_resource_counter_increment!}" + end + def new_resource_class(args = {}) # rubocop:disable Metrics/CyclomaticComplexity - class_name = args.fetch(:name, "#{test_run_id}TestCustomResource#{test_resource_counter_increment!}") + class_name = args.fetch(:name, test_resource_class_name) remove_customer_resource_class(class_name: class_name) @@ -31,9 +35,9 @@ def new_resource_class(args = {}) # rubocop:disable Metrics/CyclomaticComplexity references_one a[0], **{ to: reference_class }.merge(a[1] || {}) end - references_many = args.fetch(:references_many, []) - references_many = Array(references_many) - references_many.each do |a| + references_manies = args.fetch(:references_many, []) + references_manies = Array(references_manies) + references_manies.each do |a| a = Array(a) references_many a[0], **{ to: reference_class }.merge(a[1] || {}) end From 7a84ae4bb1d71c49d023645168932f5dcd1aff22 Mon Sep 17 00:00:00 2001 From: Ryan Jackson Date: Tue, 3 Sep 2024 22:49:01 -0700 Subject: [PATCH 2/6] remove default from resource --- lib/ledger_sync/resource_attribute.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/ledger_sync/resource_attribute.rb b/lib/ledger_sync/resource_attribute.rb index 88778746..fb8b97cc 100644 --- a/lib/ledger_sync/resource_attribute.rb +++ b/lib/ledger_sync/resource_attribute.rb @@ -20,15 +20,13 @@ class ResourceAttribute :reference, :resource_class, :type, - :value, - :default + :value def initialize(args = {}) @name = args.fetch(:name).to_sym @resource_class = args.fetch(:resource_class) @type = args.fetch(:type) @value = args.fetch(:value, nil) - @default = args.fetch(:default, nil) # Default if nil value @type = type.new if type.respond_to?(:new) && !type.is_a?(Type::Value) @@ -36,9 +34,7 @@ def initialize(args = {}) end def assert_valid(args = {}) - # pd args - # pd default - value = args.fetch(:value, default) + value = args.fetch(:value) type.assert_valid(value: value) rescue Error::TypeError::ValueClassError From 278f63505ba348f59105f3b1e34650a72e466bb2 Mon Sep 17 00:00:00 2001 From: Ryan Jackson Date: Tue, 3 Sep 2024 22:50:12 -0700 Subject: [PATCH 3/6] Revert resource --- lib/ledger_sync/resource_attribute/reference/many.rb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/ledger_sync/resource_attribute/reference/many.rb b/lib/ledger_sync/resource_attribute/reference/many.rb index 499f061c..b4035837 100644 --- a/lib/ledger_sync/resource_attribute/reference/many.rb +++ b/lib/ledger_sync/resource_attribute/reference/many.rb @@ -47,16 +47,11 @@ def self.included(base) end module ClassMethods - def references_many(name, args = {}) - if name == :objs && args[:to] != LedgerSync::Ledgers::TestLedger::Subsidiary - pd name - pd args - raise "asdf" - end + def references_many(name, to:) resource_attribute = ResourceAttribute::Reference::Many.new( name: name, resource_class: self, - **args + to: to ) resource_attributes.add resource_attribute _define_attribute_methods(name) From 4fece84da593d567f4a487e5f9458716f55ea92e Mon Sep 17 00:00:00 2001 From: Ryan Jackson Date: Wed, 4 Sep 2024 21:08:00 -0700 Subject: [PATCH 4/6] Updates --- lib/ledger_sync/resource_attribute.rb | 2 +- lib/ledger_sync/type/reference_many.rb | 4 +++- lib/ledger_sync/type/value_mixin.rb | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/ledger_sync/resource_attribute.rb b/lib/ledger_sync/resource_attribute.rb index fb8b97cc..043332b2 100644 --- a/lib/ledger_sync/resource_attribute.rb +++ b/lib/ledger_sync/resource_attribute.rb @@ -74,7 +74,7 @@ def will_change?(val) end def cast_val(val) - type.cast(value: val, default: default) + type.cast(value: val) end end end diff --git a/lib/ledger_sync/type/reference_many.rb b/lib/ledger_sync/type/reference_many.rb index 6c44b368..c8fa197e 100644 --- a/lib/ledger_sync/type/reference_many.rb +++ b/lib/ledger_sync/type/reference_many.rb @@ -17,6 +17,8 @@ def initialize(resource_class:) def cast(args = {}) value = args.fetch(:value) default = args.fetch(:default, nil) + + pd default return default if value.nil? many_array_class = LedgerSync::ResourceAttribute::Reference::Many::ManyArray @@ -35,7 +37,7 @@ def type def valid?(args = {}) value = args.fetch(:value) - # binding.pry + return false unless value.is_a?(Array) return true if (resource_classes & value.map(&:class)).any? return true if value.is_a?(Array) && value.empty? diff --git a/lib/ledger_sync/type/value_mixin.rb b/lib/ledger_sync/type/value_mixin.rb index 4bd5396a..8a3aa49a 100644 --- a/lib/ledger_sync/type/value_mixin.rb +++ b/lib/ledger_sync/type/value_mixin.rb @@ -9,7 +9,6 @@ def self.included(base) end def assert_valid(args = {}) - # pd args args[:value] = args.fetch(:default, nil) if args.fetch(:value).nil? return if valid?(args) @@ -25,6 +24,8 @@ def assert_valid(args = {}) def cast(args = {}) assert_valid(args) + return args.fetch(:default, nil) if args.fetch(:value).nil? + cast_value(args) end @@ -37,7 +38,6 @@ def valid?(args = {}) # Override this method to handle different types of casting. def cast_value(args = {}) value = args.fetch(:value) - return args.fetch(:default, nil) if args.fetch(:value).nil? super(value) end From af226bb8c7f7a8756766c5a9beada0d1deb14664 Mon Sep 17 00:00:00 2001 From: Ryan Jackson Date: Wed, 4 Sep 2024 21:36:59 -0700 Subject: [PATCH 5/6] More changes --- lib/ledger_sync/resource_attribute.rb | 12 ++++++------ lib/ledger_sync/type/reference_many.rb | 2 +- lib/ledger_sync/type/value_mixin.rb | 11 +++++++++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/ledger_sync/resource_attribute.rb b/lib/ledger_sync/resource_attribute.rb index 043332b2..8e01b2e9 100644 --- a/lib/ledger_sync/resource_attribute.rb +++ b/lib/ledger_sync/resource_attribute.rb @@ -37,12 +37,12 @@ def assert_valid(args = {}) value = args.fetch(:value) type.assert_valid(value: value) - rescue Error::TypeError::ValueClassError - raise ResourceAttributeError::TypeError.new( - attribute: self, - resource_class: resource_class, - value: value - ) + # rescue Error::TypeError::ValueClassError + # raise ResourceAttributeError::TypeError.new( + # attribute: self, + # resource_class: resource_class, + # value: value + # ) end def cast(value) diff --git a/lib/ledger_sync/type/reference_many.rb b/lib/ledger_sync/type/reference_many.rb index c8fa197e..6af0cfca 100644 --- a/lib/ledger_sync/type/reference_many.rb +++ b/lib/ledger_sync/type/reference_many.rb @@ -36,7 +36,7 @@ def type end def valid?(args = {}) - value = args.fetch(:value) + value = args.fetch(:value, args.fetch(:default, nil)) return false unless value.is_a?(Array) return true if (resource_classes & value.map(&:class)).any? diff --git a/lib/ledger_sync/type/value_mixin.rb b/lib/ledger_sync/type/value_mixin.rb index 8a3aa49a..793c6728 100644 --- a/lib/ledger_sync/type/value_mixin.rb +++ b/lib/ledger_sync/type/value_mixin.rb @@ -9,7 +9,8 @@ def self.included(base) end def assert_valid(args = {}) - args[:value] = args.fetch(:default, nil) if args.fetch(:value).nil? + pd self + pd valid?(args) return if valid?(args) value = args.fetch(:value) @@ -43,10 +44,16 @@ def cast_value(args = {}) end def valid_class?(args = {}) - value = args.fetch(:value) + # value = args.fetch(:value) + value = args.fetch(:value, args.fetch(:default, nil)) + pd args + pd value + pd value.nil? return true if value.nil? + pd return true if valid_classes.select { |e| value.is_a?(e) }.any? + pd false end From 7ada93811aa35eacfb2ed883a90df3721b865a52 Mon Sep 17 00:00:00 2001 From: Ryan Jackson Date: Wed, 4 Sep 2024 21:50:51 -0700 Subject: [PATCH 6/6] Update --- lib/ledger_sync/serialization/type/deserializer_type.rb | 4 +++- lib/ledger_sync/type/reference_many.rb | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ledger_sync/serialization/type/deserializer_type.rb b/lib/ledger_sync/serialization/type/deserializer_type.rb index 8e298b70..7bbbfff1 100644 --- a/lib/ledger_sync/serialization/type/deserializer_type.rb +++ b/lib/ledger_sync/serialization/type/deserializer_type.rb @@ -16,12 +16,14 @@ def cast_value(args = {}) deserializer_attribute = args.fetch(:deserializer_attribute) resource = args.fetch(:resource) value = args.fetch(:value) + default = args.fetch(:default, nil) + + return default if value.nil? first_dot = deserializer_attribute.resource_attribute_dot_parts.first.to_sym nested_resource = resource.send(first_dot) nested_resource ||= resource.class.resource_attributes[first_dot].type.resource_class.new - return if value.nil? deserializer.new.deserialize(hash: value, resource: nested_resource) end diff --git a/lib/ledger_sync/type/reference_many.rb b/lib/ledger_sync/type/reference_many.rb index 6af0cfca..30a725c6 100644 --- a/lib/ledger_sync/type/reference_many.rb +++ b/lib/ledger_sync/type/reference_many.rb @@ -36,6 +36,7 @@ def type end def valid?(args = {}) + pd args value = args.fetch(:value, args.fetch(:default, nil)) return false unless value.is_a?(Array)