В этом уроке рассмотрим структуру проекта на Rails.
Структура проекта
При создании нового проекта на Rails с помощью команды rails new my_app
создается предопределенная структура каталогов. Основные директории включают:
- app/: здесь находятся основные компоненты приложения:
- models/: модели данных.
- views/: шаблоны для отображения.
- controllers/: контроллеры, обрабатывающие запросы.
- helpers/: вспомогательные модули.
- assets/: статические файлы (CSS, JavaScript, изображения).
- config/: файлы конфигурации приложения, включая маршруты и настройки среды.
- db/: миграции и схемы базы данных.
- lib/: дополнительные библиотеки и модули.
- log/: файлы журналов приложения.
- test/ или spec/: тесты для приложения.
Окружение
Rails поддерживает несколько окружений по умолчанию:
- development: для разработки.
- test: для запуска тестов.
- production: для рабочего приложения.
Каждое окружение может иметь свои настройки в файле config/environments/*.rb
. Там же можно создать новое окружение.
У каждого окружения могут быть свои зависимости. Например для локальной разработки мы можем использовать базу данных SQLite, а для продакшена - PostgreSQL:
# Пример Gemfile из hexlet-cv
# https://github.com/Hexlet/hexlet-cv/blob/main/Gemfile
group :development, :test do
gem 'factory_bot_rails'
gem 'faker'
gem 'rubocop-performance'
gem 'rubocop-rails'
gem 'slim_lint'
gem 'sqlite3', '~> 1.4'
end
#...
group :production, :staging do
gem 'pg'
end
Модели
Модели в Rails представляют данные и бизнес-логику. Они обычно наследуются от ActiveRecord::Base
, что позволяет им взаимодействовать с базой данных. Пример модели резюме из Hexlet CV:
# https://github.com/Hexlet/hexlet-cv/blob/main/app/models/resume.rb
class Resume < ApplicationRecord
validates :name, presence: true
validates :github_url, presence: true, unless: :draft?
validates :summary, length: { minimum: 200 }, presence: true, unless: :draft?
validates :skills_description, presence: true, unless: :draft?
validates :contact_email, presence: true, unless: :draft?
validates :contact_email, 'valid_email_2/email': true
validates :contact_phone, phone: true
def initialize(attribute = nil)
defaults = {
locale: I18n.locale,
relocation: :not_specified
}
attrs_with_defaults = attribute ? defaults.merge(attribute) : defaults
super(attrs_with_defaults)
end
def to_s
name
end
def author?(user)
user_id == user.id
end
end
Миграции
Миграции позволяют управлять изменениями в структуре базы данных. Они записываются в виде отдельных файлов в каталоге db/migrate
. Пример миграции для создания таблицы пользователей:
# frozen_string_literal: true
class CreateResumes < ActiveRecord::Migration[6.0]
def change
create_table :resumes do |t|
t.string :state
t.string :name
t.string :content
t.references :user, null: false, foreign_key: true
t.timestamps
end
end
end
Роутинг
Роутинг в Rails управляет тем, как запросы направляются к контроллерам. Файл маршрутов находится в config/routes.rb
. Пример файла с маршрутами:
Rails.application.routes.draw do
scope '(:locale)', locale: /en|ru/ do
scope module: :web do
resources :resumes do
scope module: :resumes do
resources :answers do
member do
patch :change_applying_state
end
end
resources :pdfs, only: :show
resources :comments
end
end
resources :users
resources :pages
end
end
end
Контроллеры
Контроллеры обрабатывают запросы и взаимодействуют с моделями. Они находятся в каталоге app/controllers
. Пример контроллера для пользователей:
# frozen_string_literal: true
class Web::ResumesController < Web::ApplicationController
redirect_actions_when_not_founded_to -> { root_path }, only: :show, if: -> { browser.bot? }
def index
@resumes = Resume.web.with_locale.order(id: :desc)
respond_to do |format|
format.rss
end
end
def show
@resume = Resume.web.with_locale.find(params[:id])
authorize @resume
impressionist(@resume) if inc_view_counter?
@resume_answers = @resume.answers
.web
# .includes(:comments)
# .merge(Resume::Answer::Comment.web)
.order(likes_count: :desc)
.uniq
@answer = Resume::Answer.new resume: @resume
@current_user_answer = @resume.answers.find_by(user: current_user)
current_user_likes = @resume.answer_likes.where(user: current_user)
@current_user_likes_by_answer_id = current_user_likes.index_by(&:answer_id)
@resume_educations = @resume.educations.web
@resume_works = @resume.works.web
set_meta_tags canonical: resume_url(@resume)
set_meta_tags og: {
title: @resume,
description: @resume.summary,
type: 'article',
url: resume_url(@resume)
}
end
def inc_view_counter?
return true unless current_user
!@resume.author?(current_user) && !@resume.impressions.exists?(user_id: current_user.id)
end
Представления
Представления (views) отвечают за отображение данных пользователю. Они находятся в каталоге app/views
. Каждое действие контроллера имеет соответствующий файл в виде HTML-шаблона (обычно с расширением .html.erb
или .html.slim
). Например, для метода index
контроллера UsersController
будет файл app/views/users/index.html.erb
.
Пример представления для отображения страницы резюме с помощью шаблонизатора Slim:
= content_for :meta do
= structured_data_tag 'resume',
resume: @resume, educations: @resume_educations, works: @resume_works
= content_for :header do
.d-flex.justify-content-center
.m-1
= link_to @resume.user.full_name, user_path(@resume.user)
- if current_user_or_guest.admin?
.m-1
= link_to edit_admin_resume_path(@resume), class: 'btn btn-outline-primary' do
span.bi.bi-gear
h3.text-center = @resume
Генераторы
Rails предоставляет генераторы, которые помогают быстро создавать модели, контроллеры, миграции и другие компоненты. Например, чтобы создать модель пользователя с миграцией, используйте:
rails generate model User name:string
# Короткая команда
# rails g model User name:string
Это создаст файл модели и соответствующую миграцию. Для отмены изменений используйте destroy
:
bin/rails destroy model User name:string
# bin/rails d model User name:string
Список всех генераторов можно посмотреть командой bin/rails generate
# короткая версия
# bin/rails g
bin/rails generate
Usage:
bin/rails generate GENERATOR [args] [options]
General options:
-h, [--help] # Print generator's options and usage
-p, [--pretend] # Run but do not make any changes
-f, [--force] # Overwrite files that already exist
-s, [--skip] # Skip files that already exist
-q, [--quiet] # Suppress status output
Please choose a generator below.
Rails:
application_record
benchmark
channel
controller
generator
helper
integration_test
jbuilder
job
mailbox
mailer
migration
model
resource
scaffold
scaffold_controller
system_test
task
ActiveRecord:
active_record:application_record
active_record:multi_db
Stimulus:
stimulus
TestUnit:
test_unit:channel
test_unit:generator
test_unit:install
test_unit:mailbox
test_unit:plugin
Выводы
Мы рассмотрели ключевые компоненты структуры проекта на Rails, которые позволяют организовать разработку веб-приложений.
- Команда
rails new <app_name>
создает новый проект.. - Окружение определяет настройки и конфигурации для разработки, тестирования и продакшена, что обеспечивает гибкость в работе приложения.
- Модели описывают данные и бизнес-логику приложения, связывая их с базой данных через Active Record.
- Миграции служат для управления изменениями в схеме базы данных, позволяя легко вносить изменения в структуру данных.
- Роутинг отвечает за определение URL-адресов и связывание их с соответствующими контроллерами и действиями.
- Контроллеры обрабатывают запросы, управляют потоком данных и взаимодействуют с моделями и представлениями.
- Представления отвечают за отображение данных пользователю и формируют пользовательский интерфейс приложения.
- Генераторы упрощают создание шаблонов, моделей, контроллеров и других компонентов, что ускоряет разработку.
Самостоятельная работа
cv.hexlet.io — опенсорс-проект для соискателей и HR-специалистов. Кандидаты публикуют на сайте резюме, а опытные эйчары рекомендуют, как улучшить эти документы. В проекте используется Ruby on Rails.
Скачайте и разверните локально приложение Hexlet CV. Откройте его в браузере. Ознакомьтесь с доступными командам. Изучите используемые зависимости, доступные команды в Makefile (попробуйте выполнить их).
Дополнительные материалы
- Официальный гайд по Ruby On Rails
- Hexlet CV — проект Хекслета на Ruby On Rails
- Полезные команды в Rails
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.