Уеб сайт с Ruby и Sinatra
Базирано на това ръководство от Piotr Szotkowski (@chastell). Код на ръководството в GitHub.
Съдържание
- Какво е това ръководство?
- Запознаване с инструментите – текстови документи и редактори
- Що е то “конзола”? – основни понятия, съвети и упражнения
- Основи на HTML и CSS
- Блиц-увод в програмирането – данни и код, променливи, действия (методи/функции), условия, цикли и изрази
- Представяне на идеята за приложението – какво е интернет, какво е уеб приложение, защо Sinatra, инсталиране на Sinatra и документация
- Първо работещо приложение! и стартиране на приложението
- Добавяне на начална страница с формуляр за гласуване и преместване на HTML-а в отделен файл (view)
- Добавяне на страница след успешно гласуване
- Показване на резултати
- Реално отчитане на гласовете
- Опционални задачи – добавяне на layout, качване на приложението на Heroku, трайно съхранение на гласовете и други
Какво е това ръководство?
Това ръководство представлява кратък увод в основите на създаването на уеб приложения. Предназначено е за напълно начинаещи или хора с минимален опит. В ръководството се минава през няколко стъпки, като крайният резултат е едно малко уеб приложение за гласуване. Засягат се и се използват технологиите HTML, CSS, Ruby, Sinatra. Работи се в конзола (shell).
Предполага се, че ръководството се прави с помощта на инструктор, който да дообяснява нещата, които не са покрити в текста, да отговаря на въпросите на четящия и да го напътства. Това, разбира се, не пречи да бъде направено и изцяло самостоятелно.
- Един готов и работещ вариант на примерно приложение може да бъде изпробван тук.
- Кодът на това примерно приложение, в неговата цялост, може да бъде разгледан тук.
- Историята на промените по кода съответства приблизително и на стъпките в това ръководство. Може да я прегледате тук.
Ръководството по-долу прави предположението, че вече имате работеща среда, в която да изпълнявате примерите. Най-удобно за тази цел е да си направите регистрация в Github и да си създадете нов Codespace, използвайки Blank Template.
Запознаване с инструментите
Преди да започнем да правим каквото и да е, трябва да се запознаем с инструментите, които ще използваме. В нашия случай, това са обикновен текстов редактор (например Notepad) и интегрираната онлайн среда за разработка Github Codespaces.
Всеки майстор има нужда от определен набор инструменти и си има собствена работилница, в която твори. Вместо да ви караме да отделяте време, за да се снабдите с всички необходими инструменти и да си обзаведете собствена работилница специално за това събитие, ние ще използваме една готова такава – услугата Github Codespaces.
Инструктор:
Това е добър момент да влезете с участничките си в техния профил в Github и да създадете нов Codespace, използвайки Blank Template, ако все още липсва такъв. Ползват се основно 3 неща от интерфейса – дървото с файлове в левия панел, текстовия редактор в центъра и Bash конзолата, която е в долния панел, под текстовия редактор. Средите “заспиват” автоматично след 30 минути неактивност. При повторно отваряне, с помощта на бутон се “събуждат”.
Обяснете основните компоненти на интерфейса в Codespaces, без да навлизате в твърде много детайли – къде стоят файловете, къде е този сървър (компютър в “облака”). Обяснете какво всъщност замества тази услуга – текстов редактор, конзола, файлова система, стартиране на процеси. Посочете коя част от интерфейса на кой инструмент отговаря. По-долу ще се разгледат основните инструменти в повече детайли.
Текстови документи и текстови редактори
Програмистите обикновено пишат код в текстови файлове, тъй като “кодът” е най-обикновен текст. Текстовите файлове са просто файлове с чист текст вътре – без никакво специално форматиране. Интересен факт е, че Word документите не са текстови файлове – дори да не сте приложили никакво форматиране на текста. Самият Word файл съдържа специални и нечетими символи вътре, които се ползват като “служебна” информация, когато в Word документа има приложено форматиране. За илюстрация, може да опитате да отворите Word документ с Notepad – ще видите нечетимите символи, които са служебна информация за Word и които той не ви показва.
Името на текстовите документи често завършва на .txt
, но е напълно възможно това окончание (наричано още файлово разширение) да бъде друго, например .html
, .rb
, или пък да няма разширение изобщо – например README
. Името на файла няма директно отношение към съдържанието на файла. Един файл може да се казва photo.jpg
и вътре да има обикновен текст. Разбира се, ако опитате да отворите файла с програма за обработка на изображения, ще получите грешка, но пък ако го отворите с Notepad, ще видите текстовото му съдържание.
За редакция на файловете с код в това ръководство ще използваме т.нар. “текстови редактори”. Това са програми, които са предназначени за редакция на обикновен текст. Notepad е такава програма в Windows. В онлайн средата Github Codespaces също има вграден такъв текстов редактор. Някои текстови редактори предлагат допълнителни помощни функции като автоматично оцветяване на различните специални команди според типа код вътре, но по същество са си най-обикновени текстови редактори.
Конзола (терминал, Command Prompt)
Нещо, което ще използвате в средата си за разработка, е един вариант на така наречената “конзола” (console). Конзолата обикновено представлява един черен екран с бели или зелени букви текст в нея и нищо друго:
Като синоними на конзола ще срещате още терминал (terminal), команден ред (command line или Command Prompt) или Shell. Например, Command Prompt е името на конзолата в Windows. Всеки Windows си има вградена такава. Може да стартирате Command Prompt в Windows като натиснете Win
+ R
и в отворилия се прозорец “Run” напишете cmd
и натиснете Enter
.
В конзолата се пишат команди като текст и резулатът се показва като текст. Реално, конзолата е софтуер, с който може да управлявате компютъра си и “конзола” е нещо като събирателно понятие за този тип софтуер за взаимодействие с компютър.
Интересен факт за конзолите е, че първият интерфейс към компютрите е бил такъв – изцяло текстов, със зелени или бели букви на черен екран (уверете се сами). Логичен въпрос тук е “Защо ме занимават с толкова стар начин за взаимодействие с компютър?” А може би е интересно да се запитаме и защо все още има такива неща като конзола в съвременните компютри?
В интерес на истината, програмистите често използват някаква разновидност на конзола в ежедневната си работа. Причината за това е много проста – конзолата е бърз и ефективен начин да свършим нещо. Защо?
Конзолата има много прост принцип на действие – има поле, в което пишем команди под формата на текст, натискаме Enter
, командата се изпълнява и виждаме резултата от изпълнението ѝ също като текст. Ако сме написали невалидна (несъществуваща) команда, или сме объркали нещо друго, ще ни се изпише съобщение за грешка. След изпълнението на командата, отново ни се показва познатото поле за писане на команда.
Някои възможности на конзолата:
- Можем да стартираме програми и да спираме програми директно от конзолата. Програмите може дори да нямат видими прозорци, могат да вършат работа във “фонов” режим.
- Имаме достъп до цялата файлова система – всички папки и файлове – и можем да правим с тях каквото си искаме. Можем да се движим по папките, да разглеждаме и манипулираме файлове, като ги преименуваме, местим, трием или създаваме.
- Можем да навръзваме неограничен брой команди, като подадем резултата (изхода) от една команда към входа на друга.
- Можем да имаме стартирани повече от една конзола в даден момент от времето и във всяка от тях да правим различни неща.
- Имаме бързи клавиши и auto-complete (с клавиша
Tab
), който ни дописва неща като имена на команди, файлове и папки. - Имаме история на всички изпълнени до момента команди (като натискаме бутоните
↑
/↓
на клавиатурата докато сме в конзолата) и можем да разглеждаме, променяме или пускаме предишни команди. - Лесно можем да автоматизираме работата си, като запазваме поредици от команди във файл и после направо изпълняваме запазената поредица.
И много други. Това са някои от причините да виждате и днес програмисти и системни администратори масово да пишат текст в тяхната разновидност на конзола или терминал. В днешно време можем да си нагласяме цвета на фона (например бял, полупрозрачен или изображение), цвета, размера и шрифта на текста и дори някои команди ни показват резултат в цветен текст, но принципът на действие си е същият. Вижте пример за по-шарена конзола.
Хайде да запретнем ръкави и да станем бързо майстори на конзолата!
Основни понятия за конзолите
- (Command) prompt – това е полето, в което пишете командата си, или, по-точно, текстът вляво от него. Т.нар. “prompt” се изобразява различно в различните конзоли и текстът вляво може да варира, но обикновено е валидно следното – текстът вляво показва текущата ви директория (вж. следващото понятие) и е последван от символа
$
или>
, след който можете да пишете команди. Мястото за писане обикновено е обозначено от правоъгълен, плътен и “светещ” курсор. Може би вече се досещате откъде идват и имената на някои конзоли. - Текуща директория – папката, в която се намира текущата конзола (обикновено можем да си пуснем повече от една конзола). Тази папка е папка от вашата файлова система. Всички файлове и подпапки на текущата ви директория могат да бъдат реферирани просто с името си. Например, ако текущата ви директория е
C:\RailsGirls
и в тази папка имате файлnotes.txt
, ще можете да го отворите с Windows Notepad като изпълните командатаnotepad notes.txt
. Ако текущата ви директория бешеC:\Documents and Settings\Radostina
, тогава за да отворите същия файл в Notepad, ще ви трябва командатаnotepad C:\RailsGirls\notes.txt
. - Команди и параметри – командите в конзолата имат проста структура –
име-на-команда параметър1 параметър2 ...
. Името на командата винаги е първата дума от реда с командата, след което може да следват т.нар. “параметри”. Параметрите са неща, които са необходими на текущата команда, за да си свърши работата. Тези параметри винаги се разделят с интервали. Тоест, името на командата са символите до първия интервал. След това, ако има параметри, първият параметър е от първия интервал до втория интервал и т.н. Има два типа команди – вградени и външни. - Вградени команди – вградените команди са неща, които се разпознават и изпълняват директно от конзолата ви. Това са команди като
cd
(“change (current) directory”),pwd
(“print (current) working directory”; в Windows:echo Current folder: %cd%
),ls
(“list files”; в Windows:dir
) и други. - Външни команди – външните команди са просто имената на програми, които са инсталирани на определено място на компютъра, на който работи конзолата. Например, ако напишете
notepad
в Command Prompt в Windows, това не е една от вградените команди там и затова Command Prompt ще потърси програма, която се казваnotepad.exe
в няколко специално определени за целта папки и ако намери такава програма, ще я стартира. Ако не намери такава програма, ще получите грешка за непозната команда.
Практически съвети за конзолите
- Използвайте този пищов с често срещани команди.
- Възможно е да стартирате програма, която да “обсеби” вашата конзола. Ще познаете, че това се е случило, ако последния ред текст в конзолата ви не е обичайния ви command prompt. В тези случаи, обикновено може да прекратите работата на работещата програма с клавишната комбинация
Ctrl
+C
. Ако програмата, която работи, ви дава възможност да пишете, може да пробвате да я спрете, като напишетеexit
илиquit
. Ако не стане – пробвайте сCtrl
+C
.
Примери и упражнения
Windows: Създаване на папка и файл през конзолата, показване съдържанието на файла в конзолата и отваряне на файла с текстов редактор:
Други полезни команди и вариации на такива в Windows (помолете инструктора си за обяснение какво прави всяка една от тях):
Mac OS X и Linux: Създаване на папка и файл през конзолата, показване съдържанието на файла в конзолата и отваряне на файла с текстов редактор (в Linux отварянето на файл с текстов редактор трябва да стане по различен начин, например с gedit hello.txt
):
Други полезни и често срещани команди под Mac OS X и Linux (помолете инструктора си за обяснение какво прави всяка една от тях):
Честито! Вече сте майстори на конзолата! За награда, може да се насладите на този комикс.
Инструктор:
Упражнете командите по-горе и техни вариации, като направите това в Command Prompt и/или в Shell-а в Github Codespaces и разяснете нещата, които не са ясни.
In HTML we trust - статичен сайт
HTML е основният градивен блок на сайтовете. Преди да се занимаем с това приложение, ще покрием основни понятия в HTML и CSS с помощта на вашия инструктор.
В това упражнение ще създадете една малка страничка, която илюстрира основни принципи в HTML. Може да видите примерния очакван резултат тук. Знаете ли, че можете да разгледате HTML и CSS кода на всеки сайт? Питайте вашия инструктор как.
Алтернативно, ако ви е по-интересно, може да създадете и една семпла страничка, която да играе ролята на ваша визитка. Пример за такава може да видите тук.
Незадължително, ако ви остане време тук, или в края на събитието. Направете си безплатен профил в GitHub и използвайте това ръководство, за да публикувате току-що създадената страничка онлайн, на безплатния хостинг на GitHub за статични страници. Ако потребителското ви име е radostina, то сайтът ви ще се намира на адрес https://radostina.github.io
.
Инструктор:
Примерите по-долу могат да се тестват лесно в Github Codespaces, като вляво, от таба Extensions се инсталира Preview. След това вляво се създаде и отвори за редакция един
something.html
файл там и с десен бутон се избере “Open Preview”. Това preview ще се отвори в панел в Codespaces. За да се отразят промените, които се направили по файла, изберете отново “Open Preview”.
Друг вариант да показвате примерите по-долу, е с Notepad или Notepad2 на лаптопите на участничките, без да се занимавате с Github Codespaces. За целта, може да изтеглите Notepad2 (директен линк, x86), за да е цветен HTML-ът, който ще показвате тук. Notepad2 е добър вариант за Windows, тъй като е много лек и прост, прилича на вградения Notepad и няма излишни неща в интерфейса.
Забележка: На Windows е добре да изключите опцията, която крие разширенията на файловете - инструкции тук.
Примерен план за обяснения:
- HTML са командите, с които караме браузърите да рисуват неща по екрана. Суха дефиниция. След малко ще я илюстрираме. Тук е добър момент да се каже каква е ролята на HTML в интернет, защо показваме HTML и защо започваме с него – HTML е технология (не точно език за програмиране), която е градивното блокче на интернет и на която стъпва визуализацията на всички сайтове - това е, което се точи по жицата до нашия компютър.
- HTML е просто текст. Всеки текст е и HTML. Започва се с обикновен текстов файл, с разширение
.html
. Може да ползвате Notepad, или Notepad2, инсталиран в предишната стъпка, като направите уточнението, че и с Notepad става, просто с Notepad2 е цветно. Плюсът на Notepad е, че може да се демонстрира как само с вградените в операционната система инструменти, човек може да твори HTML. Бонус е когато впоследствие HTML файлът бъде отворен с по-умен редактор и когато се покаже оцветяването и нещата, които редакторът дава. Във файла участничките пишат “Къде да обядваме?” на първия ред, оставят един празен ред и допълват с няколко имена на заведение, като всяко е на отделен ред. Ако правят визитка, вместо това може да си напишат името на първия ред, оставят празен ред и да напишат едно-две изречения за себе си, пак на отделни редове. Файлът се отваря с браузър. Всичко се вижда, но е на един ред. Изводи - какво значи whitespace-а за HTML (а и какво е “whitespace”).- HTML таговете са начални и крайни маркери. Задават структура. Имат сурова визия по подразбиране. Нека оградят първия ред с
<p>
таг. Може да го напишете на хартия, за да видят отварящия и затварящия таг и с какви скоби са. Може да им отнеме малко време да намерят символите на клавиатурата. Добре е те да си напишат тага. Запазете файла и презаредете браузъра. Обсъдете резултата - името е с големи букви и е на отделен ред. Вкарайте<h1>
след това. Споменете за различните видове h1, h2, …- Може да покажете таговете за линк, картинка и нов ред. Обърнете внимание, че таговете
<img>
и<br>
са едни от малкото, които нямат съответен затварящ им таг. Като покажете нов таг, дайте мнемоника, с която да го запомнят (img
= image,br
= (line) break,p
= paragraph,h*
= heading,a
= anchor,ul
= unordered list,li
= list item и т.н.)- Браузърите са толерантни към невалиден HTML – това, което сме създали, формално погледнато, е само парченце от цялостен HTML документ и е невалиден такъв документ, според формалната дефиниция. Но работи. Кажете какво друго има обикновено в един валиден HTML документ –
<html>
,<head>
,<body>
.- Обяснете защо има нужда от
<body>
и<head>
– в body слагаме видимото съдържание, а в<head>
неща, които са по-скоро допълнителна информация за документа – например, инструкции към търсещи машини като Google, допълнителни инструкции за браузърите и други. Може да дадете пример и с тага<title>
, който реално задава заглавието на таба в браузъра.CSS е за визия, оформление, шарено – HTML е създаден 1993 г., а CSS - 1996 г. Първоначално е имало само HTML. Добавете следния ред код в примерния HTML, някъде в
<head>...</head>
секцията, за да приложите примерно стилизиране (CSS-ът е направен за примерния HTML по-долу):<link rel="stylesheet" type="text/css" href="voter.css">
Това ще демонстрира как се променя един и същ HTML след прилагане на стилове. Стиловете може да се видят тук. Определено покажете CSS Zen Garden - идеята на този сайт е, че HTML-ът е един и същ, но има различни CSS стилове, които коренно променят визията на сайта. Има линкове в самия сайт към алтернативните визии.
Друг много полезен и интересен пример, който може да се покаже, е този сайт, който прогресивно добавя стилизиране над собственото си съдържание.
Финално, cssicon.space демонстрира как могат да се създават доста богати визуални елементи с помощта на CSS и минимален HTML.
- При наличие на време и желание, може да покажете как изглежда един CSS документ (например показанията в предната стъпка
voter.css
) и да обясните двете основни неща вътре: селектори (selectors) и правила (properties). Правилата задават конкретен визуален стил – цвят, шрифт, фон, размери и прочее. Селекторите пък указват за кои парчета от HTML документа да важи този конкретен визуален стил.Примерна структура на HTML документ (този пример го има и тук без CSS, тук със CSS, а страничката-визитка тук):
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Машина за гласуване</title> </head> <body> <h1>Добре дошли в машината за гласуване!</h1> <p>Къде да обядваме?</p> <ul> <li>Happy</li> <li>Кривото</li> <li>Мистър Пица</li> <li>Слънце луна</li> </ul> <form> <p> Вашият избор: <input type="text" name="vote"> <button type="submit">Гласувай!</button> </p> </form> <p>Или <a href="https://foursquare.com/">потърсете още места</a>.</p> <p> Добър апетит! </p> <a href="http://www.nipponham.co.jp/files/topics/18678_ext_06_0.jpg" target="_blank" title="Bento Lunch"> <img src="http://www.nipponham.co.jp/files/topics/18678_ext_06_0.jpg" width="300" alt="A photo of a Bento lunch"> </a> </body> </html>
Основи на програмирането с Ruby
Инструктор:
Презентация, покриваща основните концепции от тази секция, може да бъде видяна тук. Не е нужно да минавате през нея с участничките.
Ще изпробваме някои неща с Ruby, като използваме инструмента irb
(съкратено от “Interactive Ruby”).
irb
е името на програма, която идва инсталирана заедно с Ruby. Тя е вид конзола, наречена REPL (read-eval-print loop). Може да я стартирате директно от конзолата (Shell) в Codespaces. irb
наподобява конзола (command line) – пишете Ruby изрази, натискате Enter и irb
ги оценява веднага и ви показва резултата (или грешката, ако има такава). Обърнете внимание, че irb
е различен тип конзола от стандартната ви – командите, които irb
разбира, не са за движение по папките ви, за стартиране на команди или за отваряне и манипулация на файлове – irb
разбира само езика за програмиране Ruby
.
За да стартирате irb
, напишете следната команда в конзолата на Codespaces и натиснете Enter:
irb
Обърнете внимание, че prompt-ът (символите отляво на курсора) ще се сменят с такива от irb
. За да ви е по-удобно, може да увеличите размера на панела с конзолата.
От irb
се излиза с Ctrl
+ D
или като напишете exit
и натиснете Enter.
Инструктор:
Припомнете накратко какво е конзола (синоними: терминал, command line, shell) и разяснете разликата между конзолата и
irb
, тъй като двете си приличат и това може да е много объркващо в началото.Внимание: ако в
irb
има синтактична грешка от типа на незатворена кавичка или скоба и се натисне Enter,irb
няма да изпълни израза и да покаже грешка, а ще чака да “завършите” израза, т.е. да затворите кавичката или скобата. Prompt-ът наirb
също ще се промени на символа, който се очаква в момента. Ето пример:$ irb irb(main):001:0> puts "Hello, world! irb(main):002:0" irb(main):003:0"
В такива случаи, може да се натисне
Ctrl
+D
,Ctrl
+C
, или просто да се въведе липсващият символ.
Данни и код
Програмите боравят с данни. Тези данни трябва да се вземат отнякъде. Или ги зареждате по някакъв начин от външния свят (прочитате от файл, сваляте от интернет, потребител ги попълва), или вие като програмист ги слагате директно в кода.
Данните биват различни типове:
- Текст, още наричан (текстов) низ – нещо, заградено в единични или двойни кавички:
'some text'
,"more text here"
, … - Числа – цели или с плаваща запетая:
5
,42
,3.14
, … - Съставни типове данни – списъци, речници:
["apple", "orange", "pear", "melon"]
,{'one' => 'eins', 'two' => 'zwei', 'three' => 'drei'}
, … - Наши собствени типове данни – продукт, поръчка, потребител, …
Причината за разграничаването на типовете на данните е, че с всеки тип данни могат да се правят различни операции – например, числата могат да се умножават, текстът – не.
Инструктор:
Упражнете основните типове данни и някои операции с тях в
irb
. Съставете списък, намерете му дължината, обходете елементите и ги отпечатайте на екрана. Обърнете внимание на разделението между данни и код.
Имена (променливи)
Ако определени данни ни трябват на повече от едно място в програмата (което е по-честият случай), не е практично да повтаряме вмъкването им всеки път.
Затова в Ruby (и другите езици за програмиране) имаме възможност да дадем име на определени данни. Това име се нарича “променлива” и как се казва променливата си избираме ние. Добре е името да описва ясно смисъла и целта на данните, към които сочи. Насочваме името към данни, като използваме конструкцията име = данни
. Например:
Името participant_name
става налично веднага след този ред код (но не и преди това). След това, правим манипулации над самото име, като реално ще работим с данните, към които името сочи. Например:
Тук puts
е вградена в Ruby ключова дума, която извежда на екрана подадените ѝ данни.
Обърнете внимание, че имената в Ruby са просто имена. Може да насочите повече от едно име към едни и същи данни и да ги променяте от което и да е от имената. Можете и да сменяте накъде сочи дадено име. Например:
Друг интересен момент е, че данните от дясната страна на равенството може да се получат в следствие на динамично изчисление, което, логично, може да включва и други, вече дефинирани променливи:
Инструктор:
Упражнете работа с имена и основни типове данни в
irb
. Покажете как работи повече от едно име към един и същи обект. Може да използвате метод, който променя състоянието на данните in-place, напримерString#upcase!
. Променливите нямат тип и са просто имена/етикети, закачени към обекти.Тук е добър момент да се обърне внимание на разликата между “извеждане на екрана” (например с
puts
) и показване на резултата от даден израз, коетоirb
прави автоматично след всеки израз. Добре е да се спомене и че когато Ruby програмата се изпълнява от файл (ruby program.rb
), а не вirb
, оценките на изразите няма да са видими, а ще се виждат само неща, които са изрично показани на екрана сputs
.
Действия
Както споменахме по-горе, всеки тип данни поддържа определен набор от действия върху него. Може да разглеждаме всеки тип данни в една Ruby програма като обект, над който можем да изпълняваме този набор действия. Общият начин за изпълнение на действие над определени данни е данни.име_на_действие(опции)
. Например:
Това са все действия, дори да не виждате кръгли скоби навсякъде.Поставянето на кръгли скоби след името на действието не е задължително в Ruby.
“Каноничният” формат на записване на горния пример е такъв:
Вероятно така по-лесно може да разпознаете шаблона на извикване на действие. Изпускането на кръглите скоби на места прави израза по-лесно разбираем за четящия кода. Това е една от причините да е позволено в Ruby да ги пропуснете. При изпълнение на действия над числа е позволено да се изпусне и точката, защото е по-естествено да напишем 2 + 2
, отколкото 2.+(2)
, въпреки, че първото реално се обръща вътрешно до второто.
Важно е да се отбележи, че след изпълнението на всяко действие има “резултат” под формата на нови данни. Тоест, всеки израз, който включва изпълнение на действие, си има резултат, който резултат представлява потенциално нови, променени данни. Тези нови данни, на свой ред, също си имат набор от действия, които може да изпълните над тях. Това е и причината да може да “навързвате” действия едно след друго:
Или:
Обърнете внимание, че горният пример е еквивалентен на Date.today().to_s()
.
Възможно е да наричаме данните в Ruby “обекти”. Двете ще използваме като синоними – всички данни в Ruby са обекти и всички данни (обекти) си имат определен набор от валидни действия.
Инструктор:
Упражнете работа с действия върху обекти в
irb
.Забележка: За да ползвате
Date.today
, трябва да изпълните някъдеrequire 'date'
.
Условия
Условията в езиците за програмиране ни дават възможност да напишем “умни” програми, които могат да взимат решения за промяна в логиката си по време на работа на програмата.
Това е сложен начин да опитаме да обясним следния пример:
if условие
изпълни това, ако условието е истина
else
иначе изпълни тази част
end
Например, нека имаме този ред код:
В Ruby, gets
е ключова дума, която пита потребителя за вход. При изпълнение на кода по-горе, Ruby програмата ви ще паузира работата си и ще очаква да въведете данни. Като ги въведете, ще ви ги върне в прогамата като текст. Ако въведете число, това число ще дойде като текст. Например, ако въведете 42
, в програмата си ще го получите като текста "42"
. В случая, искаме да вземем годините на потребителя като число, за да можем да използваме действия, присъщи на числа. Действието to_i
ще извлече числото от текста и ще ни го даде в подходящия тип: "42".to_i
ще ни върне 42
.
След този ред код, можем да съставим условие, което ще промени поведението на програмата в зависимост от входа на потребителя:
Условията имат и други форми. Например, else
клонът не е задължителен. Освен това, имаме възможност да добавим и един или повече elsif
клонове, които да позволяват разклонение на пътя на програмата на повече от две (забележете, че не е elseif
, а е elsif
).
Важно: Когато сравнявате в условия за равенство, го правите с два, а не с един символ за равенство: ==
. Помнете, че един символ =
се ползва за присвояване на стойност на променлива, а две равенства ==
– за сравнение. За сравнение за различие, се използва !=
(четете като “различно”, или “не-равно”).
Инструктор:
Упражнете работа с различни видове условия.
Повторение (цикли)
За какво щеше да ни е да програмираме, ако нямахме начин да накараме компютъра да прави това, в което е най-добър – да повтори едно действие милиарди пъти за част от секундата?
Във всеки език за програмиране има начини да накараме програмата да изпълни част от логиката си определен брой пъти. Това може да е фиксиран брой (например, 10), или неограничен брой пъти, до изпълнение на дадено условие (например, повтаряй това, докато потребителят не въведе текста "exit"
).
Повторенията се наричат още цикли.
В Ruby, както и в други езици за програмиране, има повече от един начин да се стартира един цикъл. Програмистът избира кой начин да използва според ситуацията.
Ето пример за цикъл, който ще се изпълни фиксиран брой пъти:
Обърнете внимание, че в този пример 30
е число (данни) и всъщност 30.times
е изпълнение на действие върху тези данни. Това означава, че 30
може да се замени и с променлива и нещата пак ще работят.
Ето и пример за цикъл, който ще се повтаря неограничен брой пъти, до възникването на определено условие:
Чувствайте се свободни да смените стойността на correct_password в примера по-горе.
Инструктор:
Обърнете внимание на конкатенацията на низове с
+
и на комбинацията междуif
иwhile
. Обходете кода стъпка по стъпка. Упражнете цикли, в комбинация с наученото до момента.
Изрази
Всяка Ruby програма, дори най-кратката, може да се разглежда като съвкупност от изрази.
Всеки израз е просто валидно парче Ruby код, което може да бъде изпълнено самостоятелно без това да доведе до грешка. След изпълнението на всеки валиден израз се получава някакава стойност. Това винаги е така. Стойността е просто някакви данни. Наричаме я оценка на израза.
Всички примери за Ruby код, които разгледахме до момента – всички до един – са валидни изрази. Дори if-else-end
конструкциите. Може да проверите това, като ги paste-нете в irb
и натиснете Enter. irb
ще ги изпълни (оцени) и ако няма грешка, ще ви покаже оценката им (данните, които са резултат от изпълнението на израза).
Това е важен принцип, който трябва да имате предвид. Едно много важно и ценно следствие от него е следното твърдение:
Навсякъде, където работите с данни, можете да ги замените с произволно сложен и валиден Ruby израз.
Например, там, където имате данни.действие(други, данни)
, всъщност може да имате израз.действие(друг_израз, трети_израз)
. Това е много мощен инструмент, който ви дава възможност да комбинирате по-прости изрази с по-сложни и с който може да сте страшно гъвкави при писането на код.
Инструктор:
Упражнете наученото до момента – работа с речници, променливи, низове, изрази и комбинацията между тях. Отговорете на възникналите въпроси, но не влизайте в прекалено много детайли.
Динамичен сайт - за гласуване
След като сме се позабавлявали малко с HTML и CSS, е време да направим следващата важна стъпка – да напишем софтуер, който да създава HTML код вместо нас – и динамично.
Ще създадем малко приложение за гласуване.
Представете си, че планирате хапване с група приятели или колеги. Понякога изборът на място, от което максимално много хора да са доволни, е трудна задача. Програмистите обичаме да си създаваме инструменти, които да ни помагат с решаването на трудни задачи. Това ще е целта и на нашето приложение за гласуване.
Ще го напишем от нулата с помощта на помощна библиотека за правене на уеб сайтове с Ruby, която се казва Sinatra. Sinatra решава вместо нас набор от проблеми, които се срещат често при изработката на един уебсайт. Бихме могли и да не използваме Sinatra, но ще трябва да напишем доста повече Ruby код. Също така, Sinatra е просто един от възможните инструменти, които бихме могли да приложим. Има и други, разбира се (например библиотеката Ruby on Rails). Sinatra е сравнително компактна и семпла библиотека, която въпреки това има много възможности.
Един готов и работещ вариант на примерно приложение може да бъде изпробван тук. Кодът на това примерно приложение, в неговата цялост, може да бъде разгледан тук.
Но какво е всъщност интернет?
За някои от нас, интернет е мястото, чрез което поддържаме връзка с приятелите си, следим последните новини, пазаруваме и играем игри. За други, интернет може да означава техния локален доставчик, скритите под земята мрежи и оптични кабели, които пренасят информация напред и назад през градове и океани. Тогава, кой е прав?
Нека започнем от самото начало - 1974 г. Това е годината, в която няколко компютърни специалисти изобретили нещо, наречено Пакет за интернет протокол (Internet Protocol Suite) или TCP/IP за по-кратко. TCP/IP създали множество от правила, които позволявали на компютрите да си “говорят” помежду си. С други думи, TCP/IP осигуряват правила за комуникация, които гарантират, че свързаните устройства се “разбират” и могат да си изпращат информация. Групата от свързани устройства се увеличила от просто една стая до много стаи, след това до много сгради, а накрая до цели градове и държави и така се родил интернет.
А какво е уеб приложение?
Ако играете онлайн игри, използвате онлайн програма за редактиране на снимки или разчитате на уеб-базирани услуги като Google Maps, Twitter, YouTube или Facebook, то тогава вие сте активен гражданин в света на уеб приложенията.
На английски, web app е съкратено от web application (уеб приложение). Приложенията се наричат още програми или софтуер. Първоначално, те са били създадени, за да извършват големи и обширни задачи като счетоводни услуги или задачи, свързани с обработването на текст. В света на уеб браузърите и смартфоните, приложенията обикновено са бързи програми, фокусирани върху една единствена задача. Уеб приложенията конкретно изпълняват тези задачи в уеб браузъра и често предоставят богато и интерактивно преживяване. Google Maps е добър пример за уеб приложение. То е фокусирано върху една задача - осигуряването на полезни функции за работа с карта директно през уеб браузъра.
Sinatra и Ruby on Rails
След като се отклонихме малко, за да разясним още няколко термина, да се залавяме с истинската работа. Както казахме, ще сглобим нашето уеб приложение с помощта на Sinatra.
Интересен факт е, че името на Rails Girls събитията идва от друга Ruby библиотека за правене на уеб приложения, наречена Ruby on Rails. В първите издания на Rails Girls Sofia използвахме Ruby on Rails в това ръководство, но впоследствие преминахме на Sinatra, която е далеч по-проста и изчистена и е много по-добър вариант за навлизане в света не уеб програмирането.
Инструктор:
Обяснете накратко какво е Sinatra, какво е “библиотека”/”framework” и защо съществуват софтуерните библиотеки изобщо.
Инсталиране на Sinatra
Първо се налага да инсталираме библиотеката Sinatra, която ще използваме. Изпълнете следната команда в конзолата/комадния ред на Codespaces:
gem install sinatra --no-document
Инструктор:
Припомнете и допълнете неща за работа с command line, ако е нужно.
Опцията
--no-document
пропуска генерирането на конзолна документация за Sinatra и значително ускорява процеса по инсталация.
Помощ (документация) за Sinatra
След като сме си инсталирали библиотеката, идва моментът да я използваме. По-долу ще ви даваме необходимия код, който да изпълните стъпка по стъпка, но ако някъде искате да се отклоните от примерите, или ударите на проблем, ще ви е необходима консултация с ръководството (документацията) на библиотеката Sinatra.
Тази документация се намира на адрес: http://www.sinatrarb.com/intro.html
Умението да се намира правилната документация и да се чете и извлича необходимата информация от нея е много важно и често подценявано. Ако търсите нещо там, четете внимателно, осмисляйте и питайте инструктора за това, което не ви е ясно. Не сканирайте диагонално, за да не изпуснете това, което ви трябва.
Създайте своето първо Sinatra приложение
За да започнем нашето приложение, ще създадем един празен текстов файл в папката на нашия Codespaces проект. Преди това, обаче, е добре да изтрием всички други примерни файлове, които са създадени там. Нито един от тях няма да ни трябва, само ще ни пречат. Можете да ги изтриете един по един от дървото с файлове вляво, или да изпълните следната команда в прозореца с конзолата на Codespaces: rm -r *
. Попитайте инструктора си за обяснение на тази команда. Може да използвате и този пищов с помощни команди.
Когато сме почистили излишното от папката на проекта, можем да пристъпим към създаването на празния текстов файл. Може да го кръстим voter.rb
. Създаването може да стане или от терминала, с командата touch voter.rb
, или от графичния интерфейс на Codespaces, с дясно копче върху дървото с файлове. След като го създадете, го отворете в редактора (с двоен клик върху дървото с файлове) и сложете вътре следното съдържание:
В този Ruby файл ще се намира кодът (логиката) на вашето приложение. Можете да кръстите Ruby файла с каквото име желаете. voter.rb
е просто примерно такова.
Стартиране на приложението
От директорията, съдържаща създадения по-горе файл, изпълнете следната команда:
ruby voter.rb
Ще видите да се появяват съобщения на екрана. След няколко секунди, приложението ви би трябвало да е заредило напълно и да е готово да обслужва потребители.
В долния десен ъгъл на екрана ще се появи прозорец, който съдържа URL адреса на вашето приложение. Ако кликнете върху линка Open in Browser, ще се отвори нов раздел в браузъра ви, в който трябва да пише “Здравей, гласоподавателю!”.
Инструктор:
Обяснете за това как се стартират Ruby програми и припомнете, че
ruby
е програма-интерпретатор, посредник между написания в текстовия файл Ruby код и операционната система/компютъра, които не разбират директно Ruby. Говорете за команди и терминал, ако е необходимо. Обърнете внимание, че терминалът е “зает” с изпълнението на процес и това ще остане така, докато не спрем процеса ние, ръчно.Панелите в Codespaces могат да се разместват и да им се променя големината. Могат да се отварят и повече от един таб с конзола, както в долната част на екрана, така и в големия прозорец с редактора, или в панел до него.
Ако правим промени по кода на приложението, ще се налага да го спираме и пускаме, за да се отразят тези промени. Трябва да затваряме и отваряме наново съответния таб в браузъра.
За да спрете приложението си, натиснете клавишната комбинация Ctrl
+ C
, когато фокусът ви е в терминала.
Инструктор:
Обяснете накратко, че кодът около
get
се грижи да посрещне заявките до началната страница на нашето приложение (/
) и да върне отговор и че това, което пише вътре в низа (внимавайте с термините; низ = текст между кавички), е това, което ще се покаже в браузъра на потребителя.Ако прецените, че е удачно на този етап, може да споменете накратко за
HTTP
и как информацията пътува между браузъра и сървъра (request → response). В това ръководство се използва самоHTTP GET
за простота.
Добавяне на начална HTML страница
В примерната “страница” по-горе сложихме едно изречение, но без нито грам HTML. Нека променим това.
Заменете текста 'Здравей, гласоподавателю!'
между единичните кавички със съдържанието на някой от HTML файловете, които сте създали на предните стъпки. Бихте могли да копирате целия файл и да го вмъкнете между единичните кавички и нещата би трябвало да работят.
Възможно е да имате проблем само ако във файла с HTML-а имате единични кавички ('
). Ако това е така, за да помогнете на Ruby да разбере откъде започва и къде свършва вашият HTML, може да използвате %q(
вместо “отваряща кавичка” и )
вместо затваряща. Например така:
Инструктор:
Обяснете какво се случва тук – последният текстов низ в
get
блока в Sinatra реално е това, което Sinatra ще изпрати на браузъра.По-долу този подход се изоставя и се преминава към отделни view файлове, които вече използват ERB, за да има правилно оцветяване на кода и да е по-удобна редакцията – да не трябва да се рестартира приложението при всяка промяна на inline-натия HTML. Въпреки това, ако прецените, че е още рано за ERB и отделни изгледи, може да останете на текущия подход. В този случай, може да ви се наложи да иползвате стрингова интерполация, за да вмъквате Ruby код в текста. Това може да стане като замените единичните кавички около HTML кода с
%Q(
и)
(еквивалент на низ с двойни кавички) и използвате синтаксиса за интерполация#{ruby code here}
, например така:%Q(The answer is: #{40 + 2})
.
Преместване на HTML-а в отделен файл
Подходът по-горе, при който вмъкваме HTML-а директно в Ruby файла на нашето приложение (voter.rb
) работи и е удобен в началото, но има няколко проблема:
- Не виждаме оцветяване на HTML таговете.
- Ако HTML страниците станат няколко, ще стане трудно да се ориентираме в дългия
voter.rb
файл. - За всяка промяна по HTML-а ще се налага да рестартираме приложението.
Можем да решим и трите проблема, ако изведем HTML кода на страниците в отделни, самостоятелни файлове. Така нещата ще са ясни и подредени. Всеки файл ще съдържа само HTML, който ще е отделен от Ruby кода на приложението ни и ще си има правилното оцветяване на HTML таговете.
В контекста на едно уеб приложение, такива отделни файлове с HTML код се наричат още “шаблони за изгледа” (“view templates”, или само “views” накратко). Защо шаблони ще разберете скоро.
За целта, трябва да направим папка в нашия проект, в която ще слагаме тези HTML файлове. Папката трябва да се казва views
(логично, нали?)
Сложете следния код във файл, който се казва index.erb
и се намира в папката views
(т.е. views/index.erb
):
Променете секцията с get
действието във файла voter.rb
така, премахвайки HTML кода от там:
Проверете дали всичко е наред, като спрете и пуснете отново вашето приложение с ruby voter.rb
. Знаете ли, че в терминала имате история на последно изпълнените команди? Като натискате стрелките нагоре и надолу на клавиатурата, ще се движите по тази история, когато в момента няма друга текущо работеща команда.
Очакваният резултат е списък с места за обяд, под формата на радио бутони и бутон “Гласувай!”.
Инструктор:
Обяснете защо HTML-ът, който сложихме в
index.erb
, се генерира от приложението ни (конвенция, приета от Sinatra, която търси файл с това име въвviews/
; ако е нужно, покажете документацията на Sinatra, секцията за изгледи).Обяснете защо избираме точно името “index”.
Предаване на променливи към изгледите
Променете index.erb
файла в папката views
, за да добавите <h1>…</h1>
тагове:
Променете и get
действието по следния начин:
Инструктор:
Обяснете концепцията за шаблони (templates), още наричани “изгледи”. Защо има нужда от това? Обяснете какво е ERB (embedded Ruby) и как става вмъкването на логика (Ruby) в изгледа и как HTML-ът се “динамизира”. Опционално, може да отбележите и че в Ruby има и други начини за генериране на HTML от шаблони (например, Slim, HAML и че ERB е просто една от възможностите.
Споменете накратко, че
@title
е определен вид променлива (в случая, инстанционна) и че това е начин да се предават стойности (променливи) от “действието” (get
) към шаблона на изгледа (index.erb
). За информация на инструктора – причината това да работи е, че в Sinatra и действиетоget
, и изгледите се оценяват в контекста на един и същи Ruby обект. Инстанционните променливи в Ruby могат да се създават динамично и не е нужно да са предварително декларирани. Достъп до недефинирана инстанционна променлива връщаnil
.Обърнете внимание върху ERB таговете
<%= %>
, които не са HTML код, не се виждат в браузъра и служат за изпълнение на Ruby код на сървъра и за вмъкване на резултата в HTML-а, който браузърът ще види.Проверете в браузъра как изглежда вече генерираният HTML, за да се види разликата между шаблона
index.erb
и резултата, който браузърът вижда.
Добавяне на възможност за изпращане на резултатите
Инструктор:
Какво става, когато се гласува в момента? Обърнете внимание на 404 страницата по подразбиране на Sinatra и на информацията на нея. Защо имаме грешка 404?
Добавете следното във voter.rb
:
Създайте нов файл в папката с изгледи views
, който се казва cast.erb
. В него сложете следния HTML и ERB код:
Инструктор:
Обяснете, че нещата в
params
идват от Sinatra и чеparams
е друг вид променлива от тип Ruby речник. Разкажете как се съпоставят полетата от формуляра с нещата вparams
и как можем да ги използваме.
Бонус:
Добавете линк към страницата с резултатите и на началната страница, например до бутона за гласуване.
Показване на резултатите
Добавете следния код във вашето приложение, във voter.rb
:
Създайте и нов шаблон за изглед в папката views
, който кръстете results.erb
:
Стартирайте отново приложението с ruby voter.rb
и проверете дали ще може да видите резултатите.
Инструктор:
Обяснете как работят таблиците в HTML. Обяснете как липсващите стойности от речника се броят като нула (за справка - документацията на
fetch
). Обяснете как така умножаваме текстов низ по число и какъв е резултатът.Припомнете концепцията на типа данни “речник” (хеш). При необходимост, пуснете още един терминал в Codespaces и в него стартирайте
irb
, където демонстрирайте работа с хешове (речници) – създаване, извличане на стойност, добавяне и промяна на елементи, обхождане. Използвайтеputs
където е нужно. Оставете участничките да си поиграят и да осмислят концепциите за променливи. Експериментирайте сfetch
.Помислете заедно защо в момента гласовете не се отразяват изобщо. Съберете идеи какво би трябвало да се промени.
Отчитане на гласовете
Добавете следния код в началото на файла voter.rb
(преди всички действия get
):
След което променете кода в действията cast
и results
в същия файл така:
Спрете и стартирайте отново приложението. Уверете се, че гласовете вече се отчитат правилно. Може да дадете адреса до вашето приложение и на някой друг, за да гласува и той.
Поздравления! Първата бета версия на вашето уеб приложение за гласуване е готова!
Инструктор:
Може участничките да си разменят линковете на приложенията и да гласуват в чуждото приложение.
Обяснете промените. Защо имаме нужда от този
fetch
вcast
? Каква е ролята на променливатаvotes
?(Блоковете в Ruby виждат локалните променливи, дефинирани в closure-a над тях, а действията
get
в Sinatra реално са Ruby блокове. Докато Sinatra работи и уеб приложението е живо, локалната променлива се пази между request-и, като in-memory DB. Инстанционните (тези, започващи с@
) променливи в действията – не се пазят между request-и.)Обърнете внимание на факта, че като се спре приложението, данните се губят.
Опционални и допълнителни задачи
Стъпките по-долу не са задължителни и спокойно можете да спрете с ръководството до тук. Все пак, ако ви е останало време и ви е интересно, можете да си изберете което и да е от нещата по-долу и да пробвате да го реализирате с напътствия от инструктора ви.
Опционално – изнесете общия код в layout
Ако искате да промените текста в <title>
тага, на колко места ще трябва да направите промяната? Ами ако искате да добавите други стилове? А ако искате да вмъкнете header или footer, който да се появява на всяка страница?
За да се избегне повторението на код, което възниква между различните изгледи, обикновено е практика общата част да се изнесе в отделен шаблон – така нареченият “layout”.
Създайте файл layout.erb
в папката с изгледите views
. Сложете там следния код:
След това махнете вече дублиращите се общи части с HTML от другите два шаблона (index.erb
, cast.erb
и results.erb
).
Инструктор:
Обяснете защо се прави тази операция. Разяснете, че другите изгледи се вмъкват на мястото на
yield
и не е нужно да носят информация за общия layout.Обяснете защо кръстихме файла
layout
и защо нещата автоматично сработиха, без да декларираме някъде, че това е нашият layout (Sinatra спазва принципа “convention over configuration” и ако следваме определени правила за кръщаване на файлове и папки, нещата ще работят автоматично, без да има нужда от конфигурация).
Опционално – качете приложението на Heroku
Ако желаете, може да си направите безплатна регистрация в Heroku и да качите приложението, което сте направили до момента, за да може да го ползва всеки, който пожелае.
За целта, може да следвате това ръководство и да помолите инструктора си за съдействие.
Опционално – трайно съхранение на гласовете с YAML::Store
Време е за нещо вълнуващо! Трайно съхранение на данни (persistence). Обикновено това става в СУБД (системи за управление на бази данни), накратко наричани “бази данни”. Примери за някои популярни СУБД са PostgreSQL, MySQL, MS SQL, Oracle и други.
Ние няма да използваме цяла СУБД, а ще пазим данните от гласуването в обикновен текстов файл, който ще се обновява автоматично от нашето приложение. За целта ще ни послужи друга помощна библиотека, която е вградена в езика Ruby, но която трябва да заредим изрично.
Добавете следното в началото на voter.rb
:
Пак във voter.rb
, заменете действията get '/cast'
и get '/results'
със следните версии:
На този етап може да изтриете и реда votes = {}
от voter.rb
, който добавихме на предната стъпка.
Спрете и пуснете отново приложението. Гласувайте и наблюдавайте резултатите. Вижте дали се запазват, ако спрете и пуснете приложението отново. Разгледайте новопоявилия се и автоматично създаден и попълван файл votes.yml
. Би трябвало да се намира в същата папка, където е voter.rb
.
Инструктор:
Обяснете какво е YAML и как се грижи за обновяване на
votes.yml
файла и защо са ниif
-овете в кода по-горе.
Още опционални задачи
Опитайте да промените неща в приложението, за да видите какви ще са резултатите:
- Променете стилизирането на страницата по ваш вкус.
-
Препращайте веднага към резултатите след гласуване.
Инструктор:
Обяснете защо това е добра практика. Например, опитайте да презаредите страницата веднага след гласуване.
-
На колко места трябва да направите промяна, за да добавите ново заведение в списъка? Това добре ли е според вас? Пробвайте да намалите повторението на код в списъка със заведенията, като използвате речник (hash) в Ruby. При нужда от помощ, може да разгледате и примерна реализация на този вариант тук.
Инструктор:
Неща, които може да се наложи да се разгледат и обяснят тук – цикъла
each
, откъде идват стойностите на променливитеplace_id
иplace_name
, разликата между ERB таговете<% %>
(control) и<%= %>
(output), защоCHOICES
се изписва с главни букви (CHOICES
е константа и че това е необходимо, за да може да е с глобална видимост и да се “вижда” и в изгледа). При необходимост, пуснете още един терминал в Codespaces и в него стартирайтеirb
, където демонстрирайте работа с хешове (речници) – създаване, извличане на стойност, добавяне и промяна на елементи, обхождане. Използвайтеputs
където е нужно. Оставете участничките да си поиграят и да осмислят концепциите за променливи. - Помислете има ли проблеми от гледна точка на сигурност с вашето приложение? Ако има такива, имате ли идеи за възможни решения, дори само на концептуално ниво?
-
Поиграйте си с Ruby в
irb
.Инструктор:
Говорете за изрази, стойности, оценки, викане на методи, параметри, типове данни и т.н.