Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Модели Основы разработки на Ruby on Rails

Программа урока

  • Что такое модели в Rails и для чего они нужны
  • Как связаны код и модель
  • Как и зачем валидировать модель
  • Как создавать, изменять, и удалять записи в БД, используя модели

ActiveRecord

  • Представление моделей и их данных
  • Представление связей между моделями
  • Представление иерархий наследования с помощью связанных моделей
  • Валидация моделей до того, как они станут персистентными в базе данных
  • Выполнение операций с базой данных в объектно-ориентированном стиле
class User < ApplicationRecord
  validates :first_name, presence: true
  validates_inclusion_of :role, in: %w{ customer admin superuser }
  validates_length_of :last_name, maximum: 30, message: "less than 30 if you don't mind"

  attribute :is_active, :boolean, default: -> { false }

  scope :admins, -> {where(role: 'admin') }
  has_many :orders
  belongs_to :city
end

Связь класса модели с таблицей

Class Table name
Article articles
LineItem line_items
Deer deers
Mouse mice
Person people

Генерация моделей

bin/rails g model User first_name last_name is_active:boolean

invoke  active_record
create    db/migrate/20211202144414_create_users.rb
create    app/models/user.rb
invoke    test_unit
create      test/models/user_test.rb
create      test/fixtures/users.yml
class User < ApplicationRecord
end

Миграции

Создание миграции

bin/rails g migration create_users first_name last_name is_admin:boolean is_active:boolean
class CreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      t.string :first_name
      t.string :last_name
      t.boolean :is_active
      t.timestamps
    end
  end
end

Выполнение миграции:

bin/rails db:migrate

db/schema.rb

ActiveRecord::Schema.define(version: 2021_12_02_144414) do
  create_table "users", force: :cascade do |t|
    t.string "first_name"
    t.string "last_name"
    t.boolean "is_active"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end
end

Database tasks

bin/rails db:create
bin/rails db:drop
bin/rails db:migrate
bin/rails db:prepare
bin/rails db:reset
bin/rails db:rollback STEP=3
bin/rails db:schema:dump
bin/rails db:schema:load
bin/rails db:seed
bin/rails db:setup

Полный список:

bin/rails -T 'db'

ActiveRecord

Создание

admin = User.create(first_name: 'John', last_name: 'Doe', role: 'admin')
user = User.new(first_name: 'Tom', last_name: 'Smith', role: 'customer')
user.save

Ошибки ActiveRecord


user = User.new(last_name: 'Smith', role: 'customer')

user.save

user.validate! # => ["cannot be nil"]
user.valid? # false
user.invalid? # true
user.errors # Error object
user.errors.messages # {"first_name" => "cannot be nil"}
user.errors.full_messages # ["first_name cannot be nil"]

Чтение

users = User.all
user = User.first
user = User.find(1)
user = User.find_by(id: 1)
user = User.last
users = User.where(name: 'John', is_admin: true).order(created_at: :desc)

Удаление

user = User.find_by(name: 'John')
user.destroy

User.destroy_all

Сиды

# db/seeds.rb
User.create(first_name: 'John', last_name: 'Doe', role: 'admin')
User.create(first_name: 'John', last_name: 'Smith', role: 'customer')

100.times do
  User.create(
    first_name: Faker::Name.first_name,
    last_name: Faker::Name.last_name,
    role: %w[customer admin superuser].sample,
    is_active: [true, false].sample
  )
end

Наполнение БД тестовыми данными (сидами):

bin/rails db:seed

Конфиг подключения к БД

Файл config/database.yml содержит настройки для подключения к БД

default: &default
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: db/test.sqlite3

production:
  <<: *default
  database: db/production.sqlite3

Запросы

User.where.not(role: :admin)
User.where(role: :admin).or(User.where(role: :superuser))
User.order(:age)
User.order(age: :desc)
User.select(:first_name, :last_name)
User.select(:last_name).distinct
User.limit(15)
User.limit(15).offset(30)
User.group(:age).count
User.none

Скоупы

Модель со скоупами:

class User < ApplicationRecord
  validates :first_name, presence: true
  validates_inclusion_of :role, in: %w( customer admin superuser )
  validates_length_of :last_name, maximum: 15, message: "less than 15 if you don't mind"
  validates :age, numericality: { only_integer: true, greater_than: 17 }
  validates :email, uniqueness: true
  validates :email, format: { with: /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/ }
  validate :custom_validation

  attribute :is_active, :boolean, default: -> { false }

  def custom_validation
    errors.add :first_name, 'You are not welcome here, John'  if first_name == 'John'
  end

  # scope :admins, -> {where(role: 'admin') }
  # has_many :orders
  # belongs_to :city

  attribute :is_active, :boolean, default: -> { false }

  scope :customers, -> { where(role: 'customer') }
  scope :admins, -> { where(role: 'admin') }
  scope :superusers, -> { where(role: 'superuser') }
  scope :old_admins, -> { admins.where('age > ?', 60) }
  scope :admins_older_than, -> (age) { admins.where('age > ?', age) }

  # default_scope { admins }
end

Применение скоупа на выборку:

User.customers.where("age > ?", 45).select(:email)

Дефолтный скоуп:

class User < ApplicationRecord
  # ...
  scope :admins, -> { where(role: 'admin') }
  default_scope { admins }
end

# У модели установлен дефолтный скоуп, выбираются только админы
User.all.count # 32

# Выбор пользователей без скоупов
User.unscoped.all.count # 100

Домашнее задание

Загрузите домашнее задание с помощью команды:

hexlet program download rails models

Дополнительные материалы

  1. Официальный гайд по Ruby On Rails — Active Record Basics

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 130 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Разработчик на Ruby on Rails
Профессия
Создает веб-приложения со скоростью света
18 мая 5 месяцев

Используйте Хекслет по максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»

Изображение Тото

Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу