Andy from Webcrunch

Subscribe for email updates:

Portrait of Andy Leverenz
Andy Leverenz

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

Link this article
Est. reading time: 3 minutes
Stats: 410 views

Categories

Collection

Part of the Rails Quick Tips collection

Products and courses