Spec-Zone.ru › Ruby on Rails 5.1

класс 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 предоставляются действию через методы доступа. Затем выполняется действие.

Объект полного запроса доступен через доступ к запросу и используется в основном для запроса 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!

Ответы

Каждое действие приводит к ответу, который содержит заголовки и документ, который будет отправлен браузеру пользователя. Фактический объект ответа генерируется автоматически с помощью отображений и перенаправлений и не требует вмешательства пользователя.

Отображения

Контроллер действий отправляет содержимое пользователю, используя один из пяти методов отображения. Наиболее универсальный и распространенный — отображение шаблона. В 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

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

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

make_response!(request) Показать исходный код
# File actionpack/lib/action_controller/base.rb, line 264
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