<%= note.content %> „> [Modifică]
/ Complet ">?
Creată: <%= note.created_at %>
Bine ați venit la piesa 2 a Cântării cu Sinatra. În prima parte, am revizuit rutele, cum să lucrăm cu parametrii URI, să lucrăm cu formulare și cum Sinatra diferențiază rutele prin metoda HTTP la care au fost solicitate. Astăzi, vom extinde cunoștințele noastre despre Sinatra construind o aplicație bazată pe baze de date, "Recall", pentru a face note sau a face o listă de sarcini.
Vom folosi o bază de date SQLite pentru a stoca notele și vom folosi DataMapper RubyGem pentru a comunica cu baza de date. Rulați următoarele în interiorul unei cochilii pentru a instala pietrele relevante:
gem instalați sqlite3 datamapper dm-sqlite-adapter
În funcție de modul în care ați instalat RubyGems pe sistemul dvs., este posibil să aveți nevoie să prefixați gem install
cu sudo
.
Să mergem direct prin crearea unui nou director pentru proiect și crearea fișierului de aplicație, recall.rb
. Începeți-l prin solicitarea pietrelor relevante:
cer "rubygems" necesită "sinatra" necesită "datamapper"
Notă: Dacă rulați Ruby 1.9 (care ar trebui să fie), puteți renunța la linia "requby" rubygems "deoarece Ruby în mod automat încărcă RubyGems oricum.
Și configurați baza de date cu următoarele:
DataMapper :: setup (: default, clasa "sqlite3: // # Dir.pwd /recall.db") Notă include DataMapper :: Resource property: id, Serial property: content, Text: completă, Boolean,: required => true,: default => proprietate falsă: created_at, DateTime property: updated_at, DateTime end DataMapper.finalize.auto_upgrade!
Pe prima linie, configurăm o nouă bază de date SQLite3 în directorul curent, numit recall.db
. Mai jos, în baza noastră, de fapt, în baza de date se stabilește o tabelă "Note".
În timp ce sunăm clasa "Notă", DataMapper va crea tabelul ca "Note". Aceasta este în concordanță cu o convenție pe care Ruby on Rails și alte cadre și module ORM urmează.
În cadrul clasei, setăm schema bazei de date. Tabelul "Note" va conține 5 câmpuri. Un id
câmp care va fi o cheie primară intreg și auto-incrementare (aceasta este ceea ce înseamnă "Serial"). A conţinut
câmp conținând text, un boolean complet
câmp și două câmpuri datetime, creat la
și updated_at
.
Ultimul rând îl instruiește pe DataMapper să actualizeze automat baza de date pentru a conține tabelele și câmpurile pe care le-am setat și să o facem din nou dacă facem orice modificare a schemei.
Acum, să creăm pagina noastră de pornire:
În partea de sus este un formular pentru a adăuga o notă nouă, și mai jos sunt toate notele din baza de date. Pentru a începe, adăugați următoarele în fișierul de aplicații, recall.rb
:
obtineti '/' do @notes = Note.all: .order =>: id.desc @title = 'Toate notele' erb: home end
Notă importantă: Scoateți punctul (".
') în :.Ordin
. (WordPress interferează cu proba de cod.)
Pe a doua linie, vedeți cum preluăm toate notele din baza de date. Dacă ați folosit anterior ActiveRecord (ORM folosit în Rails), sintaxa DataMapper se va simți foarte familiarizată. Notele sunt atribuite funcției @notes
variabila de instanta. Este important să utilizați variabilele de instanță (variabilele care încep cu un @
), astfel încât acestea să fie accesibile din fișierul de vizualizare.
Am setat @titlu
instanță variabilă și încărcați vizualizari / home.erb
vizualizați fișierul prin parserul ERB.
Creați vizualizari / home.erb
vizualizați fișierul și porniți-l cu următoarele:
<% # display notes %>
Avem un simplu formular care trimite POST-uri către pagina principală ('/'
), și de mai jos este un cod ERB care servește ca înlocuitor pentru moment.
Lotul de standarde HTML din rândul dvs. poate să fi suferit un accident vascular cerebral minor după ce a văzut că fișierul nostru de vizualizare de origine nu conține nici o etichetă HTML sau doctype. Ei bine, există un motiv pentru asta. Creeaza o layout.erb
fișier în dvs. vizualizari /
care conține următoarele:
<%= @title + ' | Recall' %> rechemare
pentru că ești prea ocupat să-ți amintești
<%= yield %>
Cele două părți interesante sunt linii 5 și 18. Pe linia 5 se vede prima utilizare a liniei <%=? %>
Etichetele ERB. <%=
este diferit de cel obișnuit <%
deoarece imprimă ceea ce este înăuntru. Deci, aici afișăm ce este în @titlu
instanță variabilă urmată de | rechemare
pentru pagina lui
etichetă.
Pe linia 18 este <%= yield %>
. Sinatra va afișa acest lucru layout.erb
fișier pe toate rutele. Conținutul actual pentru acea rută va fi inserat oriunde Randament
este. Randament
este un termen care în esență înseamnă "opriți aici, introduceți ce așteaptă, apoi continuați".
Porniți serverul cu shotgun recall.rb
în shell, și să aruncați o privire la pagina de pornire din browser. Ar trebui să vedeți conținutul din fișierul de aspect, iar formularul de la actual home.erb
vedere.
În fișierul de aspect am inclus două fișiere CSS. Sinatra poate încărca fișiere statice (de ex., CSS, JS, imagini etc.) dintr-un folder numit public/
în directorul rădăcină. Deci, creați acel director, și în interiorul acestuia două fișiere: reset.css
și style.css
. Resetarea conține resetarea CSS HTML5 Boilerplate CSS:
/ * HTML5? Boilerplate style.css conține o resetare, normalizarea fontului și unele stiluri de bază. creditul este lăsat în cazul în care creditul este datorat. multă inspirație a fost preluată din aceste proiecte: yui.yahooapis.com/2.8.1/build/base/base.css camendesign.com/design/ praegnanz.de/weblog/htmlcssjs-kickstart * / / * html5doctor.com Resetați foaia de stil ( Rezumatul lui Eric Meyer Reloaded + HTML5) Autori: Eric Meyer & Richard Clark html5doctor.com/html-5-reset-stylesheet/ * / html, corp, div, span, obiect, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre , abbr, adresa, cite, cod, del, dfn, em, img, ins, kbd, samp, mic, puternic, sub, var, b, i, dl, , câmpul, formularul, eticheta, legenda, tabelul, caption, tbody, tfoot, thead, tr, th, td, articol, deoparte, pânză, detalii, figcaption, figura, subsol, antet, hgroup, meniu, nav, , timp, marcă, audio, video margine: 0; padding: 0; de frontieră: 0; font-size: 100%; font: inherit; vertical-align: linia de bază; articol, deoparte, detalii, figcaption, figura, subsol, header, hgroup, meniu, nav, secțiune display: block; blockquote, q citate: none; blockquote: înainte, blockquote: după, q: înainte, q: după content: "; -color: # ff9; culoare: # 000; font-style: italic; font-weight: bold; del text-decoration: line-through; abbr [title], dfn [title] border-bottom: aranjate, cursorul: ajutor; tabel colaps de margine: colaps; spațiere frontieră: 0; hr display: block; padding: 0; intrare, selectați vertical-align: middle; / * END RESET CSS * / / * normalizarea fontului inspirată din fonturile fonturilor.css: developer.yahoo.com/yui/ * / body font : 13px / 1.231 sans-serif; * font-size: small; / * hack păstrat pentru a păstra specificitatea * / select, input, textarea, butonul font: 99% sans-serif; wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome * / pre, code, kbd, samp font-family: monospace, sans-serif; / * * minimal b ase stiluri * / body, selectare, introducere, textarea / * # 444 arata mai bine decat negru: twitter.com/H_FJ/statuses/11800719859 * / color: # 444; / * setați aici fontul de bază pentru a aplica uniform * / / * font-family: Georgia, serif; * / / * anteturile (h1, h2, etc) nu au dimensiune implicită a fontului sau margine. definiți-vă singuri. * / h1, h2, h3, h4, h5, h6 font-greutate: bold; / * forțați întotdeauna o bara de derulare în non-IE: * / html overflow-y: scroll; / * tratament accesibil accesibil: people.opera.com/patrickl/experiments/keyboard/test * / a: hover, a: activ outline: none; a, a: activ, a: vizitat culoare: # 607890; a: hover culoare: # 036; ul, ol margin-stânga: 2em; ol list-style-type: decimal; / * eliminați marginile pentru listele de navigare * / nav ul, nav li margine: 0; list-style: none; listă-stil-imagine: nici unul; mici font-size: 85%; puternic, font-weight: bold; td vertical-align: top; / * set sub, sup fără a afecta înălțimea liniei: gist.github.com/413930 * / sub, sup font-size: 75%; linia-înălțime: 0; poziție: relativă; sup top: -0.5em; sub bottom: -0.25em; pre / * www.pathf.com/blogs/2008/05/formatting-quoted-code-in-blog-posts-css21-white-space-pre-wrap/ * / alb-spațiu: pre; spațiu alb: spațiu prealabil; spațiu alb: pre-linie; cuvânt-wrap: break-cuvânt; padding: 15px; textarea overflow: auto; / * www.sitepoint.com/blogs/2010/08/20/ie-remove-textarea-scrollbars/ * / .6 legenda, .7 legenda margin-left: -7px; / * thnx ivannikolic! * / / * aliniați casetele de selectare, radiourile, intrările de text cu eticheta acestora: Thierry Koblentz tjkdesign.com/ez-css/css/base.css * / input [type = "radio"] vertical-align: text-bottom; introduceți [type = "checkbox"] vertical-align: bottom; .7 intrare [type = "checkbox"] vertical-align: linia de bază; intrare .ie6 vertical-align: text-bottom; / * cursorul de mână pe elementele de intrare clicabile * / etichetă, introduceți [type = "button"], introduceți [type = submit], introduceți [type = "image"], butonul cursor: pointer; / * browserele webkit adaugă o marjă de 2px în afara cromului elementelor de formă * / buton, intrare, selectare, textarea margine: 0; / * culori pentru validitatea formularului * / input: valid, textarea: valid intrare: invalid, textarea: invalid border-radius: 1px; -moz-box-shadow: 0px 0px 5px roșu; -webkit-box-shadow: 0px 0px 5px roșu; box-shadow: 0px 0px 5px roșu; .no-boxshadow de intrare: invalid, .no-boxshadow textarea: invalid background-color: # f0dddd; / * Aceste declarații de selecție trebuie să fie separate. Fără text-shadow: twitter.com/miketaylr/status/12228805301 De asemenea: fierbinte roz. * / :: - moz-selection background: # FF5E99; Culoare: #fff; text-umbra: nici unul; :: selecție background: # FF5E99; Culoare: #fff; text-umbra: nici unul; / * j.mp/webkit-tap-highlight-color * / a: link -webkit-tap-highlight-color: # FF5E99; / * face butoanele să fie frumoase în IE: www.viget.com/inspire/styling-the-button-element-in-internet-explorer/ * / butonul width: auto; overflow: vizibil; / * redimensionarea bicubică pentru dimensiunea IMG non-nativă: code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ * / .ie7 img -ms-interpolare-mod: bicubic;
Și style.css
conține un stil de bază pentru a face aplicația să arate destul:
corp margine: 35px auto; lățime: 640px; header text-aliniere: centru; margine: 0 0 20px; header h1 display: inline; font-size: 32px; header h1 a: link, header h1 a: vizitat culoare: # 444; text-decoration: nici unul; antetul h2 font-size: 16px; font-style: italic; culoare: # 999; #main marja: 0 0 20px; #add marja: 0 0 20px; #add textarea height: 30px; lățime: 510px; padding: 10px; frontieră: 1px solid #ddd; #add input height: 50px; lățime: 100px; margine: -50px 0 0; frontieră: 1px solid #ddd; fundal: alb; #edit textarea height: 30px; lățime: 480px; padding: 10px; frontieră: 1px solid #ddd; #edit intrare [type = submit] height: 50px; lățime: 100px; margine: -50px 0 0; frontieră: 1px solid #ddd; fundal: alb; #edit introduceți [tip = casetă de selectare] height: 50px; lățime: 20px; articol border: 1px solid #eee; frontieră: nici una; padding: 15px 10px; articol: prima de tip border: 1px solid #eee; articol: n-copil (echivalent) background: #fafafa; article.complete background: # fedae3; articol span font-size: 0.8em; p margine: 0 0 5px; .meta font-size: 0.8cm; font-style: italic; culoare: # 888; .links font-size: 1.8; înălțimea liniei: 0.8cm; float: dreapta; marja: -10px 0 0; .link un display: block; text-decoration: nici unul;
Reîmprospătați pagina în browser și totul ar trebui să fie mai mult stil. Nu vă faceți griji prea mult despre acest CSS; doar face ca lucrurile să arate puțin mai frumoase!
Chiar dacă încercați să trimiteți formularul pe pagina de pornire, veți obține o eroare de traseu. Să creăm ruta POST pentru pagina de pornire acum:
post '/' do n = Notă.new n.content = params [: conținut] n.created_at = Time.now n.updated_at = Time.now n.save redirect '/' sfârșit
Deci, atunci când o cerere de post este făcută pe pagina de pornire, vom crea un nou obiect Notă în n
(datorită ORM-ului DataMapper), Note.new
reprezintă un nou rând în notițe
tabelul din baza de date). conţinut
câmpul este setat la datele trimise de la textarea și creat la
și updated_at
datetime sunt setate la marca curentă curentă.
Noua notă este apoi salvată și utilizatorul redirecționat înapoi la pagina principală unde va fi afișată noua notă.
Așadar, am adăugat o notă nouă, însă nu o putem vedea pe pagina principală, deoarece nu am scris codul pentru aceasta. În interiorul vizualizari / home.erb
vizualizați fișierul, înlocuiți fișierul <%# display notes %>
line cu:
<% @notes.each do |note| %>> <% end %><%= note.content %> „> [Modifică]
/ Complet ">?
Creată: <%= note.created_at %>
În prima linie începem o buclă prin fiecare @notes
(în mod alternativ, am fi putut scrie pentru note în @nnnume
, dar folosind un bloc, așa cum suntem aici, este o practică mai bună). Pe linia 2, oferim o clasă de
complet
dacă nota curentă este setată la complet
. Restul ar trebui să fie destul de drept.
Deci, putem adăuga și vedea note. Acum avem nevoie doar de abilitatea de a le edita și șterge.
S-ar putea să fi observat asta în noi home.erb
vizualizăm un set [Editați | ×]
legătură pentru fiecare notă cu ceea ce este esențial /: Id
, așa că hai să creăm acel traseu acum:
primi '/: id' do @note = Note.get paramuri [: id] @title = "Editare notă ## params [: id]" erb:
Returnați nota solicitată din baza de date folosind ID-ul furnizat, configurați a @titlu
variabile și încărcați vizualizari / edit.erb
vizualizați fișierul prin parserul ERB.
Introduceți următoarele pentru vizualizari / edit.erb
vedere:
<% if @note %>
/ Șterge "> Delete
<% else %>Notă nu a fost găsită.
<% end %>Aceasta este o viziune destul de simplă. Un formular care indică înapoi la pagina curentă, o textare care conține conținutul notei și o casetă de selectare care se verifică dacă nota este setată la complet
.
Dar uita-te la a treia linie. Misterios. Pentru a explica acest lucru, trebuie să vedem puțin.
Ați auzit de cei doi termeni GET și POST.
Dar GET și POST nu sunt singurele "verbe HTTP" - mai sunt încă două despre care trebuie să știți: PUT și DELETE.
Din punct de vedere tehnic, POST ar trebui să fie folosită numai pentru a crea ceva - cum ar fi crearea unei noi note, de exemplu, în noua dvs. aplicație web minunată.
PUT este verbul pentru modificarea ceva. Și DELETE, ai ghicit-o, înseamnă că ai șters ceva.
Având aceste patru verbe este o modalitate foarte bună de a separa o aplicație. Este logic. Din păcate, browserele web nu acceptă de fapt solicitări PUT sau DELETE, motiv pentru care probabil că nu ați mai auzit niciodată de acestea înainte.
Deci, revenind aici, dacă vrem să împărțim în mod logic aplicația noastră (pe care Sinatra o încurajează), trebuie să falsăm aceste cereri PUT și DELETE. Veți vedea formularul nostru acțiune
este setat sa post
. Ascunsul _metodă
câmpul de introducere pe care l-am setat a pune
pe linia a treia permite Sinatra să falsă această cerere PUT, în timp ce utilizează efectiv un POST. Rails, printre alte cadre, fac lucrurile în mod similar.
Acum, ne-am falsificat solicitarea PUT, putem crea un traseu pentru aceasta:
pune '/: id' n n = Note.get paramuri [: id] n.content = params [: conținut] n.complete = params [: complete]? 1: 0 n.updated_at = Time.now n.save redirecționare '/' sfârșit
E destul de simplu. Obțineți nota relevantă folosind ID-ul din URI, setați câmpurile la noile valori, salvați și redirecționați acasă. Observați cum, pe linia a patra, folosim un operator ternar pentru a seta n.complete
la 1
dacă params [: complet]
există, sau 0
in caz contrar. Acest lucru se datorează faptului că valoarea unei casete este trimisă doar cu un formular dacă este bifată, așa că pur și simplu verificăm existența acesteia.
În a noastră edit.erb
vizualizare, am adăugat o legătură "Ștergeți" la ceea ce este, în esență, calea /: Id / șterge
. Adăugați aceasta în fișierul de aplicație:
primiți '/: id / delete' do @note = Note.get paramuri [: id] @title = "Confirmă ștergerea notei ## params [: id]" erb:
În această pagină vom primi confirmarea de la utilizator că ei vor să ștergă această notă. Creați fișierul de vizualizare la vizualizari / delete.erb
cu urmatoarele:
<% if @note %><% else %>Sigur doriți să ștergeți următoarea notă: "<%= @note.content %>"?
Notă nu a fost găsită.
<% end %>Rețineți că, la fel ca modul în care am falsificat o cerere PUT prin setarea unei ascunse _metodă
câmpul de introducere, acum ne confruntăm cu o solicitare DELETE.
Sunt sigură că mai ai de-a face cu asta. Ruta de ștergere este:
ștergeți '/: id' la n = Note.get params [: id] n.destroy redirect '/' sfârșit
Încearcă! Acum ar trebui să puteți vizualiza, adăuga, edita și elimina note. Mai este doar un lucru?
Chiar acum dacă doriți să setați o notă ca complet
trebuie să accesați vizualizarea Editați și să bifați caseta din acea pagină. Să facem acest proces un pic mai simplu.
Înapoi când am creat pagina de pornire principală, am inclus a /: Id / complet
link pe fiecare notă. Să facem acum acel traseu, care va stabili pur și simplu o notă ca completă (sau incompletă dacă ar fi fost deja finalizată):
primi '/: id / completă' n n = Note.get params [: id] n.complete = n.complete? 0: 1 # flip it n.updated_at = Time.now n.save redirecționare '/' sfârșit
Tu și Sinatra trageți un duet de crackin! Ați scris foarte repede o aplicație web simplă care efectuează toate operațiile CRUD pe care le-ați aștepta ca o aplicație să o facă. Este scris în codul Ruby de super-sexy și este separat în părțile sale logice.
În ultima parte a Cântării cu Sinatra, Encore, vom îmbunătăți gestionarea erorilor, vom securiza aplicația din XSS și vom crea un flux RSS pentru note.
Notă: Puteți căuta fișierele finale de proiect pentru acest tutorial la GitHub.