class 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 Moved, который перенаправляет пользователя на действие index.
Эти два метода представляют два основных типа действий, используемых в контроллерах действий: получение и отображение и выполнение и перенаправление. Большинство действий являются вариациями этих тем.
Запросы
Для каждого запроса маршрутизатор определяет значение ключей controller и action. Они определяют, какой контроллер и какое действие вызываются. Остальные параметры запроса, сессия (если она доступна) и весь запрос со всеми заголовками HTTP предоставляются действию через методы доступа. Затем выполняется действие.
Полный объект запроса доступен через accessor 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.
Ответы
Каждое действие приводит к ответу, который содержит заголовки и документ, который должен быть отправлен в браузер пользователя. Фактический объект ответа генерируется автоматически с помощью методов отображения и перенаправления и не требует вмешательства пользователя.
Отображения
Контроллер действий отправляет содержимое пользователю, используя один из пяти методов отображения. Наиболее универсальным и распространенным является отображение шаблона. В 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
Если вам нужно перенаправить в зависимости от условия, обязательно добавьте «и 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 184
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.