From f83b5003de8a87f71e1e342888390a8330288de0 Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Wed, 12 Aug 2026 08:32:38 -0500 Subject: [PATCH] Add Handle Bad Numerical Amounts With BigDecimal as a Rails TIL --- README.md | 3 +- ...-bad-numerical-amounts-with-big-decimal.md | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 rails/handle-bad-numerical-amounts-with-big-decimal.md diff --git a/README.md b/README.md index 34b9335..d7efd7c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ working across different projects via [VisualMode](https://www.visualmode.dev/). For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter). -_1859 TILs and counting..._ +_1860 TILs and counting..._ See some of the other learning resources I work on: @@ -1223,6 +1223,7 @@ If you've learned something here, support my efforts writing daily TILs by - [Get The Current Time](rails/get-the-current-time.md) - [Grab A Random Record From The Database](rails/grab-a-random-record-from-the-database.md) - [Halt ActionMailer Delivery With Callback](rails/halt-action-mailer-delivery-with-callback.md) +- [Handle Bad Numerical Amounts With BigDecimal](rails/handle-bad-numerical-amounts-with-big-decimal.md) - [Handle Named Arguments In A Rake Task](rails/handle-named-arguments-in-a-rake-task.md) - [Hash Slicing](rails/hash-slicing.md) - [Ignore Poltergeist JavaScript Errors](rails/ignore-poltergeist-javascript-errors.md) diff --git a/rails/handle-bad-numerical-amounts-with-big-decimal.md b/rails/handle-bad-numerical-amounts-with-big-decimal.md new file mode 100644 index 0000000..9b319af --- /dev/null +++ b/rails/handle-bad-numerical-amounts-with-big-decimal.md @@ -0,0 +1,38 @@ +# Handle Bad Numerical Amounts With BigDecimal + +I'm working on a payment page with a backing Rails controller. The user can +select between their full balance or some partial payment amount. Because this +form accepts an arbitrary value for the amount, I need to do some server-side +validation. + +While I could parse the `amount` value and handle the exception that gets raised +on bad numerical values, I'd rather have bad values coerce to `nil` and let +downstream validations handle it from there. + +[`BigDecimal`](https://docs.ruby-lang.org/en/master/BigDecimal.html) can help +here with the support of its `exception` option. + +```ruby +> BigDecimal('123', exception: false) +=> 0.123e3 +> BigDecimal('taco', exception: false) +=> nil +``` + +Maybe that parsing logic ends up looking something like this: + +```ruby +def parse_payment_amount(value, current_balance) + amount = BigDecimal(value, exception: false) + + if amount.present? && amount == current_balance + [:full_balance, amount] + else + [:other, amount] + end +end +``` + +I return tuples where you either get a verified `:full_balance` amount or you +get some `:other` amount. The other amount could be `nil` which would trigger a +downstream validation.