Cheat Sheet Active Record

Générer un model post

rails generate model Post title:string likes:integer

Migrations (Rails documentation)

add_column :products, :title, :string
add_index :products, :title
add_reference :products, :user, foreign_key: true
add_reference :products, :supplier, polymorphic: true
remove_reference :table_name, :reference_model, index: true
remove_column :products, :part_number, :string
rename_column :table_name, :old_column, :new_column
change_column :products, :part_number, :text
change_column_default :products, :approved, from: true, to: false
drop_table :table_name

Validations (Rails documentation)

class Order
  validates_presence_of :first_name, :last_name
  validates :category, inclusion: { in: ["sports", "clothing", "technology"] }
  validates :first_name, uniqueness: { scope: :last_name }
  validates :password, confirmation: true, unless: -> { password.blank? }
  validates :rating, numericality: { greater_than: 0 }
  validates :email, format: { with: /\A.*@.*\.com\z/ }
end

Ajouter un message d’erreur

errors.add(:amount_base, 'Le montant de la facture de solde doit être égale au solde restant du devis')

Has many

class Author
  has_many :articles, strict_loading: true # avoid N+1 query
  has_many :comments, through: :articles
  has_many :authorized_articles, -> { where(allowed: true) }, class_name: 'Articles'
end

Scope

class Post
  scope :published, -> { where(published: true) }
end

Migration avec des uuid à la place des id

class CreateOrders < ActiveRecord::Migration[7.0]
  def change
    create_table :orders, id: :uuid do |t|
      t.float :amount
      t.timestamps
    end
  end
end

Generating Secure Tokens on Your ActiveRecord Models

class User < ApplicationRecord
  has_secure_token :access_code, length: 30
end

class AddAccessCodeToUser < ActiveRecord::Migration[7.0]
  def change
    add_column :users, :access_code, :string
  end
end

Joindre 2 tables

Order.joins(:products)

Inclure une autre table à une requête pour éliminer les query N+1

Order.includes(:products)

Joindre une autre table mais ne renvoie que les orders

Order.joins(:products).where(products: { name: 'Play Station'})

Récupérer des informations sur une query (détail de la requête plus query planner)

Order.all.explain

Where avec une date

Post.where(created_at: 1.week.ago..) # Find all posts created in the last week

Where avec un ilike (i pour case Insentitive)

Post.where("title ILIKE ?", "%blog%")

Where avec une longue query

sql_query = <<~SQL
  movies.title ILIKE :query
  OR movies.synopsis ILIKE :query
  OR directors.first_name ILIKE :query
SQL
Movie.joins(:director).where(sql_query, query: "%blog%")

Callback (Rails documentation)

class User < ApplicationRecord
  before_validation :ensure_login_has_a_value

  private

  def ensure_login_has_a_value
    if login.nil?
      self.login = email unless email.blank?
    end
  end
end

Friendly Url in routes with #to_param

class User < ApplicationRecord
  def to_params
    "#{id}-#{title.parameterize}"
  end
end

Has Nested Attributes (Rails documentation)

class Book < ActiveRecord::Base
  has_one :author
  has_many :pages

  accepts_nested_attributes_for :author, :pages
end

Money rails lien de la gem

class Product
  monetize :price_cents
end

Product.last.price #=> #<Money cents:100 currency:EUR>

Counter cache pour les relations

class Items
  belongs_to :orders, counter_cache: true
end

class AddItemsCountToOrders < ActiveRecord::Migration[7.0]
  def change
    add_column :orders, :items_count, :integer, default: 0, null: false
  end
end

Des articles pour aller plus loin sur les bases de données dans Rails :

Résoudre et les problèmes de query N+1
Les Transactions dans Rails
Le Polymorphisme dans Rails
Comment optimiser sa base de données sour Rails
ActiveRecord Optimisation: Utilising .exists?, .any? and .size
Advanced Active Record: Optimizing Performance and Robustness with Locking, UUIDs, Fulltext Search, Database Views, and Geospatial Data
Assign a default value to an attribute in Active Record