# coding: utf-8

8.3.3 Флэш

Перед отправкой валидной регистрации в браузер, мы собираемся немного отполировать ее, в соответствии с общепринятой в веб приложениях идеей: добавив сообщение, которое временно появляется, а затем исчезает при перезагрузке страницы. (Если сейчас что-то непонятно, будьте терпеливы; Конкретный пример появится в ближайшее время) Rails способ сделать это состоит в использовании специальной переменной flash, которая работает как флэш-память в том, что она хранит свои данные временно. Переменная flash это на самом деле хэш; и вы можете даже вспомнить консольный например, в Разделе 4.3.3, где мы видели, как для перебора хэша использовался стратегически именованный хэш flash. Чтобы вспомнить, попробуйте эту консольную сессию:

$ rails console
>> flash = { :success => "It worked!", :error => "It failed. :-(" }
=> {:success=>"It worked!", :error => "It failed. :-("}
>> flash.each do |key, value|
?>   puts "#{key}"
?>   puts "#{value}"
>> end
success
It worked!
error
It failed. :-(

Мы можем организовать отображение содержимого Флэш на веб-узле, включив его в макет нашего приложения, как в Листинге 8.16.

Листинг 8.16. Добавление содержимого flash переменной в макет сайта.

app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
      .
      .
      .
      <%= render 'layouts/header' %>
      <section class="round">
        <% flash.each do |key, value| %>
          <div class="flash <%= key %>"><%= value %></div>
        <% end %>
        <%= yield %>
      </section>
      .
      .
      .
</html>

Этот код организует вставку каждого флэш элемента в div тег, с CSS классом, указывающим на тип сообщения. Например, если flash[:success] = "Welcome to the Sample App!", то код

<% flash.each do |key, value| %>
  <div class="flash <%= key %>"><%= value %></div>
<% end %> 

произведет такой HTML:6

<div class="flash success">Welcome to the Sample App!</div>

Причина, по которой мы перебираем все возможные пары ключ/значение заключается в том, что благодаря этому мы сможем включать другие виды флэш сообщений; например, в Листинге 9.8 мы увидим flash[:error] используемое для индикации неудавшегося входа на сайт.7

Давайте протестируем флэш сообщение, чтобы убедиться в его правильности и в том, что оно появляется под ключом :success (Листинг 8.17).

Листинг 8.17. Тест для флэш сообщения об успешной регистрации.

spec/controllers/users_controller_spec.rb
require 'spec_helper'

describe UsersController do
  render_views
  .
  .
  .
  describe "POST 'create'" do
    .
    .
    describe "success" do
      .
      .
      .
      it "should have a welcome message" do
        post :create, :user => @attr
        flash[:success].should =~ /welcome to the sample app/i
      end
    end
  end
end

Это вводит “равно-тильда” =~ оператор для сравнения строк с регулярными выражениями. (Мы впервые увидели регулярные выражения в email_regex Листинга 6.17). Вместо того, чтобы тестировать полное флэш сообщение, мы просто тестируем на существование “welcome to the sample app”. (Обратите внимание, что у нас еще нет теста для внешнего вида реального HTML флэш сообшений; мы исправим это тестированием фактического тега div в Разделе 8.4.3.)

Если вы много программировали ранее, скорее всего, вы уже знакомы с регулярными выражениями, но вот быстрая console сессия в случае если Вам необходимо введение:

>> "foo bar" =~ /Foo/     # Regex сравнение чувствительно к регистру по умолчанию.
=> nil
>> "foo bar" =~ /foo/
=> 0

Значения, возвращаемые здесь консолью, могут выглядеть странно: для несовпадения, regex сравнение возвращает nil; для совпадения оно возвращает index (позицию, место) в строке где началось совпадение.8 Обычно точный индекс не имеет значения, так как сравнение, как правило, используется в булевом контексте: вспомните из Раздела 4.2.3 что nil это false в булевом контексте и что все остальное (даже 0) является истиной. Таким образом, мы можем написать код, подобный этому:

>> success = "Welcome to the Sample App!"
=> "Welcome to the Sample App!"
>> "It's a match!" if success =~ /welcome to the sample app/
=> nil

Здесь нет совпадения, поскольку регулярные выражения чувствительны к регистру по умолчанию, но мы можем быть более снисходительными при сравнении, используя /.../i чтобы добиться нечувствительного к регистру совпадения:

>> "It's a match!" if success =~ /welcome to the sample app/i
=> "It's a match!"

Теперь, когда мы понимаем, как работает сравнение регулярных выражений в тестах флэш, мы можем получить прохождение тестов, назначив flash[:success] в действии create как в Листинге 8.18. Сообщения используют различный регистр, но тесты пройдут в любом случае так как в конце регулярного выражения стоит i. Таким образом, мы не испортим тест, если напишем, например, sample app вместо Sample App.

Листинг 8.18. Добавление флэш сообщения в регистрацию пользователя.

app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(params[:user])
    if @user.save
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      @title = "Sign up"
      render 'new'
    end
  end
end
# coding: utf-8