Статьи

Синатра Флэш

Flash — это удобный маленький вспомогательный метод в Rails, который позволяет хранить информацию между запросами. Когда ваше приложение обрабатывает запрос, оно обычно заканчивается перенаправлением на другой URL, который генерирует другой запрос. Флэш — это хеш-подобный объект, который хранит временные значения, такие как сообщения об ошибках, чтобы их можно было извлечь позже — обычно по следующему запросу. Он также удаляет информацию после ее использования.

Sinatra Flash — это аккуратное маленькое расширение, написанное Стивеном Эли. Он включает в себя все функциональные возможности Rails Flash, но, в соответствии с минималистским характером Синатры, использует гораздо меньше кода.

Установка

Прежде всего нам нужно установить гем sinatra-flash, вот так:

gem install sinatra-flash 

Чтобы опробовать базовую функциональность, нам понадобится простое приложение Sinatra. Создайте файл с именем ‘main.rb’, который содержит следующий код:

require ‘sinatra’
require ‘slim’
require ‘sinatra/flash’

view raw
gistfile1.rb
hosted with ❤ by GitHub

Это драгоценные камни, необходимые для нашего основного приложения — очевидно, Sinatra, и я использую движок Slim для рендеринга (не стесняйтесь использовать другой, такой как erb или haml, если хотите). Чтобы использовать Sinatra Flash, нам нужен драгоценный камень. Sinatra Flash использует сессии для хранения данных от одного запроса к другому. Сессии по умолчанию отключены в Sinatra, но их легко использовать, просто добавьте следующую строку после обязательного:

enable :sessions

view raw
gistfile1.rb
hosted with ❤ by GitHub

Далее мы создадим простой обработчик для нашей индексной страницы:

get ‘/’ do
slim :index
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

Здесь ничего особенного не происходит, он просто отображает индексное представление, когда пользователь переходит к корневому URL. Нам понадобится макет и некоторые основные виды, чтобы начать работу. Я собираюсь использовать потрясающие встроенные представления Синатры, чтобы я мог хранить все в одном файле. Просто поместите объявление __END__ Вот очень простой HTML5 макет и представление, которое просто отображает заголовок.

__END__
@@layout
doctype html
html
head
meta charset=»utf-8″
title Sinatra Flash
body
== yield
@@index
h1 Sinatra Flash

view raw
gistfile1.rb
hosted with ❤ by GitHub

Давайте проверим это. Откройте окно командной строки и перейдите в папку, содержащую файл main.rb, а затем введите следующее:

 $> ruby main.rb 

Теперь перейдите к «http: // localhost: 4567» в вашем браузере, и вы должны увидеть следующее:

Становится роскошным

Теперь давайте попробуем использовать Flash. Обычная причина, по которой вы хотите использовать эту функцию, — это когда кто-то взаимодействует с вашим сайтом, нажимая кнопку или посещая URL-адрес. Ваше приложение перейдет на соответствующий URL-адрес, обработает некоторую информацию и затем перенаправит пользователя на другой URL-адрес. Флэш-память позволяет вам дать некоторую обратную связь с момента обработки информации, которая в противном случае была бы потеряна. Чтобы продемонстрировать это, давайте добавим кнопку на страницу индекса. Измените код представления @@index

@@index
h1 Sinatra Flash
form action=«/time» method=«POST»
input type=«submit» value=«What Time Is It?» title=«What time is it?»

view raw
gistfile1.rb
hosted with ❤ by GitHub

Это просто добавляет кнопку, которая отправит запрос на публикацию на сервер. Нам нужно добавить обработчик для обработки этого запроса, поэтому добавьте следующий код после корневого обработчика:

post ‘/time’ do
@time = Time.now.strftime(«%I:%M:%S»)
redirect ‘/’
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

Это устанавливает переменную экземпляра с именем @time Давайте попробуем получить доступ к переменной @time Добавьте следующее в представление @@index

@@index
h1 Sinatra Flash
form action=«/time» method=«POST»
input type=«submit» value=«What Time Is It?» title=«What time is it?»
p The time is #{@time}

