High Leverage Rails
Introduction
Introduction to this course
Why use Ruby on Rails
Why use SQLite
Ruby on Rails + SQLite
Powering Your App with SQLite
Creating tables
Timestamps
Column types
Typeof
Ruby types
Creating table introduction
Creating table advanced
Inserting data
Updating data
Upserting data
Reading data
Virtual columns
Enums
Introduction to JSON
Indexing JSON
JSON table functions
Building a Modern Rails Application
Creating a new Rails application
Installing Solid Queue
Installing Solid Cache
Installing Solid Cable
Dockerfile
Application overview
Authentication
Base styles
Registration
Scaffolding posts
Polishing posts
Scaffolding comments
Polishing comments
Polishing models
Polishing controllers
Creating new post
Updating post
Reviewing MVP
Tagging posts
Custom tags
Friendly URLs
Full text search
Deploying & Operating Your App
Backups
Check Litestream locally
Verifying backups
Deployment options
Deploying with Hatchbox
Deployment constraints
Vertical scaling
Database access
Migrations
Locked video

Please purchase the course to watch this video.

Video thumbnail
Powering Your App with SQLite
Creating table advanced

Full Course

$
129
$179
USD, one-time fee
This course came at the perfect time. I’ve recently gotten back into Rails after an 18-year hiatus, and this was a perfect refresher and shows just how much you can accomplish with Rails right out of the box.
Garrett Winder
Garrett Winder

Move fast and fix things

Application monitoring that helps developers get it done.

Rails hosting made simple

Deploy apps to servers that you own and control.

Summary

Understand error handling in Active Record, including how validations and callbacks affect create and save. Learn why create! raises exceptions on validation failures while create returns an object with errors. We also explore how callbacks execute post-transaction, ensuring data integrity and maintaining a reliable workflow in Rails applications.

Video Transcript

In our last video, we learned how to use Active Record’s create and save commands to insert records into our tables. We saw how these generate generic SQL queries, wrap them in transactions to ensure data integrity, and provide error-handling mechanisms using the exclamation point (!) or its absence.

In this video, I want to explore how Active Record handles errors, what actually happens behind the scenes, and how we can control these behaviors.

Exploring Error Handling in Active Record

Jumping into our IRB playground session, I’ve added more details to our Post model:

  1. A validation rule – The title field must be present.
  2. A callback – After a successful create operation, a message will print confirming that the callback was triggered.

Let’s get this set up and explore edge cases in how create and save handle errors.

What Happens When We Try to Create an Invalid Record?

Instead of supplying values, let’s try creating an empty record:

post = Post.create!

This raises an exception with a long stack trace with a validation error:

Validation failed: Title can't be blank (ActiveRecord::RecordInvalid)

We also notice that no SQL queries are executed. This confirms that Active Record stops execution if validations fail, preventing invalid data from reaching the database.

Using create Without the Bang (!)

Now, let’s try creating a record without the exclamation point:

post = Post.create

Again, no SQL queries are executed, but this time, instead of raising an exception, we get back a blank Post object.

Checking post.errors reveals:

post.errors
# => [#<ActiveModel::Error attribute=title, type=blank, options={}]>

With both the create and save method, it is always going to first run the validations defined on the Active Record Model.

If a record fails validation, it is halted and no SQL queries are executed. Instead either the bang (!) version raises an exception or the non-bang version returns a non-persisted object with validation errors.

In summary, you can:

  • Use create! or save! when you want to force valid data and get an immediate error if something is wrong.
  • Use create or save when you want to handle errors manually and check .errors.

Understanding Callbacks in Active Record

So far, we haven’t seen our callback message print. That’s because the record hasn’t been created successfully.

Now, let’s create a valid record:

Post.create!(title: "new title")

This time, we see:

  1. A SQL INSERT statement is executed.
  2. A transaction is committed.
  3. The callback message is printed, confirming the callback ran after the record was saved.

Key Takeaways from create and save

  • Validations run before executing SQL queries.
  • Callbacks only run after a successful database transaction.
  • Using create! or save! throws an exception on failure, while create or save returns an object with errors.

In the next video, we’ll explore how to insert records directly into the database without triggering validations or callbacks—a technique that can be useful for performance-sensitive operations.