Что такое ActiveRecord и как он работает?ruby-42

ActiveRecord — это реализация паттерна Object-Relational Mapping (ORM) в Rails, которая обеспечивает связь между Ruby-объектами и реляционными базами данных.

Основные концепции ActiveRecord

1. Паттерн Active Record

Каждая модель соответствует таблице в БД, а экземпляр модели — строке в этой таблице.

2. Соглашение вместо конфигурации

  • Таблица: users (множественное число)
  • Модель: User (в единственном числе)
  • Первичный ключ: id
  • Внешний ключ: user_id
  • Таблица связей: users_roles

Основные компоненты ActiveRecord

1. Подключение к БД

Конфигурация в config/database.yml:

development:
  adapter: postgresql
  database: myapp_development
  username: user
  password: password

2. Модель

Базовый пример модели:

class User < ApplicationRecord
  validates :email, presence: true, uniqueness: true
  has_many :articles
  scope :active, -> { where(active: true) }
end

3. Миграции

Пример миграции:

class CreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.timestamps
    end
  end
end

Как работает ActiveRecord

1. CRUD операции

Create:

user = User.create(name: "John", email: "john@example.com")
# Или
user = User.new
user.name = "John"
user.save

Read:

User.all
User.find(1)
User.where(name: "John").first
User.find_by(name: "John")

Update:

user = User.find(1)
user.update(name: "New Name")
# Или
User.where(active: true).update_all(verified: true)

Delete:

user.destroy
User.delete_all

2. Цепочки запросов

ActiveRecord использует ленивую загрузку (lazy loading):

User.where(active: true).order(:name).limit(10)

Фактический SQL-запрос выполняется только при необходимости (например, при вызове .each или .to_a).

3. Ассоциации

Основные типы ассоциаций:

class User < ApplicationRecord
  has_many :articles
  has_one :profile
  belongs_to :company
  has_and_belongs_to_many :roles
  has_many :comments, through: :articles
end

4. Валидации

class User < ApplicationRecord
  validates :email,
    presence: true,
    uniqueness: true,
    format: { with: URI::MailTo::EMAIL_REGEXP }

  validate :custom_validation

  private

  def custom_validation
    errors.add(:base, "Custom error") if some_condition
  end
end

5. Колбэки

class User < ApplicationRecord
  before_create :generate_token
  after_save :send_welcome_email

  private

  def generate_token
    self.token = SecureRandom.hex(10)
  end
end

Внутренняя работа ActiveRecord

  1. Connection Pooling: Управление соединениями с БД
  2. Query Building: Построение SQL-запросов
  3. Type Casting: Преобразование типов данных
  4. Relation: Представление запросов в виде цепочки методов
  5. Transaction Management: Управление транзакциями

Пример транзакции:

User.transaction do
  user.update!(balance: user.balance - 100)
  Payment.create!(amount: 100, user: user)
end

Расширенные возможности

1. Arel

Библиотека для построения сложных SQL-запросов:

users = User.arel_table
User.where(users[:name].matches("%John%"))

2. Делегирование методов

class User < ApplicationRecord
  has_one :profile
  delegate :address, to: :profile
end
# Теперь можно использовать user.address

3. Полиморфные ассоциации

class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end

class Article < ApplicationRecord
  has_many :comments, as: :commentable
end

Резюмируем: ActiveRecord — это мощный ORM-слой в Rails, который предоставляет простой интерфейс для работы с БД, используя Ruby-объекты вместо SQL-запросов. Он реализует паттерн Active Record, поддерживает ассоциации, валидации, колбэки и транзакции, значительно упрощая работу с данными в Rails-приложениях.