view raw
gistfile1.rb
hosted with ❤ by GitHub

Теперь перезапустите сервер (нажмите одновременно клавиши «Ctrl» и «C», а затем повторно введите ruby main.rb Попробуйте нажать «Сколько сейчас времени?» кнопку, и вы должны увидеть следующее:

Это верно, время не показывает. Это потому, что значение @time Нам нужно использовать вспышку, чтобы передать ее следующему запросу. Измените обработчик сообщения на следующее:

post ‘/time’ do
flash[:time] = Time.now.strftime(«%I:%M:%S»)
redirect ‘/’
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

И измените представление индекса на следующее:

@@index
h1 Sinatra Flash
form action=«/time» method=«POST»
input type=«submit» value=«What Time Is It?» title=«What time is it?»
p The time is #{flash[:time]}

view raw
gistfile1.rb
hosted with ❤ by GitHub

Теперь перезагрузите сервер, перезагрузите страницу и попробуйте нажать «Сколько времени?» кнопка. Если все работает правильно, вы должны увидеть отображаемое время:

В предыдущем примере показано, как установить и отобразить флэш-память, используя синтаксис flash[:time]:time Вспомогательный метод flash[:key] Вы можете использовать разные ключи, чтобы соответствовать разным сообщениям, как мы увидим в следующем разделе.

Магазин Flash Farm

Теперь, когда мы увидели вспышку в действии, я собираюсь создать простой сайт в стиле интернет-магазина, который демонстрирует наиболее распространенные варианты использования вспышки. Я создал несколько фотографий животных, чтобы показать скот нашего магазина, который вы можете увидеть ниже:

*** картинки с животными

Для начала давайте изменим представление индекса, чтобы оно отображало некоторые продукты для продажи:

@@index
h1 The Flash Farm Shop!
p Choose which animals you would like to buy from our shop.
ul#animals
li
h2 Duck
img src=«/duck.png»
form action=«/buy/duck» method=«POST»
input type=«submit» value=«Add to Basket» title=«Buy me, quack!»
li
h2 Pig
img src=«/pig.png»
form action=«/buy/pig» method=«POST»
input type=«submit» value=«Add to Basket» title=«Buy me, oink!»
li
h2 Cow
img src=«/cow.png»
form action=«/buy/cow» method=«POST»
input type=«submit» value=«Add to Basket» title=«Buy me, moo!»
form action=«/checkout» method=«POST»
input type=«submit» value=«Checkout» title=«Checkout»

view raw
gistfile1.rb
hosted with ❤ by GitHub

Обратите внимание, что вам нужно будет сохранить изображения животных в папке с именем public в том же каталоге, что и файл main.rb

У каждого животного есть кнопка «Добавить в корзину» под его кнопкой, поэтому давайте добавим обработчик, чтобы сделать это при нажатии кнопки. Добавьте следующий код после других обработчиков:

post ‘/buy/:animal’ do
#code that adds an animal to the shopping basket goes here
flash[:success] = «A #{params[:animal]} was successfully added to your basket»
redirect ‘/’
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

При этом используется параметр :animalparams Это может быть использовано для создания обобщенного URL для добавления животного в корзину покупок. На самом деле мы не собираемся реализовывать какие-либо функциональные возможности интернет-магазина в этом учебном пособии, просто имитируем его, поэтому комментарий в начале обработчика просто показывает, что именно в этом заключается ваша логика для реализации следующей важной вещи в электронной коммерции , Затем мы сохраняем во флэш-памяти сообщение о том, что процесс прошел успешно. Если вы попытаетесь проверить это в данный момент, ничего не появится, потому что мы не поместили сообщение в представление. Мы собираемся поместить сообщение в макет, чтобы оно отображалось в верхней части главной страницы, а также чтобы оно отображалось на всех страницах. Измените вид макета на следующий:

@@layout
doctype html
html
head
meta charset=«utf-8»
title The Flash Farm Shop
link rel=«stylesheet» media=«screen, projection» href=«/styles.css»
body
if flash[:success]
.flash== flash[:success]
== yield

view raw
gistfile1.rb
hosted with ❤ by GitHub

Это должно работать — когда вы нажимаете кнопку «Добавить в корзину» под каждым животным, в верхней части страницы должно появиться сообщение.

Вы можете заметить, что в макете также есть ссылка на таблицу стилей. Это потому, что теперь наша флеш-функциональность работает, пришло время придать ей немного стиля. Одна из вещей, которые мне нравятся в Sinatra, это то, как вы можете легко добавлять новые функции в один файл. Чтобы добавить стили с помощью Sass, все что нам нужно сделать, это добавить новый вид внизу main.rb Вот несколько стилей для начала:

@@styles
.flash{
width: 600px;
padding: 5px;
font-weight: bold;
margin: 20px;
background:#ddd;
color:#666;border:1px solid #ccc;
}
#animals{
overflow: hidden;
padding:0;
li{
float:left;
list-style:none;
margin: 0 10px 0 0
}
}

view raw
gistfile1.scss
hosted with ❤ by GitHub

Теперь все, что нам нужно, это поместить следующий обработчик, чтобы убедиться, что scss используется для предварительной обработки этих стилей:

get ‘/styles.css’ do
scss :styles
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

Теперь перезапустите сервер и страницу, и вы должны увидеть более приятный внешний вид магазина!

Разные вспышки

Как мы видели ранее, вы можете использовать разные клавиши во флэш-памяти для разных целей. Допустим, мы также хотим предоставить некоторую дополнительную информацию при заказе утки. Давайте изменим обработчик, чтобы добавить эту дополнительную информацию во флэш-память:

post ‘/buy/:animal’ do
animal = params[:animal]
#code that adds an animal to the shopping basket goes here
flash[:success] = «A #{animal} was successfully added to your basket»
flash[:warning] = «Warning! Buying too many ducks can drive you quackers» if animal == ‘duck’
redirect ‘/’
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

Чтобы убедиться, что все флеш-сообщения с ключом :info

@@layout
doctype html
html
head
meta charset=«utf-8»
title The Flash Farm Shop
link rel=«stylesheet» media=«screen, projection» href=«/styles.css»
body
if flash[:success]
.flash== flash[:success]
if flash[:warning]
.flash== flash[:warning]
== yield

view raw
gistfile1.rb
hosted with ❤ by GitHub

Добавление всех этих строк кода для каждого типа флэш-сообщений может стать очень раздражающим и не очень СУХИМЫМ. Другая проблема может заключаться в том, что вы не знаете, какие флэш-клавиши будут использоваться при создании макета. Это легко решается с помощью очень удобного вспомогательного метода styled_flash Это происходит в любом из ваших представлений и повторяется по всей флэш-памяти, отображая все сообщения внутри их собственного элемента div, который имеет тот же класс, что и клавиша флэш-памяти. Все, что нам нужно сделать, это изменить наш макет следующим образом:

@@layout
doctype html
html
head
meta charset=«utf-8»
title Sinatra Flash
link rel=«stylesheet» media=«screen, projection» href=«/styles.css»
body
== styled_flash
== yield

view raw
gistfile1.rb
hosted with ❤ by GitHub

Это создаст следующую разметку:

<div id=’flash>
<div class=’flash success>
A cow was successfully added to your basket
</div>
<div clash=’flash warning>
Warning! Buying too many ducks can drive you quackers
</div>
</div>

view raw
gistfile1.html
hosted with ❤ by GitHub

Теперь у нас есть несколько стилей, которые позволяют нам стилизовать каждый тип сообщения немного по-разному. Ниже приведены несколько стилей, которые я выбрал из уведомлений Twitter Bootstrap:

@@styles
.flash{
width: 600px;
padding: 5px;
font-weight: bold;
margin: 20px;
background:#ddd;
color:#666;border:1px solid #ccc;
}
.info{
background:#D9EDF7;
color:#3A87AD;
border:1px solid #BCE8F1;
}
.warning{
background:#FCF8E3;
color:#C09853;
border:1px solid #FBEED5;
}
.success{
background:#DFF0D8;
color:#468847;
border:1px solid #D6E9C6;
}
.error{
background:#F2DEDE;
color:#B94A48;
border:1px solid #EED3D7;
}
#animals{
overflow: hidden;
padding:0;
li{
float:left;
list-style:none;
margin: 0 10px 0 0
}
}

view raw
gistfile1.scss
hosted with ❤ by GitHub

Перезапустите сервер и протестируйте это, и вы должны увидеть красиво оформленную страницу, которая выглядит так же, как это делают профессионалы:

Проверять, выписываться

Теперь, когда у нас много разных стилей, пришло время протестировать их все. Для этого я собираюсь реализовать функцию фиктивной проверки. Кнопка уже есть в макете, поэтому нам нужен только обработчик:

post ‘/checkout’ do
n = rand(3)
flash[:error] = «There was an error processing your payment» if n == 0
flash[:success] = «Your payment was successful» if n > 0
redirect to(‘/discount’) if n == 2
redirect to(‘/finish’)
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

Я придумал пример, который позволяет нам давать разные сообщения пользователям. Чтобы начать с обработки платежей во Flash Farm, не все в порядке, и существует вероятность того, что что-то пойдет не так, как в 1 к 3, поэтому во флэш-памяти отображается сообщение об ошибке. Чтобы восполнить это, есть шанс 1 к 3, что скидка будет применена. Это включает в себя перенаправление на страницу «/ discount», поэтому давайте добавим обработчик для этого:

get ‘/discount’ do
# discount logic goes here
flash[:info] = «A discount of 10% was applied to your order»
redirect to(‘/finish’)
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

Вы также заметите, что когда процесс оформления заказа завершится, вы будете перенаправлены на страницу «/ finish», так что для этого также потребуется обработчик:

get ‘/finish’ do
flash[:message] = «Thank you for shopping at Flash Farm, please come baaa-ck soon!»
slim :index
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

Я снова использую представление @@index

Если у вас есть тестирование, вы должны заметить, что есть несколько проблем. На самом деле все в порядке — вспышка работает так, как мы описали ранее. Прежде всего, если применяется скидка, то отображается сообщение о скидке, а сообщение об успешной оплате — нет. Это связано с тем, что флэш-память отбрасывает все сообщения после одного запроса, поэтому сообщение об успешном завершении было удалено, когда оно было перенаправлено на страницу скидки. Есть простой способ обойти это, используя удобный метод flash.keep

get ‘/discount’ do
# discount logic goes here
flash.keep
flash[:info] = «A discount of 10% was applied to your order»
redirect to(‘/finish’)
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

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

Другая проблема заключается в том, что сообщение с благодарностью за покупки на ферме Flash не отображается при посещении страницы «/ finish». Опять же, здесь все в порядке, просто предполагается, что флэш-память должна отображаться при следующем запросе, а не при текущем запросе. Попробуйте перезагрузить страницу, после чего появится сообщение. Как вы уже догадались, есть способ обойти это, flash.now

get ‘/finish’ do
flash.now[:message] = «Thank you for shopping at Flash Farm, please come baaa-ck soon!»
slim :index
end

view raw
gistfile1.rb
hosted with ❤ by GitHub

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

Это все люди

Это почти все, что есть в сиянии синатры. Это аккуратный маленький кусочек кода, который блестяще справляется со своей работой, надеюсь, вы найдете его полезным. Это также отличный пример того, как сделать расширение Sinatra. Если вы посмотрите на код в Git Hub , вы увидите, что в нем менее 50 строк кода. Зайдите и прочитайте — вы найдете несколько хороших советов о том, как работают расширения Синатры. Я загрузил готовый сайт Flash Farm на Heroku и поместил код на Git Hub . Не стесняйтесь задавать любые вопросы в комментариях ниже.