Spec-Zone.ru › Ruby on Rails 5.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 Перемещено", который перенаправляет пользователя на действие 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.

По умолчанию сессии хранятся в 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 (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

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

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

make_response!(request) Показать исходный код
# File actionpack/lib/action_controller/base.rb, line 263
def self.make_response!(request)
  ActionDispatch::Response.create.tap do |res|
    res.request = request
  end
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