March 12, 2024
•Last updated March 13, 2024
Easy normalization with Rails
ActiveRecord plays a pivotal role in interacting with databases. One of the key concepts in database design is normalization, a technique for organizing and formatting data efficiently.
In this tutorial, I’ll showcase the bundled ActiveRecord normalization features within Rails.
Setting Up the Project
Let's start by generating a Rails scaffold for the app, which will be a simple one related to creating dedicated websites.
I created a basic Rails app with the following flags:
rails new normalize_demo -c tailwind -j esbuild
I also added the tailwindcss-rails gem to save some time on scaffolds.
bundle add tailwindcss-rails
rails tailwindcss:install
Finally, to get some resources and logic into the app quickly I’ll scaffold a Site
resource.
rails g scaffold Site domain:string title:string published:boolean
rails db:migrate
Lastly, update the routes:
Rails.application.routes.draw do
resources :sites
get "up" => "rails/health#show", as: :rails_health_check
root "sites#index"
end
Understanding Normalization
Normalization is all about structuring our database tables to minimize redundancy and dependency issues. It involves breaking down large tables into smaller ones and establishing relationships between them. This enhances data integrity, reduces storage space, and improves query performance.
Identifying Columns for Normalization:
In our Site
scaffold, we have three columns: domain
, title
, and published
. Of the three columns, we can look deeper at Domain and Title, which seem to be good candidates for normalization.
Domain:
A domain should have a unique format: no whitespaces, all lowercase, and no TLDs passed upon saving. We can enforce this using the normalization method.
In addition to normalizing, adding uniqueness validation would probably make sense so that only one site can have a given domain in the app—the logic of how your application works should ultimately dictate this.
Title:
While titles might seem straightforward, they can vary in length and content. Using the normalizes
method on the model, we can enforce a consistent style.
Putting it to practice
With the normalizes
method, you can pass a lambda function on the column you declare and format it on the fly. This occurs as a callback function on each database commit. If you create or update it, you’ll see the effects. Pretty neat!
class Site < ApplicationRecord
normalizes :title, with: ->(title) { title.strip.titleize }
normalizes :domain, with: ->(domain) { domain.downcase.strip.parameterize }
end
What if I want to normalize manually?
You’re in luck! You can use a handy built-in method to call in other areas of your app. I assume this might happen in the controller layer, but consider background jobs, seeds, and more.
Here are some quick examples:
site = Site.find(1)
site.title = "MY TITLE\n"
site.normalize_attribute(:title)
site.title # => "My Title"
site.save
site = Site.find(2)
site.domain = "Some Good Domain\n"
site.normalize_attribute(:domain)
site.domain = "some-good-domain"
site.save
Continue reading
Categories
Collection
Part of the Rails Quick Tips collection
Products and courses
-
Hello Hotwire
A course on Hotwire + Ruby on Rails.
-
Hello Rails
A course for newcomers to Ruby on Rails.
-
Rails UI
UI templates and components for Rails.