Spec-Zone.ru › Ruby on Rails 6.0

класс ActionController::Base

Родитель:
Metal

Контроллеры действий являются ядром веб-запроса в 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

Параметры

Все параметры запроса, будь то параметры из строки запроса в 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.

Сессии по умолчанию хранятся в куки браузера, которые криптографически подписаны, но не зашифрованы. Это предотвращает вмешательство пользователя в сессию, но также позволяет ему видеть ее содержимое.

Не храните секретную информацию в сессиях на основе куки!

Ответы

Каждое действие приводит к ответу, содержащему заголовки и документ, который будет отправлен браузеру пользователя. Фактический объект ответа генерируется автоматически с помощью методов 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 (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

Если вам нужно перенаправить при выполнении определённого условия, то обязательно добавьте «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

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

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

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

Это обеспечивает лучший контроль над тем, что вы хотите исключить, и облегчает создание класса контроллера без модулей, вместо того, чтобы вручную указывать необходимые модули.

Публичные методы экземпляра

request() Показать исходный код
# File actionpack/lib/action_controller/base.rb, line 179
    

Возвращает экземпляр ActionDispatch::Request, представляющий текущий запрос.

response() Показать исходный код
# File actionpack/lib/action_controller/base.rb, line 185
    

Возвращает ActionDispatch::Response, представляющий текущий ответ.

© 2004–2019 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

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