Hi, I’m using ActiveModel::Attributes and ActiveModel::Type for json data from some API systems. And got into trouble by casting of ActiveModel::Type::String
here is the rails code.
activemodel/lib/active_model/type/string.rb
private
def cast_value(value)
case value
when ::String then ::String.new(value)
when true then "t"
when false then "f"
else value.to_s
end
end
and here is my sample code
class Test
include ActiveModel::Model
include ActiveModel::Attributes
attribute :flag, :string
end
test = Test.new(flag: false)
test.flag
=> "f"
My expectation is that when I set boolean false to the string attribute :flag, it will return "false" as string value. This is because simple to_s method does like below.
false.to_s
=> "false"
what’s the reason or any background to cast "f" instead of "false"?
I would like to propose to change this casting to be same as to_s and returns "false".
("true" too.)
Out of curiosity, what does the data from your API look like? Could it be a boolean or string? If so, you may want to consider using a JSON type so you can correctly serialize and deserialize data of different types.
The API(which is not ours) provides/accept string “true/false”. I cannot change the request/response data type itself. So my attribute type is also string.
The background of my question is that I’m working on version up of legacy Rails, including a migration from old gem Virtus to ActiveModel::Attributes.
Then Rails code set boolean true/false to a model(created by Virtus) in a business logic, Virtus casts a boolean value to string as it is. true becomes “true” and false becomes “false”. This behavior also make sense for me.
but after migrating to ActiveModel::Attributes, boolean true/false became “t” and “f” which caused errors.
As a workaround, I created custom type of ActiveModel::Type for API connection to cast “true”/“false”.