Skip to content

Instantly share code, notes, and snippets.

@LyricL-Gitster
Last active May 21, 2024 23:36
Show Gist options
  • Save LyricL-Gitster/cb87fb4cad037068657bd1b4412bb907 to your computer and use it in GitHub Desktop.
Save LyricL-Gitster/cb87fb4cad037068657bd1b4412bb907 to your computer and use it in GitHub Desktop.
attr_json Polymorphic validation bug
class BowlerJSON
include AttrJson::Model
attr_json_config bad_cast: :as_nil, unknown_key: :strip
attr_json 'name', :string
validates :name, inclusion: { in: [nil, 'Dude', 'Walter', 'Donnie Who Loved Bowling'] }
end
class LeagueJSON
include AttrJson::Model
attr_json_config bad_cast: :as_nil, unknown_key: :strip
ATTR_JSON_POLYMORPHIC_TYPE_KEY = "__internal_type__".freeze
attr_json :bowlers, AttrJson::Type::PolymorphicModel.new(BowlerJSON, self, type_key: ATTR_JSON_POLYMORPHIC_TYPE_KEY), array: true
attr_json :the_dudes, BowlerJSON.to_type, default: -> { BowlerJSON.new }, array: true
end
class League < ApplicationRecord
include AttrJson::Record
attr_json :value, LeagueJSON.to_type, default: LeagueJSON.new
end
# TESTS
good_league = League.new(
value: {
the_dudes: [
{name: 'Dude'}
]
}
)
good_league.value.the_dudes[0].name # Dude (abides)
good_league.valid? # true (BINGO!)
good_league.value.valid? # true (BINGO!)
good_league.value.the_dudes[0].valid? # true (BINGO!)
bad_league1 = League.new(
value: {
the_dudes: [
{name: 'Lyric'}
]
}
)
bad_league1.value.the_dudes[0].name # Lyric (not 'Dude')
bad_league1.valid? # false (BINGO!)
bad_league1.value.valid? # false (BINGO!)
bad_league1.value.the_dudes[0].valid? # false (BINGO!)
bad_league2 = League.new(
value: {
bowlers: [
{name: 'Lyric', __internal_type__: 'BowlerJSON'}
]
}
)
bad_league2.value.bowlers[0].name # Lyric (not 'Dude')
bad_league2.valid? # true (should be false)
bad_league2.value.valid? # true (should be false)
bad_league2.value.bowlers[0].valid? # false (BINGO!)
bad_league3 = League.new(
value: {
bowlers: [
{name: 'Dude', __internal_type__: 'BowlerJSON'},
{the_dudes: [{name: 'Lyric'}], __internal_type__: 'LeagueJSON'}
]
}
)
bad_league3.value.bowlers[0].name # Dude (abides)
bad_league3.value.bowlers[1].the_dudes[0].name # Lyric (not 'Dude')
bad_league3.valid? # true (should be false)
bad_league3.value.valid? # true (should be false)
bad_league3.value.bowlers[0].valid? # true (BINGO!)
bad_league3.value.bowlers[1].valid? # false (BINGO!)
@LyricL-Gitster
Copy link
Author

LyricL-Gitster commented May 21, 2024

good_league and bad_league1 seem to behave as expected while bad_league2 and bad_league3 - which set the values on the PolymorphicModel - do not validate the nested object unless specifically called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment