I experienced a major headache when upgrading to Rails 5 to continue encoding my BigDecimal values as decimals instead of Strings ( I ended up pulling in Oj gem and setting Oj.default_options = { bigdecimal_as_decimal: true } ).
I have been through Do NOT return BigDecimal as string in JSON - breaks DynamoDB support · Issue #25017 · rails/rails · GitHub countless times, and I always found the tone so very hostile. Our organization understands the risks involved,if we could rewrite our API to use the default then we would do that in a heartbeat, but we have legacy APIs to maintain and can’t just change the type of attributes in our responses. It just feels like Rail’s stance on this is overly-opinionated and is preventing the programmer from making their own choices about how their app behaves.
I’ve run into this a few times with new applications. It strings extra because I “tried to the the right thing”, but ended up having to bypass the default serializer. I declared decimals with the required precision and scale in the database and on the client side, but Rails ate my number.
From the reason given on the issue you link to:
in practice all clients would parse that into a float/double data type
In my case this was not true. The client library (iOS/Swift JSONDecoder) expects Decimal as a number and won’t accept a string.
Thank you for the response. We ended up overriding as_json in BigDecimal as you describe:
class BigDecimal
def as_json
to_d
end
end
This seems to give us exactly what we need without dropping precision.
I think some of my frustration can be summarized in this issue https://github.com/rails/rails/issues/37604. Looking through the Rails changelog, I had no idea that all attributes would be forced back through as_json, since the referenced PR only mentions timestamps. Luckily we had regression tests that caught this, but it seems like there was not consideration for the broad impact that the change would have, it would have been great if this information could have been included somewhere in the changelog as suggested in the linked issue above.
Of course I understand that it is impossible to account for all changes and the impact they could potentially have, and I applaud the Rails team for doing what you guys do .
This seems like a case where documentation in “the right place” might have helped. @PhilCoggins when you first tried to solve this issue, where was the first place you looked?
By overriding as_json in BigDecimal, when we call render json: { success: true, message: message, data: data }, it still render decimal as string in json.