From 3a178e901e559a155d088cfb0522972625eedd6c Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Thu, 27 Mar 2025 10:41:35 -0500 Subject: [PATCH] Add Filter ActiveModel Validation Errors as a Rails TIL --- README.md | 3 +- .../filter-active-model-validation-errors.md | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 rails/filter-active-model-validation-errors.md diff --git a/README.md b/README.md index 71fedc7..d5ee82d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186). -_1628 TILs and counting..._ +_1629 TILs and counting..._ See some of the other learning resources I work on: - [Ruby Operator Lookup](https://www.visualmode.dev/ruby-operators) @@ -1035,6 +1035,7 @@ If you've learned something here, support my efforts writing daily TILs by - [Ensure A Rake Task Cannot Write Data](rails/ensure-a-rake-task-cannot-write-data.md) - [Ensure Migrations Use The Latest Schema](rails/ensure-migrations-use-the-latest-schema.md) - [Ensure Record Saved With after_commit Callback](rails/ensure-record-saved-with-after-commit-callback.md) +- [Filter ActiveModel Validation Errors](rails/filter-active-model-validation-errors.md) - [Filter ActiveStorage Blobs To Only Images](rails/filter-active-storage-blobs-to-only-images.md) - [Find Or Create A Record With FactoryBot](rails/find-or-create-a-record-with-factory-bot.md) - [Find Records With Multiple Associated Records](rails/find-records-with-multiple-associated-records.md) diff --git a/rails/filter-active-model-validation-errors.md b/rails/filter-active-model-validation-errors.md new file mode 100644 index 0000000..180e5d3 --- /dev/null +++ b/rails/filter-active-model-validation-errors.md @@ -0,0 +1,43 @@ +# Filter ActiveModel Validation Errors + +Now that `ActiveModel` has a custom `Errors` class (as of Rails 6.1) instead of +a hash, we get some useful functionality. Namely, we get a [`#where` +method](https://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-where) +that allows us to filter errors based on the attribute name, type of +validation, and even properties of that validation. + +Here I have created a new `Book` without any attributes. All of its validations +are going to fail and we are going to have an `ActiveModel::Errors` object +attached to it with several errors. + +```ruby +> book = Book.new +=> +# book.valid? +=> false +> book.errors +=> #:required, :if=>#}>, #, #3}>, #, #]> +``` + +Let's say I want to check for a specific validation error. I can use `#where` +to filter down by attribute name (e.g. `:title`). I can filter even further by +including the validation type as well (e.g. `:too_short`). + +```ruby +> book.errors.where(:title) +=> +[#, + #3}>] +> book.errors.where(:title, :too_short) +=> [#3}>] +> book.errors.where(:title, :too_short).first.message +=> "is too short (minimum is 3 characters)" +> book.errors.where(:title, :too_short).first.full_message +=> "Title is too short (minimum is 3 characters)" +``` + +This filtering could be used as part of conditional checks for what flash +message gets displayed to the user or even what route/view gets rendered in +response to the error.