В какой момент создается объект контроллера и сколько он живет
В Ruby on Rails объект контроллера создается на каждом HTTP-запросе и живет только в рамках обработки одного этого запроса. Это означает, что экземпляр контроллера не является долговечным — он создается, используется для выполнения логики и рендеринга, а затем уничтожается. Ниже подробно разобран весь процесс, связанный с созданием и жизненным циклом объекта контроллера.
1. Когда создается объект контроллера
Объект контроллера создается после прохождения запроса через Rack middleware и маршрутизатор (router). Весь процесс можно представить поэтапно:
-
Клиент отправляет HTTP-запрос (например, GET /articles/5).
-
Запрос попадает в стек Rack middleware.
-
Middleware передает управление в маршрутизатор (ActionDispatch::Routing::RouteSet).
Маршрутизатор (routes.rb) находит подходящий маршрут:
<br/>get '/articles/:id', to: 'articles#show'
-
Rails определяет:
-
имя контроллера (ArticlesController)
-
экшн (show)
-
На этом этапе создаётся объект контроллера:
<br/>controller = ArticlesController.new
Rails сам управляет этим процессом внутри фреймворка, в частности, через метод dispatch контроллера, вызываемый маршрутизатором.
2. Что происходит после создания контроллера
После создания экземпляра контроллера происходит следующая последовательность:
-
Внутри ActionController::Base запускается метод process(action_name), который:
-
устанавливает объект запроса (request) и ответа (response)
-
устанавливает параметры (params)
-
вызывает все фильтры (before_action, around_action, after_action)
-
вызывает метод контроллера (например, show)
-
формирует ответ, если он не был явно возвращён
-
Пример:
class ArticlesController < ApplicationController
before_action :set_article
def show
\# доступен self, @article, params и т.д.
end
private
def set_article
@article = Article.find(params\[:id\])
end
end
3. Как долго живет объект контроллера
Объект контроллера живет только в пределах одного запроса. После того как:
-
завершено выполнение экшена (show, index и т.д.)
-
сформирован и отправлен HTTP-ответ клиенту
-
выполнены after_action-фильтры (если есть)
-
завершена работа middleware и Rack
...контроллер уничтожается, и память, занимаемая его экземпляром, может быть освобождена сборщиком мусора Ruby.
Контроллер не сохраняется между запросами. Это важно, так как:
-
нельзя использовать переменные экземпляра контроллера (@something) в нескольких запросах
-
нельзя рассчитывать на сохранение состояния объекта
-
вся необходимая информация (например, id пользователя) должна храниться в сессии, куках, базе данных или передаваться в каждом запросе
4. Почему каждый запрос получает новый экземпляр контроллера
Rails придерживается принципа stateless (без состояния), как и HTTP. Это обеспечивает:
-
изоляцию между запросами: один пользователь не повлияет на обработку другого
-
безопасность: нельзя случайно "поделиться" переменной между клиентами
-
упрощение отладки и понимания кода
-
масштабируемость: приложение может обрабатывать множество запросов независимо
Таким образом, создавая новый объект контроллера каждый раз, Rails обеспечивает чистоту архитектуры и надёжность работы.
5. Особенности жизненного цикла
Объект контроллера:
-
Создается: после маршрутизации, но до выполнения экшена.
-
Инициализируется: с контекстом запроса (request, params, session, cookies, headers).
-
Используется: для вызова экшена и выполнения логики.
-
Уничтожается: после завершения формирования ответа.
Также стоит отметить, что:
-
Все instance-переменные (@article, @user, @products) живут только в рамках этого объекта.
-
После вызова экшена результат передается во View для рендеринга.
6. Пример
\# HTTP-запрос: GET /users/1
\# Внутри маршрутизатора:
UsersController.new.process(:show)
\# Что происходит:
1\. new → создается экземпляр UsersController
2\. process(:show)
\- запускается before_action
\- вызывается метод show
\- рендерится шаблон show.html.erb
3\. Ответ отправляется клиенту
4\. Объект контроллера удаляется
7. Исключения и обработка ошибок
Если в процессе выполнения контроллера возникает исключение (например, запись не найдена), то:
-
Rails вызывает middleware для обработки ошибок
-
можно определить rescue_from в контроллере
-
тем не менее, объект контроллера всё равно уничтожается после завершения обработки
class ArticlesController < ApplicationController
rescue_from ActiveRecord::RecordNotFound, with: :not_found
def show
@article = Article.find(params\[:id\])
end
def not_found
render plain: "Not found", status: 404
end
end
Жизненный цикл контроллера в Rails чётко ограничен одним запросом, что делает его надёжным, предсказуемым и изолированным компонентом MVC-архитектуры.