класс 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 не отобразит шаблон. После выполнения своего основного назначения (создания нового поста) оно инициирует перенаправление. Это перенаправление работает путём возвращения внешнего 302
Moved HTTP-ответа, который перенаправляет пользователя на действие index.
Эти два метода представляют два основных типа действий, используемых в контроллерах действий: получить и отобразить и выполнить и перенаправить. Большинство действий являются вариациями этих тем.
Запросы
Для каждого запроса маршрутизатор определяет значение ключей controller и action . Они определяют, какой контроллер и какое действие вызываются. Остальные параметры запроса, сессия (если она доступна) и полный запрос со всеми HTTP-заголовками предоставляются действию через методы доступа. Затем выполняется действие.
Полный объект запроса доступен через accessor request и используется в основном для запроса HTTP-заголовков:
def server_ip
location = request.env["REMOTE_ADDR"]
render plain: "This server hosted at #{location}"
end
Параметры
Все параметры запроса, будь то из строки запроса в 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-файле браузера, который криптографически подписан, но не зашифрован. Это предотвращает вмешательство пользователя в сессию, но также позволяет ему видеть её содержимое.
Не храните секретную информацию в сессиях на основе cookie-файлов!
Ответы
Каждое действие приводит к ответу, содержащему заголовки и документ, которые будут отправлены в браузер пользователя. Фактический объект ответа генерируется автоматически с помощью методов render и redirect и не требует вмешательства пользователя.
Отображения
Контроллер действий отправляет содержимое пользователю, используя один из пяти методов отображения. Наиболее универсальным и распространённым является отображение шаблона. 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 (не повторяйте себя), мы используем (и перенаправляем на) действие 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
Если вам нужно перенаправить в зависимости от условия, обязательно добавьте «and return», чтобы остановить выполнение.
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 267
def self.make_response!(request)
ActionDispatch::Response.create.tap do |res|
res.request = request
end
end # File actionpack/lib/action_controller/base.rb, line 197
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 179
Возвращает экземпляр ActionDispatch::Request, представляющий текущий запрос.
# File actionpack/lib/action_controller/base.rb, line 185
Возвращает ActionDispatch::Response, представляющий текущий ответ.
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.