класс ActionController::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 Перемещено», который перенаправляет пользователя на действие index.
Эти два метода представляют собой два основных типа действий, используемых в контроллерах действий. Получить-и-отобразить и сделать-и-перенаправить. Большинство действий являются вариациями этих тем.
Запросы
Для каждого запроса маршрутизатор определяет значение ключей controller и action. Они определяют, какой контроллер и какое действие вызываются. Остальные параметры запроса, сессия (если она доступна) и весь запрос со всеми HTTP-заголовками доступны действию через методы доступа. Затем выполняется действие.
Объект полного запроса доступен через аксессор request и используется в основном для запроса HTTP-заголовков:
def server_ip
location = request.env["REMOTE_ADDR"]
render plain: "This server hosted at #{location}"
end
Параметры
Все параметры запроса, будь то GET- или POST-запрос или из URL, доступны через метод 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.
Сессии по умолчанию хранятся в куки браузера, которые криптографически подписаны, но не зашифрованы. Это предотвращает вмешательство пользователя в сессию, но также позволяет ему видеть ее содержимое.
Не помещайте секретную информацию в сессии, основанные на куки!
Ответы
Каждое действие приводит к ответу, который содержит заголовки и документ, который должен быть отправлен в браузер пользователя. Фактический объект ответа генерируется автоматически с помощью отображений и перенаправлений и не требует вмешательства пользователя.
Отображения
Контроллер действий отправляет контент пользователю, используя один из пяти методов отображения. Наиболее универсальный и распространенный — отображение шаблона. В Action Pack включен 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
Если вам нужно перенаправление при определенном условии, убедитесь, что добавили «и возвращаемся», чтобы остановить выполнение.
def do_something redirect_to(action: "elsewhere") and return if monkeys.nil? render action: "overthere" # won't be called if monkeys is nil end
Константы
- MODULES
- PROTECTED_IVARS
-
Определяет некоторые внутренние переменные, которые не должны передаваться в представление.
Открытые методы класса
# File actionpack/lib/action_controller/base.rb, line 262 def self.protected_instance_variables PROTECTED_IVARS end
# File actionpack/lib/action_controller/base.rb, line 195
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
Это обеспечивает лучший контроль над исключаемыми элементами и упрощает создание базового класса контроллера вместо ручного перечисления необходимых модулей.
Открытые методы экземпляра
# File actionpack/lib/action_controller/base.rb, line 177
Возвращает экземпляр ActionDispatch::Request, представляющий текущий запрос.
# File actionpack/lib/action_controller/base.rb, line 183
Возвращает ActionDispatch::Response, представляющий текущий ответ.
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.