Flash — это удобный маленький вспомогательный метод в Rails, который позволяет хранить информацию между запросами. Когда ваше приложение обрабатывает запрос, оно обычно заканчивается перенаправлением на другой URL, который генерирует другой запрос. Флэш — это хеш-подобный объект, который хранит временные значения, такие как сообщения об ошибках, чтобы их можно было извлечь позже — обычно по следующему запросу. Он также удаляет информацию после ее использования.
Sinatra Flash — это аккуратное маленькое расширение, написанное Стивеном Эли. Он включает в себя все функциональные возможности Rails Flash, но, в соответствии с минималистским характером Синатры, использует гораздо меньше кода.
Установка
Прежде всего нам нужно установить гем sinatra-flash, вот так:
gem install sinatra-flash
Чтобы опробовать базовую функциональность, нам понадобится простое приложение Sinatra. Создайте файл с именем ‘main.rb’, который содержит следующий код:
require ‘sinatra’ | |
require ‘slim’ | |
require ‘sinatra/flash’ |
Это драгоценные камни, необходимые для нашего основного приложения — очевидно, Sinatra, и я использую движок Slim для рендеринга (не стесняйтесь использовать другой, такой как erb или haml, если хотите). Чтобы использовать Sinatra Flash, нам нужен драгоценный камень. Sinatra Flash использует сессии для хранения данных от одного запроса к другому. Сессии по умолчанию отключены в Sinatra, но их легко использовать, просто добавьте следующую строку после обязательного:
enable :sessions |
Далее мы создадим простой обработчик для нашей индексной страницы:
get ‘/’ do | |
slim :index | |
end |
Здесь ничего особенного не происходит, он просто отображает индексное представление, когда пользователь переходит к корневому URL. Нам понадобится макет и некоторые основные виды, чтобы начать работу. Я собираюсь использовать потрясающие встроенные представления Синатры, чтобы я мог хранить все в одном файле. Просто поместите объявление __END__
Вот очень простой HTML5 макет и представление, которое просто отображает заголовок.
__END__ | |
@@layout | |
doctype html | |
html | |
head | |
meta charset=»utf-8″ | |
title Sinatra Flash | |
body | |
== yield | |
@@index | |
h1 Sinatra Flash |
Давайте проверим это. Откройте окно командной строки и перейдите в папку, содержащую файл 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?» |
Это просто добавляет кнопку, которая отправит запрос на публикацию на сервер. Нам нужно добавить обработчик для обработки этого запроса, поэтому добавьте следующий код после корневого обработчика:
post ‘/time’ do | |
@time = Time.now.strftime(«%I:%M:%S») | |
redirect ‘/’ | |
end |
Это устанавливает переменную экземпляра с именем @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} |
Теперь перезапустите сервер (нажмите одновременно клавиши «Ctrl» и «C», а затем повторно введите ruby main.rb
Попробуйте нажать «Сколько сейчас времени?» кнопку, и вы должны увидеть следующее:
Это верно, время не показывает. Это потому, что значение @time
Нам нужно использовать вспышку, чтобы передать ее следующему запросу. Измените обработчик сообщения на следующее:
post ‘/time’ do | |
flash[:time] = Time.now.strftime(«%I:%M:%S») | |
redirect ‘/’ | |
end |
И измените представление индекса на следующее:
@@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]} |
Теперь перезагрузите сервер, перезагрузите страницу и попробуйте нажать «Сколько времени?» кнопка. Если все работает правильно, вы должны увидеть отображаемое время:
В предыдущем примере показано, как установить и отобразить флэш-память, используя синтаксис 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» |
Обратите внимание, что вам нужно будет сохранить изображения животных в папке с именем 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 |
При этом используется параметр :animal
params
Это может быть использовано для создания обобщенного 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 |
Это должно работать — когда вы нажимаете кнопку «Добавить в корзину» под каждым животным, в верхней части страницы должно появиться сообщение.
Вы можете заметить, что в макете также есть ссылка на таблицу стилей. Это потому, что теперь наша флеш-функциональность работает, пришло время придать ей немного стиля. Одна из вещей, которые мне нравятся в 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 | |
} | |
} |
Теперь все, что нам нужно, это поместить следующий обработчик, чтобы убедиться, что scss используется для предварительной обработки этих стилей:
get ‘/styles.css’ do | |
scss :styles | |
end |
Теперь перезапустите сервер и страницу, и вы должны увидеть более приятный внешний вид магазина!
Разные вспышки
Как мы видели ранее, вы можете использовать разные клавиши во флэш-памяти для разных целей. Допустим, мы также хотим предоставить некоторую дополнительную информацию при заказе утки. Давайте изменим обработчик, чтобы добавить эту дополнительную информацию во флэш-память:
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 |
Чтобы убедиться, что все флеш-сообщения с ключом :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 |
Добавление всех этих строк кода для каждого типа флэш-сообщений может стать очень раздражающим и не очень СУХИМЫМ. Другая проблема может заключаться в том, что вы не знаете, какие флэш-клавиши будут использоваться при создании макета. Это легко решается с помощью очень удобного вспомогательного метода 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 |
Это создаст следующую разметку:
<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> |
Теперь у нас есть несколько стилей, которые позволяют нам стилизовать каждый тип сообщения немного по-разному. Ниже приведены несколько стилей, которые я выбрал из уведомлений 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 | |
} | |
} |
Перезапустите сервер и протестируйте это, и вы должны увидеть красиво оформленную страницу, которая выглядит так же, как это делают профессионалы:
Проверять, выписываться
Теперь, когда у нас много разных стилей, пришло время протестировать их все. Для этого я собираюсь реализовать функцию фиктивной проверки. Кнопка уже есть в макете, поэтому нам нужен только обработчик:
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 |
Я придумал пример, который позволяет нам давать разные сообщения пользователям. Чтобы начать с обработки платежей во 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 |
Вы также заметите, что когда процесс оформления заказа завершится, вы будете перенаправлены на страницу «/ finish», так что для этого также потребуется обработчик:
get ‘/finish’ do | |
flash[:message] = «Thank you for shopping at Flash Farm, please come baaa-ck soon!» | |
slim :index | |
end |
Я снова использую представление @@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 |
Это просто сохраняет все сообщения, которые хранятся во флэш-памяти для еще одного запроса, поэтому теперь оба сообщения будут отображаться, если применяется скидка.
Другая проблема заключается в том, что сообщение с благодарностью за покупки на ферме 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 |
Это показывает мгновенное сообщение о текущем запросе. Это особенно полезно, если вы используете Ajax для обработки любых запросов в фоновом режиме, поскольку перенаправление не используется, поэтому вам нужно показать сообщение по текущему запросу.
Это все люди
Это почти все, что есть в сиянии синатры. Это аккуратный маленький кусочек кода, который блестяще справляется со своей работой, надеюсь, вы найдете его полезным. Это также отличный пример того, как сделать расширение Sinatra. Если вы посмотрите на код в Git Hub , вы увидите, что в нем менее 50 строк кода. Зайдите и прочитайте — вы найдете несколько хороших советов о том, как работают расширения Синатры. Я загрузил готовый сайт Flash Farm на Heroku и поместил код на Git Hub . Не стесняйтесь задавать любые вопросы в комментариях ниже.