From 1b2e41aef47be97c8b6169d9261ee9e42f19afcc Mon Sep 17 00:00:00 2001 From: Giallombardo Nathan Date: Tue, 28 May 2024 09:31:10 +0000 Subject: [PATCH] add Hash types --- lib/couchbase-orm/types.rb | 3 +++ lib/couchbase-orm/types/hash.rb | 21 +++++++++++++++++++++ lib/couchbase-orm/types/nested.rb | 4 ++-- spec/type_spec.rb | 27 +++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 lib/couchbase-orm/types/hash.rb diff --git a/lib/couchbase-orm/types.rb b/lib/couchbase-orm/types.rb index f88aa146..c97db5ad 100644 --- a/lib/couchbase-orm/types.rb +++ b/lib/couchbase-orm/types.rb @@ -4,6 +4,7 @@ require "couchbase-orm/types/array" require "couchbase-orm/types/nested" require "couchbase-orm/types/encrypted" +require "couchbase-orm/types/hash" if ActiveModel::VERSION::MAJOR <= 6 # In Rails 5, the type system cannot allow overriding the default types @@ -18,3 +19,5 @@ ActiveModel::Type.register(:array, CouchbaseOrm::Types::Array) ActiveModel::Type.register(:nested, CouchbaseOrm::Types::Nested) ActiveModel::Type.register(:encrypted, CouchbaseOrm::Types::Encrypted) +ActiveModel::Type.register(:hash, CouchbaseOrm::Types::Hash) + diff --git a/lib/couchbase-orm/types/hash.rb b/lib/couchbase-orm/types/hash.rb new file mode 100644 index 00000000..9b0ee67e --- /dev/null +++ b/lib/couchbase-orm/types/hash.rb @@ -0,0 +1,21 @@ +module CouchbaseOrm + module Types + class Hash < ActiveModel::Type::Value + def cast(value) + return nil if value.nil? + return value if value.is_a?(ActiveSupport::HashWithIndifferentAccess) + return value.with_indifferent_access if value.is_a?(::Hash) + + raise ArgumentError, "Hash: #{value.inspect} (#{value.class}) is not supported for cast" + end + + def serialize(value) + return nil if value.nil? + return value.as_json if value.is_a?(ActiveSupport::HashWithIndifferentAccess) + return value.with_indifferent_access.as_json if value.is_a?(::Hash) + + raise ArgumentError, "Hash: #{value.inspect} (#{value.class}) is not supported for serialize" + end + end + end +end diff --git a/lib/couchbase-orm/types/nested.rb b/lib/couchbase-orm/types/nested.rb index 4e332e34..8896d088 100644 --- a/lib/couchbase-orm/types/nested.rb +++ b/lib/couchbase-orm/types/nested.rb @@ -26,14 +26,14 @@ def initialize(type:) def cast(value) return nil if value.nil? return value if value.is_a?(@model_class) - return @model_class.new(value) if value.is_a?(Hash) + return @model_class.new(value) if value.is_a?(::Hash) raise ArgumentError, "Nested: #{value.inspect} (#{value.class}) is not supported for cast" end def serialize(value) return nil if value.nil? - value = @model_class.new(value) if value.is_a?(Hash) + value = @model_class.new(value) if value.is_a?(::Hash) return value.send(:serialized_attributes) if value.is_a?(@model_class) raise ArgumentError, "Nested: #{value.inspect} (#{value.class}) is not supported for serialization" diff --git a/spec/type_spec.rb b/spec/type_spec.rb index 6cf22909..753507f1 100644 --- a/spec/type_spec.rb +++ b/spec/type_spec.rb @@ -41,6 +41,7 @@ class N1qlTypeTest < CouchbaseOrm::Base attribute :some_time, :timestamp attribute :precision3_time, :datetime3decimal attribute :active, :boolean + attribute :address, :hash index_n1ql :name, validate: false index_n1ql :age, validate: false @@ -315,3 +316,29 @@ class N1qlTypeTest < CouchbaseOrm::Base end end end + +describe CouchbaseOrm::Types::Hash do + it 'should cast Hash to HashWithIndifferentAccess' do + expect(CouchbaseOrm::Types::Hash.new.cast({'a' => 1}).class).to be(HashWithIndifferentAccess) + end + + it 'should cast nil to nil' do + expect(CouchbaseOrm::Types::Hash.new.cast(nil)).to be_nil + end + + it 'should cast HashWithIndifferentAccess to HashWithIndifferentAccess' do + expect(CouchbaseOrm::Types::Hash.new.cast({'a' => 1}.with_indifferent_access).class).to be(HashWithIndifferentAccess) + end + + it 'should serialize Hash as json hash' do + expect(CouchbaseOrm::Types::Hash.new.serialize({'a' => 1}).class).to be(Hash) + end + + it 'should serialize HashWithIndifferentAccess as json hash' do + expect(CouchbaseOrm::Types::Hash.new.serialize({'a' => 1}.with_indifferent_access).class).to be(Hash) + end + + it 'should serialize nil as nil' do + expect(CouchbaseOrm::Types::Hash.new.serialize(nil)).to be_nil + end +end