В этом уроке мы разберем общие концепции, присущие ORM. Каждая из этих концепций рассматривается дальше в курсе.
ORM — это общее название для фреймворков, которые позволяют автоматически связать базу данных с кодом. Они стараются скрыть существование базы данных, насколько это возможно. Взамен программисту дают возможность оперировать данными в базе через специальный интерфейс.
Вместо построения SQL-запросов программист вызывает простые методы, а остальную работу берет на себя ORM. Например, c помощью ORM языка Ruby мы можем создать объект класса и сохранить его в базу данных:
course = Course.new
course.title = 'Ruby'
course.save # сохранение курса в базу
ORM бывают разными. Active Record относится к наиболее распространенному и простому типу ORM. Он реализует одноименный шаблон проектирования Active Record.
Этот шаблон базируется на идее, что каждой таблице в приложении соответствует один класс. Этот класс отвечает за реализацию бизнес логики и взаимодействие с базой данных. Последнее обычно появляется в модели за счет наследования от базового класса ORM.
Модель
Ниже представлен код определения класса модели Course. Даже без явного определения методов внутри, класс модели обладает всей функциональностью для работы с записями курсов в базе данных:
class Course < ApplicationRecord
end
Каждый объект данного класса соответствует одной записи из этой таблицы. За преобразования данных в объекты и обратно, отвечает ORM. Программисту лишь нужно использовать правильные методы, чтобы извлечь объекты и их модификации. Примеры таких методов:
# Поиск курса по идентификатору
course = Course.find(1)
# Обновление курса
course.title = 'Ruby on Rails'
# Сохранение в базу
course.save
# Удаление записи в базе данных
course.destroy
# Общее число курсов
# SELECT COUNT(*) FROM courses;
Course.count
Выборки
Важная часть любой ORM — это Query Interface или интерфейс запросов. Это абстракция поверх SQL, которая упрощает генерацию запросов. Она обычно выглядит как цепочка функций, каждая из которых отвечает за конкретную часть SQL, например: ORDER, SELECT или WHERE. Например, в следующей строчке кода мы получаем все активные курсы и сортируем их по названию:
courses = Course.where(state: 'active').order(title: :desc)
В тех случаях, когда этого языка недостаточно или запрос слишком сложный, ORM позволяет использовать SQL-вставки:
courses = Course.where("title LIKE '%Ruby%' AND state = 'active'")
Схема
Еще одна обязанность ORM — изменение схемы базы данных: добавление, удаление и модификация таблиц. Делается это, как правило, не на чистом SQL, а с помощью специального языка. Это позволяет работать с ORM и не отвлекаться на особенности конкретных баз данных.
ORM сама создает правильный SQL-запрос, который подходит под конкретную базу данных. Вот так выглядит код схемы с созданием таблицы courses:
ActiveRecord::Schema.define(version: 2023_05_04_123456) do
create_table "courses", force: :cascade do |t|
t.string "title", null: false
t.text "description"
t.decimal "price", default: 0
t.timestamps
end
end
В Active Record используется подход Database First. Чтобы создать новые модели или изменить поведение старых, нужно сначала изменить базу данных, а ORM сама подхватывает изменения и работает с ними.
Например, чтобы добавить новое свойство, достаточно добавить новую колонку. В коде ничего менять не нужно, ORM автоматически начинает работать.
В некоторых ORM встречается подход Code First. В таком случае изменения делаются не в базе, а в коде. А дальше ORM сама формирует необходимые изменения для базы данных, подстраивая ее под код.
Миграции
Любая база данных в процессе жизни приложения изменяется. В нее добавляются новые таблицы, удаляются и меняются старые. Этот процесс бесконечный.
Изменения в базе данных выполняются с помощью механизма миграций. Миграция — это обычно файл, который содержит SQL, меняющий текущую схему базы данных. Далее приведен пример кода файла миграции для создания таблицы курса:
class CreateCourses < ActiveRecord::Migration[6.1]
def change
create_table :courses do |t|
t.string :title, null: false
t.text :description
t.decimal :price, default: 0
t.timestamps
end
end
end
Когда этот файл создан, то происходит процесс, который называют «применением миграций». Он выполняется с помощью утилиты командной строки. В Ruby on Rails это выглядит так:
rake db:migrate
В процессе выполнения этой команды автоматически проверяются, какие миграции были уже применены, а какие — нет. Применяются только те миграции, которые еще не выполнены на текущей базе данных.
Выводы
ORM помогает программистам легче и быстрее работать с базами данных, превращая их таблицы в классы и строки в объекты. Это делает код проще для понимания и управления. ORM — важный инструмент для эффективной и безопасной разработки.
Самостоятельная работа
Зайдите в репозиторий hexlet CV и найдите схему БД проекта. Посмотрите, какие таблицы существуют в проекте
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.