Speakerline
Speakers
Proposals
Events
Tags
Edit a proposal
Adam Cuppy
Ahmed Omran
Alan Ridlehoover
Amit Zur
Andrew Mason
Andrew Nesbitt
Andy Andrea
Andy Croll
Arjun Sharda
Asia Hoe
Avdi Grimm
Ben Greenberg
Bhavani Ravi
Brandon Carlson
Brittany Martin
Caleb Thompson
Caren Chang
Chiu-Ki Chan
Christine Seeman
Claudio Baccigalupo
Cody Norman
Devon Estes
Eileen Uchitelle
Emily Giurleo
Emily Samp
Enrico Grillo
Espartaco Palma
Fito von Zastrow
Frances Coronel
Hilary Stohs-Krause
Jalem Raj Rohit
Jemma Issroff
Jenny Shih
Jim Remsik
Joel Chippindale
Justin Searls
Katrina Owen
Kevin Murphy
Kudakwashe Paradzayi
Kylie Stradley
Maeve Revels
Maryann Bell
Matt Bee
Mayra Lucia Navarro
Molly Struve
Nadia Odunayo
Nickolas Means
Noah Gibbs
Olivier Lacan
Ramón Huidobro
Richard Schneeman
Rizky Ariestiyansyah
Saron Yitbarek
Sean Moran-Richards
Shem Magnezi
Srushith Repakula
Stefanni Brasil
Stephanie Minn
Sweta Sanghavi
Syed Faraaz Ahmad
Tekin Suleyman
Thomas Carr
Tom Stuart
Ufuk Kayserilioglu
Valentino Stoll
Victoria Gonda
Vladimir Dementyev
Title
Tags (comma-separated, max 3)
Body
# Description Have you ever wished you could run Rails validators to check that a Hash, Struct or Data instance is properly formatted? Have you ever wanted to be able to compose complex validation logic on the fly rather than registering them at a class level with complicated conditionals? Did you ever have a use case for a single, generic validation and thought it’d be overkill to create a new ActiveModel class? In this talk, we'll explore how to build a single class that’ll accept almost any kind of argument and let you register and run both built-in and custom validations against that argument’s key/value pairs and methods. Through test-driven development and examining the source code for ActiveModel validations and ActiveSupport callbacks, we’ll gradually build a robust solution to support custom and built-in validators and their various options like `if` and `allow_blank`. Whether you want to validate a JSON field in a model, ensure that an incoming API request is properly formatted, check for valid events in an event-sourced application or run a validator against a class from a third-party library without monkey-patching, this talk will help you use some of Rails’ most classic features in a new and powerful way. # Additional notes For several years, I’ve been working on a Rails app that uses a closed-source, event-sourcing implementation that doesn’t use ActiveRecord. After my team noted that we didn’t have a unified strategy for validating our events–which are represented as Ruby hashes–I suggested that we investigate whether we could leverage Rails’s built-in validators rather than having to build and maintain a new library ourselves. That investigation bore fruit and led to a solution that’s been used by multiple teams in production for over a year. As a quick example, it allows us to do something like: ```rb product = { name: “Coffee”, price: 5, size: “M”, drink: true } v = Validator.new(product) v.validates :name, :price, :size, presence: true v.validates :size, inclusion: { in: %w[S M L] }, if: :drink v.validates :price, numericality: { greater_than: 0 } v.valid? ``` In other words, we both register and run validations at the instance level rather than having registering at the class-level and running at the instance-level like it would be for a typical Rails model. Our solution also works if you pass in an object that responded to the `name`, `price`, `size` and `drink` methods instead of having those as keys in a hash for maximum reusability. Each iteration of the code I show in the talk will be heavily inspired by the past iterations of our production code. To begin the talk, I’ll first establish a baseline by doing a very quick review of how validations look and work for typical ActiveRecord or ActiveModel::Model classes. That’ll lead into an initial implementation of our new validator class that naively instantiates an ActiveModel validator (e.g. `ActiveModel::Validations::PresenceValidator`) and calls its `validate` method. From there, I’ll use a test suite to demonstrate what this simple, naive approach gets us and what it fails to support (which will mostly be various validator and callback options like `if`, `on` or `allow_blank`). Next, I’ll show why those tests are failing by diving into the source code for both ActiveModel validations and ActiveSupport callbacks. I’ll show how to gradually improve our validator implementation until the entire test suite is passing. I’ll also include support for validating nested hashes like `{ foo: { bar: :baz } }`. If time permits, I’ll add how we can combine our new validator class with the shoulda_matchers gem for easy unit testing. I believe this talk will fit in well with the theme of RailsConf 2025 because it will allow attendees to learn more about parts of Rails that many of us have used for years: validations and callbacks. Simultaneously, it’ll demonstrate that even some of Rails’ most widely used features can be used in new and powerful ways to support our community, teams and businesses well into the future.
Back to Speaker Directory