class ActionController::Base
Контроллер действий Base
Контроллеры действий — основа обработки веб-запросов в Rails. Они состоят из одного или нескольких действий, выполняемых по запросу; затем действие либо отображает шаблон, либо перенаправляет на другое действие. Действие определяется как открытый метод контроллера, который автоматически становится доступным веб-серверу через маршруты Rails.
По умолчанию только ApplicationController в приложении Rails наследуется от ActionController::Base. Все остальные контроллеры наследуются от ApplicationController. Это позволяет настроить в одном классе такие параметры, как защита от подделки запросов и фильтрация конфиденциальных параметров запроса.
Пример контроллера:
class PostsController < ApplicationController
def index
@posts = Post.all
end
def create
@post = Post.create params[:post]
redirect_to posts_path
end
end
По умолчанию после выполнения кода действия оно отображает шаблон из каталога app/views, соответствующий имени контроллера и действия. Например, действие index контроллера PostsController по умолчанию отобразит шаблон app/views/posts/index.html.erb после заполнения переменной экземпляра @posts.
В отличие от index, действие create не отображает шаблон. Выполнив свою основную задачу (создание новой записи), оно инициирует перенаправление. Для этого возвращается внешний HTTP-ответ 302 Moved, который переводит пользователя к действию index.
Эти два метода представляют два основных типа действий, используемых в контроллерах действий: «получить и показать» и «выполнить и перенаправить». Большинство действий являются вариациями этих типов.
Запросы
Для каждого запроса маршрутизатор определяет значения ключей controller и action. Они определяют, какой контроллер и какое действие будут вызваны. Остальные параметры запроса, сессия (если она доступна) и полный запрос со всеми заголовками HTTP доступны действию через методы доступа. Затем выполняется действие.
Полный объект запроса доступен через метод доступа request и в основном используется для получения сведений о заголовках HTTP:
def server_ip
location = request.env["REMOTE_ADDR"]
render plain: "This server hosted at #{location}"
end
Parameters
Все параметры запроса — независимо от того, поступают ли они из строки запроса URL или из данных формы, отправленных через запрос POST, — доступны через метод params, который возвращает хеш. Например, действие, вызванное через /posts?category=All&limit=5, будет содержать { "category" => "All", "limit" => "5" } в params.
Также можно создавать многомерные хеши параметров, задавая ключи с помощью квадратных скобок, например:
<input type="text" name="post[name]" value="david"> <input type="text" name="post[address]" value="hyacintvej">
Запрос, отправленный из формы с такими полями, будет содержать { "post" => { "name" => "david", "address" => "hyacintvej" } }. Если бы поле адреса называлось post[address][street], объект params содержал бы { "post" => { "address" => { "street" => "hyacintvej" } } }. Глубина вложенности не ограничена.
Сессии
Сессии позволяют хранить объекты между запросами. Это полезно для объектов, которые ещё не готовы к сохранению, например объекта Signup, созданного в процессе с несколькими этапами, или объектов, которые редко меняются и нужны постоянно, например объекта User в системе с авторизацией. Однако сессию не следует использовать в качестве кэша для объектов, которые могут незаметно измениться. Обычно поддерживать их синхронизацию слишком трудоёмко — с этой задачей базы данных справляются гораздо лучше.
Поместить объекты в сессию можно с помощью метода session, который обращается к хешу:
session[:person] = Person.authenticate(user_name, password)
Получить объект можно через тот же хеш:
"Hello #{session[:person]}"
Чтобы удалить объекты из сессии, можно присвоить отдельному ключу значение nil:
# removes :person from session session[:person] = nil
или удалить всю сессию с помощью reset_session.
По умолчанию сессии хранятся в зашифрованной cookie браузера (см. ActionDispatch::Session::CookieStore). Поэтому пользователь не сможет прочитать или изменить данные сессии. Однако пользователь может сохранить копию cookie даже после истечения срока её действия, поэтому не следует хранить конфиденциальную информацию в сессиях на основе cookie.
Ответы
Каждое действие формирует ответ, содержащий заголовки и документ, которые будут отправлены в браузер пользователя. Фактический объект ответа создаётся автоматически при использовании рендеринга и перенаправлений и не требует вмешательства пользователя.
Рендеринг
Контроллер действий отправляет содержимое пользователю одним из пяти способов рендеринга. Самый гибкий и распространённый — рендеринг шаблона. В состав Rails также входит Action View, позволяющий отображать шаблоны ERB. Он настраивается автоматически. Контроллер передаёт объекты представлению, присваивая им переменные экземпляра:
def show @post = Post.find(params[:id]) end
После этого они автоматически становятся доступны представлению:
Title: <%= @post.title %>
Необязательно полагаться на автоматический рендеринг. Например, если действие может отображать разные шаблоны, используются методы ручного рендеринга:
def search
@results = Search.find(params[:query])
case @results.count
when 0 then render action: "no_results"
when 1 then render action: "show"
when 2..10 then render action: "show_many"
end
end
Подробнее о создании шаблонов ERB и Builder читайте в ActionView::Base.
Перенаправления
Перенаправления используются для перехода от одного действия к другому. Например, после действия create, сохраняющего запись блога в базе данных, мы можем захотеть показать пользователю новую запись. Следуя принципу DRY (Don’t Repeat Yourself — «не повторяйся»), мы повторно используем действие show (и перенаправляем на него), которое, как мы предполагаем, уже создано. Код может выглядеть так:
def create
@entry = Entry.new(params[:entry])
if @entry.save
# The entry was saved correctly, redirect to show
redirect_to action: 'show', id: @entry.id
else
# things didn't go so well, do something else
end
end
В этом случае после сохранения новой записи в базе данных пользователь перенаправляется к методу show, который затем выполняется. Обратите внимание: это перенаправление на уровне HTTP, из-за которого браузер отправляет второй запрос (GET к действию show), а не внутренняя маршрутизация, при которой действия «create» и «show» вызываются в рамках одного запроса.
Подробнее о redirect_to и доступных параметрах читайте в разделе ActionController::Redirecting.
Вызов нескольких перенаправлений или рендерингов
Действие может выполнить только один рендеринг или одно перенаправление. Повторная попытка выполнить одно из них приведёт к ошибке DoubleRenderError:
def do_something redirect_to action: "elsewhere" render action: "overthere" # raises DoubleRenderError end
Если перенаправление должно выполняться только при определённом условии, обязательно добавьте «return», чтобы остановить выполнение.
def do_something
if monkeys.nil?
redirect_to(action: "elsewhere")
return
end
render action: "overthere" # won't be called if monkeys is nil
end
Константы
- MODULES
- PROTECTED_IVARS
-
Определяет некоторые внутренние переменные, которые не должны передаваться представлению.
Публичные методы класса
# File actionpack/lib/action_controller/base.rb, line 223
def self.without_modules(*modules)
modules = modules.map do |m|
m.is_a?(Symbol) ? ActionController.const_get(m) : m
end
MODULES - modules
end Вспомогательный метод, возвращающий все модули, подключённые к ActionController::Base, кроме переданных в качестве аргументов:
class MyBaseController < ActionController::Metal
ActionController::Base.without_modules(:ParamsWrapper, :Streaming).each do |left|
include left
end
end
Это позволяет точнее контролировать, что следует исключить, и упрощает создание базового класса контроллера вместо ручного перечисления необходимых модулей.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.