<%= note.content %> "> [Rediger]
/ Komplett ">?
laget: <%= note.created_at %>
Velkommen til Track 2 of Singing med Sinatra. I del ett har vi gjennomgått ruter, hvordan å jobbe med URI-parametere, arbeider med skjemaer, og hvordan Sinatra skiller ruter med HTTP-metoden de ble forespurt av. I dag skal vi utvide vår kunnskap om Sinatra ved å bygge en liten database-drevet app, "Recall", for å ta notater / lage en gjøremålsliste.
Vi skal bruke en SQLite-database for å lagre notatene, og vi vil bruke DataMapper RubyGem til å kommunisere med databasen. Kjør følgende inne i et skall for å installere de relevante Gems:
perle installasjon sqlite3 datamapper dm-sqlite-adapter
Avhengig av hvordan du har RubyGems satt opp på systemet, må du kanskje prefiks perle installasjon
med sudo
.
La oss hoppe rett inn ved å opprette en ny katalog for prosjektet, og opprette applikasjonsfilen, recall.rb
. Start det ved å kreve de relevante perlene:
krever 'rubygems' krever 'sinatra' krever 'datamapper'
Merk: Hvis du kjører Ruby 1.9 (som du burde være), kan du slippe "required" rubygems-linjen, da Ruby automatisk laster RubyGems uansett.
Og sett opp databasen med følgende:
DataMapper :: oppsett (: standard, "sqlite3: // # Dir.pwd /recall.db") klasse Ta med DataMapper :: Ressursegenskap: id, Seriell eiendom: innhold, Tekst,: required => sann eiendom: fullfør, boolsk,: required => true,: default => falsk egenskap: created_at, DateTime-egenskap: updated_at, DateTime-slutt DataMapper.finalize.auto_upgrade!
På den første linjen oppretter vi en ny SQLite3-database i gjeldende katalog, oppkalt recall.db
. Nedenfor oppretter vi faktisk et notatbord i databasen.
Mens vi ringer klassen 'Notat', vil DataMapper opprette tabellen som 'Notater'. Dette er i tråd med en konvensjon som Ruby on Rails og andre rammer og ORM-moduler følger.
Inne i klassen setter vi opp databaseskjemaet. Tabellen 'Notater' har 5 felt. en id
felt som vil være et heltall primærnøkkel og automatisk inkrementering (dette er hva seriell betyr). EN innhold
felt som inneholder tekst, en boolsk fullstendig
felt og to datetime felt, created_at
og updated_at
.
Den aller siste linjen instruerer DataMapper til å automatisk oppdatere databasen for å inneholde tabellene og feltene vi har angitt, og å gjøre det igjen hvis vi gjør noen endringer i skjemaet.
La oss nå lage vår hjemmeside:
På toppen er et skjema for å legge til et nytt notat, og under er det alle notatene i databasen. For å komme i gang legger du til følgende i programfilen, recall.rb
:
få '/' do @notes = Note.all: .order =>: id.desc @title = 'Alle notater' erb: hjemme ende
Viktig notat: Fjern prikken ('.
') i :.rekkefølge
. (WordPress forstyrrer kodesamplesen.)
På den andre linjen ser du hvordan vi henter alle notatene fra databasen. Hvis du har brukt ActiveRecord (ORM brukt i Rails) før, vil DataMapper syntaks føle seg veldig kjent. Notatene er tildelt til @notes
instansvariabel. Det er viktig å bruke forekomstvariabler (det er variabler som begynner med en @
) slik at de vil være tilgjengelige fra visningsfilen.
Vi satte @tittel
instansvariabel, og last inn visninger / home.erb
se fil gjennom ERB-parseren.
Opprett visninger / home.erb
se fil og start den av med følgende:
<% # display notes %>
Vi har en enkel form som POSTer til hjemmesiden ('/'
), og under det er noe ERB-kode som fungerer som plassholder for nå.
HTML-standardpartiet blant dere kan ha lidd et mindre slag etter at vi har sett at vår hjemmevisefil inneholder ingen doktype eller andre HTML-koder. Vel, det er en grunn til det. Lage en layout.erb
filen i din visninger /
katalog som inneholder følgende:
<%= @title + ' | Recall' %> Minnes
fordi du er for opptatt av å huske
<%= yield %>
De to interessante delene her er linjer 5 og 18. På linje 5 ser du den første bruken av <%=? %>
ERB-koder. <%=
er forskjellig fra det vanlige <%
som det skriver ut hva som er inni. Så her viser vi hva som er i @tittel
instansvariabel etterfulgt av | Minnes
for sidens
stikkord.
På linje 18 er <%= yield %>
. Sinatra vil vise dette layout.erb
fil på alle ruter. Og det faktiske innholdet for den ruten vil bli satt inn hvor som helst utbytte
er. utbytte
er et begrep som i hovedsak betyr "Stopp her, sett inn hva som venter, fortsett deretter på".
Start serveren med shotgun recall.rb
i skallet, og ta en titt på hjemmesiden i nettleseren. Du bør se innhold fra layoutfilen, og skjemaet fra selve home.erb
utsikt.
I layoutfilen inkluderte vi to CSS-filer. Sinatra kan laste statiske filer (f.eks. CSS, JS, bilder etc.) fra en navngitt mappe offentlig/
i rotkatalogen. Så lag den katalogen, og inne i det to filer: reset.css
og style.css
. Tilbakestillingen inneholder tilbakestilling av HTML5 Boilerplate CSS:
/ * HTML5? Boilerplate style.css inneholder en tilbakestilling, font normalisering og noen basestiler. Kreditt er igjen hvor kreditt skyldes. mye inspirasjon ble tatt fra disse prosjektene: yui.yahooapis.com/2.8.1/build/base/base.css camendesign.com/design/ praegnanz.de/weblog/htmlcssjs-kickstart * / / * html5doctor.com Tilbakestill stilark ( Eric Meyer Reset Reloaded + HTML5 baseline) v1.6.1 2010-09-17 | Forfattere: Eric Meyer og Richard Clark html5doctor.com/html-5-reset-stylesheet/ * / html, kropp, div, span, objekt, iframe, h1, h2, h3, h4, h5, h6, p, blokk , abbr, adresse, sitere, kode, del, dfn, em, img, ins, kbd, q, samp, liten, sterk, sub, sup, var, b, jeg, dl, dt, dd, ol, ul, li Feltformat, Form, Etikett, Legende, Tabell, Tekst, Tbody, Tfoot, Thead, Tr, Th, td, artikkel, til side, lerret, detaljer, figcaption, figur, footer, header, hgroup, meny, nav, del, sammendrag , tid, markere, lyd, video margin: 0; padding: 0; kant: 0; font-size: 100%; skrifttype: arve; vertical-align: baseline; artikkel, til side, detaljer, figcaption, figur, footer, header, hgroup, meny, nav, del display: block; blockquote, q quotes: none; blockquote: før, blockquote: etter, q: før, q: etter innhold: "; innhold: ingen; inn bakgrunnsfarger: # ff9; farge: # 000; tekstdekorasjon: ingen; merk -farge: # ff9; farge: # 000; skrifttype-stil: kursiv; skrifttype-vekt: fet; del tekst-dekorasjon: linje igjennom; abbr [tittel], dfn [title] border-bottom: 1px punktert; markør: hjelp; tabell grensekollaps: kollaps; grenseavstand: 0; hr display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; input, velg vertical-align: middle; / * END RESET CSS * / / * font normalisering inspirert av fra YUI Library's fonts.css: developer.yahoo.com/yui/ * / body font : 13px / 1,231 sans-serif; * skriftstørrelse: liten; / * hack beholdt for å bevare spesifisitet * / velg, inntast, textarea, knapp font: 99% sans-serif; / * normaliser monospace dimensjonering * no. wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome * / pre, kode, kbd, samp font-familien: monospace, sans-serif; / * * minimal b ase stiler * / kropp, velg, skriv inn, textarea / * # 444 ser bedre ut enn svart: twitter.com/H_FJ/statuses/11800719859 * / color: # 444; / * angi basen font her, for å søke jevnt * / / * font-familie: Georgia, serif; * / / * overskrifter (h1, h2, etc) har ingen standard skriftstørrelse eller margin. definer dem selv. * / h1, h2, h3, h4, h5, h6 font-weight: bold; / * Tving alltid en rullefelt i ikke-IE: * / html overflow-y: scroll; / * tilgjengelig fokusbehandling: people.opera.com/patrickl/experiments/keyboard/test * / a: svever, a: aktiv disposisjon: ingen; a, a: aktiv, a: besøkt farge: # 607890; a: svever farge: # 036; ul, ol margin-left: 2em; ol liste-stil-type: desimal; / * Fjern marginer for navigasjonslister * / nav ul, nav li margin: 0; list-style: none; liste-stil-bilde: ingen; liten skriftstørrelse: 85%; sterk, th font-weight: bold; td vertikaljustering: topp; / * sett under, sup uten å påvirke linjehøyde: gist.github.com/413930 * / sub, sup font-size: 75%; linjehøyde: 0; stilling: relativ; sup topp: -0.5em; sub bunn: -0.25em; pre / * www.pathf.com/blogs/2008/05/formatting-quoted-code-in-blog-posts-css21-white-space-pre-wrap/ * / white-space: pre; hvitrom: pre-wrap; hvitrom: pre-line; ord-wrap: break-word; polstring: 15px; textarea overflow: auto; / * www.sitepoint.com/blogs/2010/08/20/ie-remove-textarea-scrollbars/ * / .ie6 legend, .ie7 legend margin-left: -7px; / * thnx ivannikolic! * / / * juster avkrysningsbokser, radioer, tekstinnganger med deres etikett av: Thierry Koblentz tjkdesign.com/ez-css/css/base.css * / input [type = "radio"] vertikaljustering: tekstbunn; input [type = "avkrysningsboks"] vertikaljustering: bunn; .ie7 input [type = "avkrysningsboks"] vertikaljustering: basislinje; .6 inngang vertikaljustering: tekstbunn; / * hånd markør på klikkbare inngangselementer * / label, input [type = "knapp"], input [type = "submit"], input [type = "bilde"], knapp markør: pointer; / * webkit-nettlesere legger til en 2px-margin utenfor krom av formelementer * / knapp, input, velg tekstarea margin: 0; / * farger for form validitet * / input: gyldig, textarea: gyldig input: ugyldig, textarea: ugyldig grense-radius: 1px; -moz-box-shadow: 0px 0px 5px rød; -webkit-boks-skygge: 0px 0px 5px rød; boks-skygge: 0px 0px 5px rød; .no-boxshadow input: ugyldig, .no-boxshadow textarea: ugyldig bakgrunnsfarge: # f0dddd; / * Disse valgdeklarasjonene må være separate. Ingen tekstskygge: twitter.com/miketaylr/status/12228805301 Også: hot pink. * / :: - moz-valg bakgrunn: # FF5E99; farge: #fff; tekstskygge: ingen; :: valg bakgrunn: # FF5E99; farge: #fff; tekstskygge: ingen; / * j.mp/webkit-tap-highlight-color * / a: link -webkit-tap-highlight-color: # FF5E99; / * Gjør knapper bra i IE: www.viget.com/inspire/styling-the-button-element-in-internet-explorer/ * / button width: auto; overløp: synlig; / * bikubisk resizing for ikke-innfødte IMG: code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ * / .ie7 img -ms-interpolation-modus: bicubic;
Og style.css
inneholder noen grunnleggende styling for å få appen til å se pen ut:
kropp margin: 35px auto; bredde: 640px; header text-align: center; margin: 0 0 20px; header h1 display: inline; skriftstørrelse: 32px; header h1 a: link, header h1 a: besøkt farge: # 444; tekst-dekorasjon: ingen; header h2 font-size: 16px; font-style: kursiv; farge: # 999; #main margin: 0 0 20px; #add margin: 0 0 20px; #add textarea høyde: 30px; bredde: 510px; polstring: 10px; grense: 1px solid #ddd; # legg inn høyde: 50px; bredde: 100px; margin: -50px 0 0; grense: 1px solid #ddd; bakgrunn: hvit; #edit textarea høyde: 30px; bredde: 480px; polstring: 10px; grense: 1px solid #ddd; #edit input [type = submit] høyde: 50px; bredde: 100px; margin: -50px 0 0; grense: 1px solid #ddd; bakgrunn: hvit; #edit input [type = avkrysningsboks] høyde: 50px; bredde: 20px; artikkel grense: 1px solid #eee; border-top: none; polstring: 15px 10px; artikkel: first-of-type border: 1px solid #eee; artikkel: nth-barn (jevn) bakgrunn: #fafafa; article.complete bakgrunn: # fedae3; artikkelstreng font-size: 0.8em; p margin: 0 0 5px; .meta font-size: 0.8em; font-style: kursiv; farge: # 888; .links font-size: 1.8em; linjehøyde: 0.8em; flyte: høyre; margin: -10px 0 0; .links en display: block; tekst-dekorasjon: ingen;
Oppdater siden i nettleseren din, og alt skal være mer stilert. Ikke bekymre deg for dette CSS for mye; det bare gjør ting ser litt finere ut!
Akkurat nå hvis du prøver å sende inn skjemaet på hjemmesiden, kommer du til å få en rutefeil. La oss lage POST-ruten for hjemmesiden nå:
post '/' gjør n = Note.new n.content = params [: innhold] n.created_at = Time.now n.updated_at = Time.now n.save omadressering '/' ende
Så når en postforespørsel blir gjort på hjemmesiden, oppretter vi et nytt Objekt-objekt i n
(takket være DataMapper ORM, Note.new
representerer en ny rad i notater
tabell i databasen). De innhold
feltet er satt til de innsendte dataene fra textarea og created_at
og updated_at
datetime felt er satt til gjeldende tidsstempel.
Det nye notatet lagres deretter, og brukeren viderekobles tilbake til hjemmesiden der det nye notatet vil bli vist.
Så vi har lagt til et nytt notat, men vi kan ikke se det på hjemmesiden ennå, siden vi ikke har skrevet koden for den. Inne i visninger / home.erb
vis fil, erstatt <%# display notes %>
linje med:
<% @notes.each do |note| %>> <% end %><%= note.content %> "> [Rediger]
/ Komplett ">?
laget: <%= note.created_at %>
På første linje begynner vi en løkke gjennom hver av @notes
(Alternativt kunne vi ha skrevet for notat i @notes
, men å bruke en blokk, som vi er her, er en bedre praksis). På linje 2, gir vi en klasse av
fullstendig
hvis nåværende notat er satt til fullstendig
. Resten skal være ganske rett frem.
Så vi kan legge til og vise notater. Nå trenger vi bare muligheten til å redigere og slette dem.
Du har kanskje lagt merke til det i vår home.erb
se vi satt en [redigere]
lenke for hvert notat til det som egentlig er /: Id
, så la oss lage den ruten nå:
få '/: id' do @note = Note.get params [: id] @title = "Rediger notat ## params [: id]" erb: rediger slutt
Vi henter det forespurte notatet fra databasen ved hjelp av den oppgitte IDen, sett opp en @tittel
variabel, og last inn visninger / edit.erb
se fil gjennom ERB-parseren.
Skriv inn følgende for visninger / edit.erb
utsikt:
<% if @note %>
/ Delete "> Slett
<% else %>Merk ikke funnet.
<% end %>Dette er en ganske enkel visning. Et skjema som peker tilbake til gjeldende side, en tekstarea som inneholder innholdet i notatet og en avkrysningsboks som blir sjekket hvis notatet er satt til fullstendig
.
Men se på den tredje linjen. Mystisk. For å forklare dette, trenger vi å spore litt.
Du har hørt om de to begrepene GET og POST.
Men GET og POST er ikke de eneste "HTTP-verbene" - det er to flere du bør vite om: PUT og DELETE.
Teknisk sett bør POST bare brukes til å skape noe - for eksempel å lage en ny kommentar i din fantastiske nye webapp, for eksempel.
PUT er verbet for å endre noe. Og SLETT, du gjettet det, er for å slette noe.
Å ha disse fire verbene er en fin måte å skille en app opp. Det er logisk. Dessverre støtter nettlesere ikke faktisk PUT eller DELETE forespørsler, og derfor har du sannsynligvis aldri hørt om dem før.
Så, å komme tilbake på sporet her, hvis vi vil logisk dele opp appen vår (som Sinatra oppfordrer), må vi fake disse PUT og SLETT forespørsler. Du ser vårt skjema handling
er satt til post
. Den gjemte _metode
inputfelt som vi har satt til sette
På den tredje linjen lar Sinatra falle denne PUT-forespørselen, mens den faktisk bruker en POST. Rails, blant annet rammer, gjør ting på samme måte.
Nå har vi faked vår PUT-forespørsel, vi kan lage en rute for det:
sett '/: id' gjør n = Note.get params [: id] n.content = params [: innhold] n.complete = params [: fullført]? 1: 0 n.updated_at = Time.now n.save omadressering '/' slutt
Det er alt ganske enkelt. Vi får det relevante notatet ved hjelp av ID-en i URI, angi feltene til de nye verdiene, lagre og viderekoble hjemmet. Legg merke til hvordan på den fjerde linjen bruker vi en ternær operatør til å sette n.complete
til 1
hvis parametere [: komplett]
eksisterer, eller 0
ellers. Dette skyldes at verdien av en avkrysningsboks kun sendes inn med et skjema hvis det er sjekket, så vi bare sjekker for eksistensen av det.
I vår edit.erb
se, vi la til en "Slett" -kobling til det som egentlig er banen /: Id / slette
. Legg dette til din søknadsfil:
få '/: id / delete' gjør @note = Note.get params [: id] @title = "Bekreft sletting av notat ## params [: id]" erb: slett slutt
På denne siden får vi bekreftelse fra brukeren at de faktisk vil slette dette notatet. Opprett visningsfilen på visninger / delete.erb
med følgende:
<% if @note %><% else %>Er du sikker på at du vil slette følgende notat: "<%= @note.content %>"?
Merk ikke funnet.
<% end %>Legg merke til at akkurat som hvordan vi fakket en PUT-forespørsel ved å sette en skjult _metode
inntastingsfelt, feiler vi nå en DELETE forespørsel.
Jeg er sikker på at du får tak i dette nå. Slett ruten er:
slett '/: id' gjør n = Note.get params [: id] n.destroy viderekobling '/' slutt
Prøv det! Du bør nå kunne se, legge til, redigere og fjerne notater. Det er bare en ting til?
Akkurat nå hvis du vil sette et notat som fullstendig
du må gå inn i redigeringsvisningen og merk av i boksen på den siden. La oss gjøre prosessen litt enklere.
Tilbake da vi opprettet hovedsiden, inkluderte vi en /: Id / komplett
lenke på hver notat. La oss lage den ruten nå, som bare vil sette et notat som komplett (eller ufullstendig hvis det allerede var satt til å fullføre):
få '/: id / complete' gjør n = Note.get params [: id] n.complete = n.complete? 0: 1 # flip it n.updated_at = Time.now n.save omadressering '/' slutt
Du og Sinatra trekker av en crackin 'duet! Du har veldig raskt skrevet en enkel webapp som utfører alle CRUD-operasjonene du forventer en app å gjøre. Den er skrevet i super-sexy-ren Ruby-kode, og er skilt i sine logiske deler.
I den siste delen av Singing med Sinatra, Encore, forbedrer vi feilhåndtering, sikrer appen fra XSS og lager et RSS-feed for notatene..
Merk: Du kan bla gjennom de endelige prosjektfilene for denne opplæringen på GitHub.