Spec-Zone.ru › Ruby on Rails 4.2

класс 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 Перемещено», который перенаправляет пользователя на действие 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

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

Открытые методы класса

protected_instance_variables() Показать исходный код
# File actionpack/lib/action_controller/base.rb, line 262
def self.protected_instance_variables
  PROTECTED_IVARS
end
without_modules(*modules) Показать исходный код
# 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

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

Открытые методы экземпляра

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

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

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

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

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

Spec-Zone.ru

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