Skip to content

Commit

Permalink
Treat all input which responds to to_h as Hash (#181)
Browse files Browse the repository at this point in the history
  • Loading branch information
ql authored Aug 17, 2024
1 parent 329cc21 commit 27d4a62
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 15 deletions.
17 changes: 11 additions & 6 deletions lib/store_model/types/one.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,17 @@ def type
# @param value [Object] a value to cast
#
# @return StoreModel::Model
def cast_value(value)
case value
when String then decode_and_initialize(value)
when Hash then model_instance(value)
when @model_klass, nil then value
else raise_cast_error(value)
def cast_value(value) # rubocop:disable Metrics/MethodLength
return nil if value.nil?

if value.is_a?(String)
decode_and_initialize(value)
elsif value.is_a?(@model_klass)
value
elsif value.respond_to?(:to_h) # Hash itself included
model_instance(value.to_h)
else
raise_cast_error(value)
end
rescue ActiveModel::UnknownAttributeError => e
handle_unknown_attribute(value, e)
Expand Down
12 changes: 7 additions & 5 deletions lib/store_model/types/one_polymorphic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ def type
# @param value [Object] a value to cast
#
# @return StoreModel::Model
def cast_value(value)
case value
when String then decode_and_initialize(value)
when Hash then extract_model_klass(value).new(value)
when nil then value
def cast_value(value) # rubocop:disable Metrics/MethodLength
return nil if value.nil?

if value.is_a?(String)
decode_and_initialize(value)
elsif value.respond_to?(:to_h) # Hash itself included
extract_model_klass(value).new(value.to_h)
else
raise_cast_error(value) unless value.class.ancestors.include?(StoreModel::Model)

Expand Down
33 changes: 33 additions & 0 deletions spec/store_model/model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,39 @@

it("assigns attributes") { is_expected.to have_attributes(attributes) }
end

context "when hash-like other class passed" do
subject do
class Product < ActiveRecord::Base
attribute :configuration, Configuration.to_type
end

Product.new(configuration: attributes)
end

let(:attributes) do
class NotHash
def initialize(attrs)
@attrs = attrs
end

def to_h
@attrs
end
end
NotHash.new(
color: "red",
model: nil,
active: false,
disabled_at: Time.new(2019, 2, 10, 12).utc,
encrypted_serial: "111-222"
)
end

it("assigns attributes") do
expect(subject.configuration).to have_attributes(attributes.to_h)
end
end
end

describe "#fetch" do
Expand Down
4 changes: 2 additions & 2 deletions spec/store_model/types/one_polymorphic_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@
end

context "when instance of illegal class is passed" do
let(:value) { [] }
let(:value) { 1 }

it "raises exception" do
expect { type.cast_value(value) }.to raise_error(
StoreModel::Types::CastError,
"failed casting [], only String, Hash or instances which " \
"failed casting 1, only String, Hash or instances which " \
"implement StoreModel::Model are allowed"
)
end
Expand Down
4 changes: 2 additions & 2 deletions spec/store_model/types/one_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@
end

context "when instance of illegal class is passed" do
let(:value) { [] }
let(:value) { 1 }

it "raises exception" do
expect { type.cast_value(value) }.to raise_error(
StoreModel::Types::CastError,
"failed casting [], only String, Hash or Configuration instances are allowed"
"failed casting 1, only String, Hash or Configuration instances are allowed"
)
end
end
Expand Down

0 comments on commit 27d4a62

Please sign in to comment.