Episodes

Active Record Tricks

Episode #347 by Teacher's Avatar David Kimura

Summary

In this episode, we look at tips and tricks from read only attributes, inserting and upserting (update or insert) records, toggling booleans, and single table inheritance.
rails activerecord 11:25

Resources

This episode is sponsored by Honeybadger

Summary

# Terminal

bin/rails g model product name category sku in_stock:boolean

# db/migrate/20220501015917_create_products.rb
class CreateProducts < ActiveRecord::Migration[7.0]
  def change
    create_table :products do |t|
      t.string :name
      t.string :category
      t.string :sku, index: { unique: true }
      t.boolean :in_stock, default: true

      t.timestamps
    end
  end
end

Read Only Attributes


# models/product.rb
class Product < ApplicationRecord
  attr_readonly :sku
end

# Rails Console
product = Product.first
product.sku = "changedsku"
product.save # record updates, but sku attribute is ignored

Insert All


# Rails Console
products = [
  { name: 'Apple 14" Macbook Pro (2021)', category: "Laptop", sku: "MKGR3LL", in_stock: true },
  { name: 'Apple 16" Macbook Pro (2021)', category: "Laptop", sku: "MK1E3LL", in_stock: true },
  { name: 'Apple Mac Mini (2020)', category: "Desktop", sku: "MGNR3LL", in_stock: true },
  { name: 'Apple Mac Studio (2022)', category: "Desktop", sku: "MJMW3LL", in_stock: true }
]

Product.insert_all(products)

laptops = [
  { name: 'Apple 14" Macbook Pro (2021)', sku: "MKGR3LL", in_stock: true },
  { name: 'Apple 16" Macbook Pro (2021)', sku: "MK1E3LL", in_stock: true }
]

Product.create_with(category: "Laptop").insert_all(laptops)

Upsert


# Rails Console

desktops = [
  { name: 'Apple Mac Mini (2020)', category: "Desktop", sku: "MGNR3LL", in_stock: false },
  { name: 'Apple Mac Studio (2022)', category: "Desktop", sku: "MJMW3LL", in_stock: true }
]

Product.upsert_all(desktops, update_only: [:in_stock], unique_by: [:sku])

Toggle


# Rails Console
product = Product.first

product.toggle(:in_stock)
product.save

product.toggle!(:in_stock)

Single Table Inheritance


# Terminal
rails g model vehicle name type

# models/car.rb
class Car < Vehicle
  WHEELS = 4
end

# models/motorcycle.rb
class Motorcycle < Vehicle
  WHEELS = 2
end

# Rails Console
Car.create(name: "Civic")
Motorcycle.create(name: "Hayabusa")

vehicle = Motorcycle.first
vehicle.becomes(Car)

vehicle.becomes!(Car)
vehicle.save