Зарегистрируйтесь, чтобы продолжить обучение

Overview Ruby On Rails

В этом уроке рассмотрим структуру проекта на 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 (попробуйте выполнить их).


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

  1. Официальный гайд по Ruby On Rails
  2. Hexlet CV — проект Хекслета на Ruby On Rails
  3. Полезные команды в Rails

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

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

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

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

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

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

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

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff