Skip to content

Commit

Permalink
Fix bug coercing boolean strings
Browse files Browse the repository at this point in the history
- fields with a type of T::Boolean were getting caught in the T.any conditional block and failing to activate the BooleanCoercer class. I moved the `select_coercer_by` call up to the serializer so we can handle the case where the type alias matches a coercer, falling back to checking each of the individual types in the alias if no top-level coercer is found.
  • Loading branch information
jeremyshearer committed Sep 4, 2024
1 parent 8446c13 commit e484f5e
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 7 deletions.
16 changes: 9 additions & 7 deletions lib/typed/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,19 @@ def serialize(struct)
def deserialize_from_creation_params(creation_params)
results = schema.fields.map do |field|
value = creation_params.fetch(field.name, nil)
coercer = Coercion::CoercerRegistry.instance.select_coercer_by(type: field.type)

if value.nil? && !field.default.nil?
Success.new(Validations::ValidatedValue.new(name: field.name, value: field.default))
elsif value.nil? || field.works_with?(value)
field.validate(value)
elsif !coercer.nil?
result = coercer.new.coerce(type: field.type, value:)
if result.success?
field.validate(result.payload)
else
Failure.new(Validations::ValidationError.new(result.error.message))
end
elsif field.type.class <= T::Types::Union
errors = []
validated_value = T.let(nil, T.nilable(Typed::Result[Typed::Validations::ValidatedValue, Typed::Validations::ValidationError]))
Expand All @@ -60,13 +68,7 @@ def deserialize_from_creation_params(creation_params)

validated_value.nil? ? Failure.new(Validations::ValidationError.new(errors.map(&:message).join(", "))) : validated_value
else
coercion_result = Coercion.coerce(type: field.type, value:)

if coercion_result.success?
field.validate(coercion_result.payload)
else
Failure.new(Validations::ValidationError.new(coercion_result.error.message))
end
Failure.new(Validations::ValidationError.new("Coercer not found for type #{field.type}."))
end
end

Expand Down
14 changes: 14 additions & 0 deletions test/typed/hash_serializer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ def test_with_boolean_it_can_deserialize
assert_payload(NEW_YORK_CITY, result)
end

def test_with_boolean_string_false_it_can_deserialize
result = Typed::HashSerializer.new(schema: Typed::Schema.from_struct(City)).deserialize({name: "New York", capital: "false"})

assert_success(result)
assert_payload(NEW_YORK_CITY, result)
end

def test_with_boolean_string_true_it_can_deserialize
result = Typed::HashSerializer.new(schema: Typed::Schema.from_struct(City)).deserialize({name: "DC", capital: "true"})

assert_success(result)
assert_payload(DC_CITY, result)
end

def test_with_array_it_can_deserialize
result = Typed::HashSerializer.new(schema: Typed::Schema.from_struct(Country)).deserialize({name: "US", cities: [NEW_YORK_CITY, DC_CITY], national_items: {bird: "bald eagle", anthem: "The Star-Spangled Banner"}})

Expand Down
14 changes: 14 additions & 0 deletions test/typed/json_serializer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ def test_with_boolean_it_can_deserialize
assert_payload(NEW_YORK_CITY, result)
end

def test_with_boolean_string_false_it_can_deserialize
result = Typed::JSONSerializer.new(schema: Typed::Schema.from_struct(City)).deserialize('{"name":"New York","capital":"false"}')

assert_success(result)
assert_payload(NEW_YORK_CITY, result)
end

def test_with_boolean_string_true_it_can_deserialize
result = Typed::JSONSerializer.new(schema: Typed::Schema.from_struct(City)).deserialize('{"name":"DC","capital":"true"}')

assert_success(result)
assert_payload(DC_CITY, result)
end

def test_with_array_it_can_deep_deserialize
result = Typed::JSONSerializer.new(schema: Typed::Schema.from_struct(Country)).deserialize('{"name":"US","cities":[{"name":"New York","capital":false},{"name":"DC","capital":true}],"national_items":{"bird":"bald eagle","anthem":"The Star-Spangled Banner"}}')

Expand Down

0 comments on commit e484f5e

Please sign in to comment.