Как устроен реквест цикл в рельсах

Цикл запроса в Ruby on Rails (request cycle) описывает весь путь HTTP-запроса от его получения сервером до возврата ответа пользователю. Этот процесс является ядром веб-приложения на Rails и включает множество уровней: веб-сервер, маршрутизацию, контроллеры, модели, виды и middleware. Ниже подробно разобраны все этапы запроса.

1. Веб-сервер получает запрос

Rails-приложение обычно работает за обратным прокси, например, Nginx или Apache. Внутри работает веб-сервер, поддерживающий Rack-интерфейс, например:

  • Puma (по умолчанию в Rails)

  • Unicorn

  • Passenger

Когда пользователь отправляет HTTP-запрос (например, GET /articles), этот запрос доходит до веб-сервера, который затем передаёт его приложению через Rack — интерфейс между веб-сервером и приложением Ruby.

2. Rack-интерфейс

Rack определяет API, через который веб-сервер взаимодействует с приложением. Он передаёт окружение (env — хэш с HTTP-данными) в Rails и ожидает в ответ массив из трёх элементов:

[status, headers, body]

Rails реализует этот интерфейс в классе Rails::Application, и все middleware проходят через этот слой.

3. Middleware (Rack middleware)

До того как запрос попадёт в маршрутизатор и контроллер, он проходит через цепочку middleware — компонентов, обрабатывающих запрос или ответ:

  • Rack::Sendfile — отвечает за отдачу статических файлов

  • Rack::Runtime — добавляет время выполнения

  • ActionDispatch::Cookies — обрабатывает cookies

  • ActionDispatch::Session::CookieStore — сессии

  • ActionDispatch::Flash — флеш-сообщения

  • Rack::MethodOverride — поддержка PUT/DELETE через POST-запрос

  • и др.

Middleware может изменять env, остановить обработку (возвращая response) или продолжить вызов следующего middleware.

4. Router (маршрутизатор)

После middleware запрос попадает в маршрутизатор — Rails.application.routes. Он сравнивает путь запроса и HTTP-метод с маршрутами, определёнными в config/routes.rb.

get '/articles', to: 'articles#index'

Если найдено совпадение, маршрут определяет:

  • контроллер (ArticlesController)

  • экшн (index)

  • параметры (params[:id] и др.)

5. Controller (контроллер)

Маршрут передаёт управление соответствующему контроллеру. Rails создаёт экземпляр контроллера и вызывает нужное действие (index, show, create, и т.д.).

Внутри контроллера:

  1. Обрабатываются параметры запроса (params)

  2. Выполняется бизнес-логика

  3. При необходимости запрашиваются данные из модели

  4. Возвращается ответ (HTML, JSON, редирект и т.д.)

Контроллер может использовать:

  • фильтры (before_action, after_action)

  • работу с куки и сессиями

  • хелперы, рендеринг, редиректы

6. Model (модель, ActiveRecord)

Если экшн требует взаимодействия с базой данных, вызываются методы модели. Rails использует ActiveRecord — реализацию паттерна ORM (Object-Relational Mapping):

@articles = Article.where(published: true)

Каждая модель — это Ruby-класс, связанный с таблицей в базе данных. Запросы преобразуются в SQL и выполняются через адаптер к СУБД (например, PostgreSQL, MySQL, SQLite).

Модель также может выполнять валидации, колбэки и ассоциации (has_many, belongs_to, и т.д.).

7. View (представление, шаблоны)

После завершения логики в контроллере вызывается рендеринг представления:

  • По умолчанию рендерится шаблон, соответствующий имени действия: views/articles/index.html.erb

  • Можно явно указать другой шаблон: render 'shared/header'

  • Можно вернуть JSON: render json: @articles

Rails использует шаблонизатор ERB (Embedded Ruby) или альтернативы (HAML, Slim) для вставки Ruby-кода в HTML.

View может также использовать layout (views/layouts/application.html.erb) и partials (_form.html.erb и т.д.).

8. Формирование ответа

После рендеринга ActionController формирует полноценный HTTP-ответ:

  • Статус-код (200, 404, 500 и т.д.)

  • Заголовки (Content-Type, Set-Cookie, и др.)

  • Тело ответа (HTML, JSON, XML)

Финальный ответ формируется в виде Rack-суммки: [status, headers, body].

9. Ответ проходит обратно через middleware

Перед тем как попасть к клиенту, ответ возвращается обратно через те же Rack middleware, но уже в обратном направлении. Это может быть полезно для:

  • логирования (Rack::Logger)

  • компрессии (Rack::Deflater)

  • модификации заголовков

  • записи cookies или сессий

10. Ответ отправляется браузеру

Rack возвращает ответ веб-серверу, который уже передаёт его клиенту (браузеру или другому HTTP-клиенту).

Браузер получает статус, заголовки и тело и отображает страницу или обрабатывает данные (например, в случае API).

Визуальная схема

HTTP-запрос

Веб-сервер (Puma/Nginx)

Rack (интерфейс)

Middleware (цепочка Rack middleware)

Router (routes.rb)

Controller (логика)

Model (база данных)

View (рендеринг)

Response

Middleware (обратный проход)

Rack → Веб-сервер

HTTP-ответ клиенту

Rails Request Cycle — это архитектура, объединяющая множество компонентов в чётко определённую цепочку обработки HTTP-запроса. Это позволяет легко масштабировать, тестировать и расширять поведение веб-приложения.