Spec-Zone.ru › Ruby on Rails 8.1

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

Определяет некоторые внутренние переменные, которые не должны передаваться представлению.

Публичные методы класса

without_modules (*modules) Показать исходный код
# 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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API