Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions lib/auth0/internal/types/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,22 @@ def initialize(values = {})
values = Utils.symbolize_keys(values.dup)

self.class.fields.each do |field_name, field|
value = values.delete(field.api_name.to_sym) || values.delete(field.api_name) || values.delete(field_name)
# key?/nil? checks keep an explicit `false`, and both keys are consumed so neither leaks into extra fields
value = nil
[field.api_name.to_sym, field_name].uniq.each do |key|
next unless values.key?(key)

field_value = value || (if field.literal?
field.value
elsif field.default
field.default
end)
candidate = values.delete(key)
value = candidate if value.nil?
end

field_value = if !value.nil?
value
elsif field.literal?
field.value
elsif !field.default.nil?
field.default
end

@data[field_name] = Utils.coerce(field.type, field_value)
end
Expand Down
42 changes: 42 additions & 0 deletions test/unit/internal/types/test_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ class ExampleWithDefaults < ExampleModel
field :type, String, default: "example"
end

class ExampleWithBooleans < Auth0::Internal::Types::Model
field :blocked, Auth0::Internal::Types::Boolean, optional: true
field :active, Auth0::Internal::Types::Boolean, optional: true, api_name: "isActive"
field :enabled, Auth0::Internal::Types::Boolean, optional: true, default: false
end

class ExampleChild < Auth0::Internal::Types::Model
field :value, String
end
Expand Down Expand Up @@ -110,6 +116,42 @@ class ExampleParent < Auth0::Internal::Types::Model
assert_equal 2014, example.year
refute_respond_to example, :yearOfRelease
end

it "preserves false values on construction and in to_h" do
example = ExampleWithBooleans.new(blocked: false, active: false)

assert_same false, example.blocked
assert_same false, example.active
assert_same false, example.to_h["blocked"]
assert_same false, example.to_h["isActive"]
end

it "preserves false values when loaded from JSON" do
example = ExampleWithBooleans.load('{"blocked":false,"isActive":false}')

assert_same false, example.blocked
assert_same false, example.active
end

it "keeps an explicit false instead of falling back to the default" do
assert_same false, ExampleWithBooleans.new.enabled
assert_same true, ExampleWithBooleans.new(enabled: true).enabled
assert_same false, ExampleWithBooleans.new(enabled: false).enabled
end

it "falls back to the field name when the api_name value is nil" do
example = ExampleWithBooleans.new(isActive: nil, active: true)

assert_same true, example.active
refute_respond_to example, :isActive
end

it "does not leak a consumed key into extra fields" do
example = ExampleWithBooleans.new(isActive: false, active: true)

assert_same false, example.active
refute ExampleWithBooleans.extra_fields.key?(:active)
end
end

describe "#inspect" do
Expand Down
Loading