Laget av Tallak Tveide / @tallakt
Du kan hente opp denne presentasjonen på din egen maskin på adressen
Dette er presentasjonene til et kursopplegg for ungdomsskole elever som går over fem kvelder med tre timer per gang.
Besøk gjerne Facebook siden vår for spørsmål på https://www.facebook.com/groups/625690284169137/
Før første kursdag er det noen ting som du gjerne kan forsøke å løse på egenhånd for å spare tid.
Du kan ta med din egen bærbare datamaskin. Om den kjører Windows, Mac OS X eller Linux betyr lite.
Om du vil så vil det være maskiner på kurset du kan låne.
Har du Mac OS X eller Linux er det sannsynlig at Ruby allerede er installert på maskinen din. Du kan sjekke dette med kommandoen:
$ ruby --version ruby 2.2.0p0 (2014-12-25 revision 49005) [i686-linux]
Hint: Du skal ikke skrive $ tegnet, denne angir hvor du skal skrive dine kommandoer.
Om du ikke har Ruby finner du det på http://ruby-lang.org. Du kan bruke en versjon som er 1.8.7 eller nyere.
På Windows anbefaler vi å velge 'Add Ruby to Path' under installajonen.
Om du har problemer med å installere Ruby får du hjelp på kurset.
For å skrive programfiler bruker vi en tekst editor. Noen gratis anbefalinger:
Vim og Emacs er to veldig avanserte editorer som brukes mye av profesjonelle. Hvis du allerede bruker en av disse er det ok.
Ta helst med en USB minnebrikke på kurset slik at du kan ta en kopi av filene dine når du reiser hjem for dagen.
Hvis du har (eller registrerer) en gratis konto på GitHub er det mulig å legge koden din der. Vi hjelper i såfall til om nødvendig.
Et annet alternativ er å bruke Dropbox href="http://www.dropbox.com/" | Dropbox
Vel møtt!
I dag går vi gjennom grunnleggende Ruby og lager noen enkle (og mindre enkle) script.
Ruby er et 20 år gammelt programmeringsspråk som ble laget av japaneren Matz (Yukihiro Matsumoto).
Han ville lage et språk som gjorde programmering gøy
Ruby er likevel et språk som kan brukes til mye. Twitter er det mest kjente nettstedet som har brukt Ruby. De brukte det til å lage hele hjemmesiden sin
Ruby tar en tekstfil og utfører kommandoer linje for linje.
Hvis vi har en tekstfil med
# i filen hello.rb
puts "Hello World!"
Når vi kjører den får vi
$ ruby hello.rb
Hello World!
Tradisjonen i programmering er at det første programmet man lærer i ett nytt språk skal skrive ut teksten "Hello World"
Vi skal lage et slikt program
Lag en mappe som heter c:\min_ruby
Lag en mappe min_ruby
i hjemmekatalogen din.
Åpne tekst editoren og skriv:
puts "Hello World!"
Lagre filen i katalogen din med navnet hello.rb
Ruby script kjører vi vanligvis i et terminalvindu.
Trykk på start knappen, så `Run...` og skriver `cmd`. For å endre katalog og kjøre scriptet ditt skriver du
c:\Program Files> cd c:\min_ruby
c:\min_ruby> ruby hello.rb
Kjør `Terminal` og skriv:
$ cd ~/min_ruby
$ ruby hello.rb
Variable brukes til å lagre verdier
a = 1
b = a + 2
puts b # Skriver ut 3
b = 10 # her setter vi b på nytt
puts b # Skriver ut 10
Variable må begynne med liten bokstav, og ikke inneholde spesielle tegn. Noen lovlige variabelnavn er:
a
tallet
svar5
et_viktig_tall
Det lønner seg å unngå norske bokstaver i variabelnavn
Variable med STORE BOKSTAVER er konstanter i Ruby. Konstanter får man ikke endre etter at de først er satt
MENINGEN_MED_LIVET_OG_ALT = 42
Konstanter kan ofte gjøre koden lettere å lese
Verdier kan ha forskjellige typer, de vanligste er:
Fixnum | Hele tall som 1 eller -100 |
Float | Desimaltall som 1.5 og 100.0 |
String |
Tekster, f.eks. "Ruby er topp!"
|
Symbol |
brukes som nøkler :ruby
|
true og false
|
angir sannhet |
nil
|
mangel på verdi |
puts "Ruby" # Skriver Ruby
puts 'Ruby' # Skriver også ut Ruby
a = "Yukihiro"
b = "Matsumoto"
puts "#{a} #{b}" # Skriver Yukihiro Matsumoto
a = "Yukihiro"
b = "Matsumoto"
puts "#{a} #{b}"
På den siste linjen vises en fin måte å sette verdier sammen til en streng. Du kunne også gjort
a = "Yukihiro"
b = "Matsumoto"
puts a + " " + b # Skriver også Yukihiro Matsumoto
Symboler brukes mye i Ruby fordi de er så greie
Man kan tenkte at symboler er som strenger
valg = :ruby
puts "Hei Java" if valg == :java
puts "Hei Ruby" if valg == :ruby
Koden over vil skrive ut `Hei Ruby`
Bruker vi `+` må vi passe på at begge verdiene vi skal sette sammen passer i hop
1 + "10" # TypeError: String cant be coerced into Fixnum
Man kan gjøre en streng om til et heltall med `to_i`.
1 + "10".to_i
=> 11
Eller motsatt, et heltall til en streng med `to_s`
1.to_s + "10" # to_s gjør til streng
=> "110"
`to_f` konverterer en streng til et desimaltall:
1 + "10.5".to_f
=> 11.5
`puts` og `gets` er en enkel måte å skrive til skjermen og spørre brukeren om ting
puts "Skriv noe"
svar = gets
puts "Du skrev #{svar}"
`puts` er mye brukt av profesjonelle kodere
IRB er et nyttig verktøy som følger med Ruby. Her kan du prøve ut Ruby kode og få resultatet umiddelbart. Du trenger ikke opprette en tekstfil.
IRB er fin for eksperimentering!
$ irb
irb(main):001:0> r = "Ruby"
=> "Ruby"
irb(main):002:0> r.upcase
=> "RUBY"
Alle verdiene i Ruby har metoder. For eksempel har verdien "Ruby" en metode `length` som angir hvor mange tegn den har.
tekst = "Ruby"
tekst.length
=> 4
"Ruby".length
=> 4
Forskjellig type verdier har forskjellige metoder
-100.abs
=> 100
" Matz ".strip
=> "Matz"
-100.strip
NoMethodError: undefined method `strip' for -100:Fixnum
Noen metoder vil trenge ekstra informasjon som parametre
tall = 16
tall.div(5) # Divisjon med hele tall
=> 3
I Ruby er det ikke nødvendig å ha parenteser rundt parametrene, dette er også ok:
tall.div 5
=> 3
Flere parametre listes opp adskilt av komma
tekst = "Ruby"
tekst.center(30, "_")
=> "_____________Ruby_____________"
Vi bruker `if` til å velge om en kodeblokk skal utføres
verdi = 1
if verdi > 10
puts "En er større enn ti? Her er noe galt"
end
Vi kan også legge til en `else` blokk der det trengs
verdi = 1
if verdi > 10
puts "En er større enn ti? Her er noe galt"
else
puts "En er ikke større en ti, som forventet"
end
For å gjenta en oppgave kan vi bruke løkker
10.times do |n|
puts "Dette er linje #{n}"
end
For å gjenta en kodeblokk til noe blir sant bruker man `while`
inntastet = 0
while inntastet != 5 do
puts "Skriv et tall, 5 for å avslutte"
inntastet = gets.to_i
end
Lag et program som skriver ut ti linjer. De første fem er fornavnet ditt, de siste fem er etternavnet.
Skriv et program som lager et tilfeldig tall mellom 0 og 9. Spør brukeren hvilket tall det er, helt til tallet er gjettet. Avslutt med en gratulasjon.
Tips: For å lage tilfeldige tall kan man bruke
tilfeldig_tall = rand(0..9)
I dag skal vi kikke på mer avanserte datastrukturer i Ruby og lese og skrive til filer.
liste = [1, 2, 3, 4]
liste.push(5) # legg til på slutten
=> [1, 2, 3, 4, 5]
liste.pop # hent siste element
=> 5
liste
=> [1, 2, 3, 4]
liste.shift # hent første element
=> 1
liste
=> [2, 3, 4]
lang_liste = liste + [:a, :b, :c]
=> [2, 3, 4, :a, :b, :c]
en_tom_liste = []
Verdiene i en liste har en indeks som begynner på null. Indeksen kan brukes til å lese en eller fler verdier.
liste = [1, 2, 3, 4]
den_forste = liste[0]
=> 1
de_tre_forste = liste[0..2]
=> [1, 2, 3]
En grei måte å gjøre noe med alle verdiene i en liste er å bruke `each` metoden.
noen_tall = [4, 6, 8, 10]
sum = 0
noen_tall.each do |tall|
sum = sum + tall
end
# Når vi kommer hit er sum lik 28
På neste side er det en kodesnutt som sorterer tall brukeren skriver inn. Kopier eller skriv av koden inn i en ruby fil som du kjører. Se om du kan finne ut hva hver linje gjør
# nulltiling av variable inntastet = nil liste = [] # vi spør brukeren om tall, og legger de til listen vår while inntastet != -1 puts "Skriv et positivt heltall og avslutt med -1" inntastet = gets.to_i if inntastet >= 0 liste.push(inntastet) end end
# vi lager en sortert liste ved å ta ut den minste verdien sortert = [] while liste.any? minste = liste.min liste.delete(minste) sortert.push(minste) end # skriv ut resultatet sortert.each do |tall| puts tall end
Ruby har sortering innebygd
[2, 5, 6, 3, 6].sort
=> [2, 3, 5, 6, 6]
I Ruby er en hash en tabell hvor man slår opp en verdi utfra en nøkkel
Eksempler hvor man ville brukt en hash er:
En hash kan minne veldig om en vegg med bankbokser. En nøkkel gir
adgang til innholdet i den ene boksen.
Eksempel 1: Telefonkatalogen. Nøkkelen i hashen vår er navnet, verdien er telefonnummeret
katalog = {} # start med en tom hash
katalog["Matz"] = "555-555-5555"
katalog["Tenderlove"] = "888-888-8888"
Når vi senere skal slå opp et nummer gjør vi:
katalog["Matz"]
=> "555-555-5555"
katalog["Yukihiro Matsumoto"] # finnes ikke
=> nil
I en hash er har hver nøkkel bare en verdi
katalog = {}
katalog["Matz"] = "555-555-5555"
katalog["Matz"] = "666-666-6666" # denne overskriver 555-555-5555
katalog["Matz"]
=> "666-666-6666"
Eksempel 2: Lagre bok informasjon
bok = {} # start med en tom hash
bok[:tittel] = "Ready Player One"
bok[:forfatter] = "Ernest Cline"
bok[:sider] = 384
Og så kan vi bruke bok variabelen slik
t = bok[:tittel]
f = bok[:forfatter]
s = bok[:sider]
beskrivelse = "#{t} av #{f}, #{s} sider"
=> "Ready Player One av Ernest Cline, 384 sider"
Legg merke til at telefonkatalogen har mange nøkler, mens boken vår har noen få faste nøkler
Lag en liste med fem navn. Gi alle personene et terningkast 1 til 6. Skriv ut hvem som fikk det høyeste tallet. Vi skal lagre resultatene i en hash med navn som nøkkel og terningkast som verdi.
Siden hash blir mye brukt i Ruby, finnes noen enklere måter å skrive de inn på
bok = {
:tittel => "Ready Player One",
:forfatter => "Ernest Cline",
:sideantall => 384
}
bok = {
tittel: "Ready Player One",
forfatter: "Ernest Cline",
sideantall: 384
}
Det er fullt mulig å kombinere en liste og hasher
liste = []
liste.push({twitter: "matz", land: "Japan"})
liste.push({twitter: "tenderlove", land: "USA"})
liste
=> [
{:twitter=>"matz", :land=>"Japan"},
{:twitter=>"tenderlove", :land=>"USA"}
]
liste[1][:land]
=> "USA"
Lister med hasher er ganske kompleks programmering. Det er ok hvis du ikke skjønner det med en gang.
# Åpne en fil for skriving
File.open("min_fil.txt", "w") do |fil|
fil.puts "A"
fil.puts "B"
end
# Åpne samme fil for å lese tilbake
File.open("min_fil.txt") do |fil|
while not fil.eof? # `eof?` angir end-of-file
puts fil.gets
end
end
Slik ser det omtrent ut hvis vi kjører scriptet
$ ruby lese_og_skrive_til_fil.rb A B
Filer er den måten en datamaskin kan lagre data mellom hver gang den startes på nytt. Filen legger seg på datamaskinens harddisk. Slike filer kan man åpne og lese i teksteditoren din.
a) Lag et script som henter inn tre tall med `gets` og skriver dem ut til en fil
b) Lag et script for å lese tallene i filen og skriv ut summen
c) Hent filen opp i en tekst editor
En tekstfil inneholder alle bokstaver adskilt av linjeskift tegnet.
Dette tegnet vises som strengen "\n"
Når vi leser linjer i en fil får vi tilbake disse tegnene også. Det er vår jobb å fjerne dem fra strengene
innhold = File.read("min_fil.txt") # leser alt i et jafs
linjer = innhold.each_line # splitter opp linjene
forste_linje = linjer.first
=> "A\n"
forste_linje.strip
=> "A"
Noen ganger må vi ha en plan B om filen ikke finnes
filnavn = "min_fil.txt"
verdi = nil
if File.exist?(filnavn)
verdi = File.read(filnavn)
else
verdi = "HELT TOMT"
end
På de neste sidene finner du noen oppgaver. Her kan du velge noe som passer
Les et tall fra brukeren. Stein saks papir er som for listen under. Datamaskinen velger så et tilfeldig valg. Angi hvem som vant, eller spill en ny runde hvis det ble uavgjort.
1 | Stein |
2 | Saks |
3 | Papir |
Tips:
tilfeldig_tall = rand(1..3)
if tilfeldig_tall == 1 then
# kode her
end
Når du starter programmet kaster vi fem terninger. Sjekk om man har fått hus. Tips: legg terningkastene i en liste og bruk `liste.sort`. Vi skal da enten ha 3+2 like eller 2+3 like.
La datamaskinen kaste to terninger hundre ganger. Pluss sammen antall øyne for hvert kast. Lagre summen i en hash med sum som nøkkel og antall kast som verdi. Skriv ut resultatene. Tips:
tellere = {}
# Initialiser hash med null
(2..12).each do |sum|
tellere[sum] = 0
end
# kast to terninger og øk teller
sum = rand(1..6) + rand(1..6)
tellere[sum] = tellere[sum] + 1
Lag en evig løkke som skriver ut "Matz" som en sinus. Tips: bruk elementer fra koden nedenfor.
s = Math.sin(0.3) # Sinus til et tall
desimaltall = 55.5
heltall = desimaltall.to_i # runder av til et heltall
innrykk = 10 * " "
puts "#{innrykk}Matz"
# evig løkke
loop do
# kode her
end
Dette er en gammel form for kryptering hvor alle bokstavene blir forskjøvet. Man angir nøkkelen, og hver bokstav forskyves så mange bokstaver videre. Hvis nøkkelen er 2 vil "A" byttes ut med "C", "B" blir til "D", "Y" blir til "A" etc. For å gjøre det enklere støttes bare A-Z, tilsammen 26 bokstaver. Dekryptering gjøres ved å kjøre ny kryptering med nøkkel 26 - (forrige nøkkel). (Hjelpekode på neste side) Programflyt:
"MATZ".chars
=> ["M", "A", "T", "Z"]
["M", "A", "T", "Z"].join
=> "MATZ"
"A".next
=> "B"
På denne linken fra Norsk Scrabble Forbund finnes en tekstfil med norske ord. Filen ser omtrent lik ut:
ACTINIUMENE subst ACTINIUMET subst ACTION subs
Lag et program som spør om et ord og så finner anagrammer for det (ord med samme bokstaver i en annen rekkefølge). Tips på neste side.
"ACTINIUMENE subst".split => ["ACTINIUMENE", "subst"]
# BEINET og BITENE er anagrammer "BEINET".chars.sort.join => "BEEINT" "BITENE".chars.sort.join => "BEEINT"
# pass på at det brukeren skriver blir likt med bokstavene i ordlisten # Fjern blanke tegn og gjør til store bokstaver inntastet = gets.strip.upcase
På hjemmesiden til The District of Columbia finnes en oversikt over alle lovbrudd som er begått i 2013. Lag en oversikt over hvor mange lovbrudd som er gjort av hver type (fjerde verdi) og skriv det ut som en tabell. Bonusoppgave: Finn ut hvilken type kriminalitet som skjedde hyppigst for hver klokketime
"A,B,C,D,E".split(",") => ["A", "B", "C", "D", "E"]
dato_tid = DateTime.parse("1/2/2013 3:00:00 PM") dato_tid.hour => 15
Implementer spillet mastermind. Datamaskinen sitter med den hemmelige løsningen. Tips: Når brukeren skal gi svar kan han ha en bokstav per farge, og skrive fire bokstaver. Programmet svarer så med hvor mange som var riktig farge på riktig sted, og hvor mange som var riktig farge på feil sted.
G | R | U | L | H | S |
Grønn | Rød | Gul | Lilla | Hvit | Sort |
# lage datamaskinens hemmelige løsning
FARGER = ["G", "R", "U", "L", "H", "S"]
losning = []
4.times do
indeks = random(0..5)
losning.push(FARGER[indeks])
end
Vi kikker litt på HTML og på hvordan en hjemmeside fungerer
I løpet av de siste tre dagene skal vi bygge en hjemmeside med Ruby. Når vi er ferdige har vi bygd en veldig enkel Facebook lignende side hvor man kan legge inn innlegg.
HTML er det språket som man beskriver en web side med.
HTML er ikke et programmeringsspråk, men en måte å beskrive en web side på
<!DOCTYPE html>
<html>
<head>
<title>Hallo!</title>
<meta charset="UTF-8">
</head>
<body>
<p>Hallo verden!</p>
</body>
</html>
Prøv å skrive inn dette i en tekstfil som du kaller `hello.html`. Åpne filen i nettleseren din (Firefox, Safari, Chrome, Internet Explorer).
I HTML har vi `tagger` som åpner og som lukker. De opptrer parvis slik som dette:
<div> </div>
Hva slags tag vi lager bestemmer hva som blir skrevet i browseren. `div` taggen gjør ingenting annet enn å gruppere andre tagger og tekst.
HTML bryr seg ikke om mellomrom og linjeskift. Dette
P taggen inneholder vanligvis et avsnitt med tekst
er likt med dette:
P taggen inneholder
vanligvis et avsnitt med
tekst
En HTML fil deles opp opp i `head` og `body`. Body inneholder alt som blir vist på siden. Head inneholder tittelen som vises øverst i nettleseren, og spesielle tagger.
Tabellen på neste side viser noen vanlige tagger
heading 1 |
<h1>
|
brukes til overskrifter |
heading 2 |
<h2>
|
brukes til overskrifter |
heading 3 |
<h3>
|
brukes til overskrifter |
paragraph |
<p>
|
inneholder et avsnitt med tekst |
division |
<div>
|
gruppering |
anchor |
<a href="...">
|
en lenke til noe annet |
image |
<img src="...">
|
bilder |
Du kan sette inn et bilde fra en komplett adresse (URL) slik
<img src="http://goo.gl/TZjd4Q"></img>
eller du kan hente bildet fra samme sted
<img src="kidsbook_logo.png"></img>
HTML filen og bildet må ligge i samme katalog
Lenker til komplette adresser lages slik
<a href="http://www.duckduckgo.com">trykk her for å søke</a>
eller du kan hoppe til en annen side fra fra samme sted
<a href="andre.html">her er den andre siden min</a>
Lag en side som skal bli Kidsbook. Siden skal ha:
Vent lengst mulig med å kikke på løsningsforslaget
Web siden vi laget ser litt kjedelig ut. Mens teksten på en web side er bestemt av HTML kodene, er utseendet bestemt av CSS filen
body {
background-color: powderblue;
}
.innlegg-tekst {
margin-top: 50px;
}
.avsender {
color: steelblue;
}
Vi kommer ikke til å gå så mye inn på CSS her, så vi skriver av denne teksten og lagrer som `kidsbook.css`
Neste steg er å koble HTML filen sammen med CSS filen. Det ser omtrent sånn ut
<head>
<title>Kidsbook</title>
<link rel="stylesheet" type="text/css" href="kidsbook.css">
</head>
For at valgene i CSS filen skal tre i kraft må de matche med tagger i HTML filen. Stilen
.avsender {
color: steelblue;
}
vil matche med denne HTML taggen:
<p class="avsender">Hilsen Doffen</p>
Resultatet vil være at avsnittet blir mørkeblå, som fargekoden steelblue angir. Farger er beskrevet her
For siden vi laget først skal vi bruke CSS filen. Gjør slik av både innlegg og avsendere er påvirket av CSS stilene. Løsningsforslag.
Vi skal lage en HTML fil nummer to hvor man får mulighet til å logge seg inn.
Vi gjør det veldig enkelt med en boks hvor man skiver inn navnet sitt, og en knapp for å bekrefte
Her er noen tagger vi kan bruke
<form>
|
omslutter alle elementer i ett skjema |
<textarea>
|
en stor boks for tekst |
<input type="text">
|
en liten boks for tekst |
<input type="submit">
|
knappen for å sende inn skjemaet |
Et enkelt skjema for innlogging ser da omtrent sånn ut
<form method="POST" action="/behandle-login">
<p>
<input type="text" name="avsender"></input>
</p>
<p>
<input type="submit" value="Logg inn" />
</p>
</form>
<form method="POST" action="/behandle-login">
<p>
<input type="text" name="avsender"></input>
</p>
<p>
<input type="submit" value="Logg inn" />
</p>
</form>
I dette skjemaet oppgir vi at aksjonen når vi trykker på knappen skal være `behandle-login`. Tenk at det er som
<a href="/behandle-login">
men som gjelder for skjemaer
<form method="POST" action="/behandle-login">
<p>
<input type="text" name="avsender"></input>
</p>
<p>
<input type="submit" value="Logg inn" />
</p>
</form>
Navnet `avsender` trenger vi når vi senere mottar dataene fra skjemaet
Lag en html fil for pålogging. Sjekk at lenken fra hovedsiden fungerer. Løsningsforslag her.
Filene som ligger på din datamaskin vil ikke være tilgjengelige for andre maskiner. Vi trenger en web server for å gjøre dette
Vi skal bruke Sinatra som web server. Sinatra er et system som brukes av mange profesjonelle kodere.
Før vi kan bruke Sinatra skal det installeres. Åpne et kommandovindu og skriv:
$ gem install sinatra -v 1.3
PS: $ tegnet skal ikke skrives.
Det neste vi skal gjøre er å lage følgende mappestruktur:
├── kidsbook.rb ├── public │ ├── kidsbook.html │ ├── login.html │ ├── kidsbook.css │ └── kidsbook_logo.png └── views └── (foreløpig tomt)
Filen `kidsbook.rb` skal være hovedfilen vår. Vi oppretter den med innholdet:
require 'sinatra'
Hvis du nå kjører scriptet starter web serven. Du kan koble til siden din på adressen http://localhost:4567/kidsbook.html
http://localhost:4567/kidsbook.html
Vi sier her at vi kjører mot vår egen maskin på port 4567. Når vi erstatter `localhost` med din ip adresse kan man lese siden fra en annen maskin.
Sinatra serveren kan gjøre mer enn å gi ut filer fra disken. La oss lage en side med tilfeldige tall.
Modifiser `kidsbook.rb` filen slik, og restart serveren. Du må trykke Ctrl+C for å avslutte den som allerede kjører.
require 'sinatra'
get '/tilfeldig' do
tall = rand(0..9999)
tall.to_s # vi må alltid gi tilbake en streng
end
Se hva som skjer når du går inn på http://localhost:4567/tilfeldig
`bit.ly` er et eksempel på en web side som lager en kort adresse som videresender deg til en annen side med en lengre adresse. Lag en egen slik web side. For å sende videre til en annen adresse bruk koden:
require 'sinatra'
get '/a' do
redirect to("http://www.google.com/")
end
Da vi laget en side for startsiden og en for innlogging la du kanskje merke til at det var en del av HTML kodene som var like (dvs alt untatt hoveddelen). Vi skal nå fikse opp i dette.
Første steg skal være å flytte
public/index.html
til
views/index.erb
Neste steg er å legge til følgende kode i kidsakoder.rb
get '/' do
erb :index
end
Det vi nå sier er at sinatra skal gi ut filen index.erb dynamisk istedet for å gi ut en statisk fil fra disken
Adressen '/' angir den siden man kommer til når adresselinjen kuninneholder maskinnavn og port.
Så kopierer vi views/index.erb til views/layout.erb, og sletter detmidterste som ikke er felles. Det skal se omtrent slik ut:
<!DOCTYPE html>
<html>
<head>
<title>Kidsbook</title>
<link rel="stylesheet" type="text/css" href="kidsbook.css">
</head>
<body>
<img src="kidsbook_logo.png"></img>
<%= yield %>
</body>
</html>
Vi erstattet delen i midten med `yield`
Til slutt gjør vi motsatt for filen views/index.erb, som skal se slikut
Trykk her for å logge inn.
Dette skal bli et innlegg
Hilsen: Legolas
Lag et layout for din indeks og innloggingssside.
Sinatra starter vanlig utviklingsmodus med begrenset tilgang. For å åpne opp for tilgang fra andre maskiner, kan vi legge til følgende kode i kidsbook.rb:
# i filen kidsbook.rb
require 'sinatra'
set(:bind, "0.0.0.0")
...
Hver gang vi endrer på koden i kidsbook.rb, trenger vi å restarte web servern vår.
Endringer i filer i views katalogen oppdateres automatisk
Vi skal implementere en enklest mulig påloggingsfunksjon.
Før vi går videre, skal alle ha kommet så langt:
Pålogging som vi skal lage er veldig enkel. Det holder å
Alle får tilgang.
Tidligere prøvde vi å logge inn med html filen fra disk. Da fikk vi trøbbel når vi trykket på knappen.
Nå kan vi la Sinatra håndtere dette
Legg til følgende kode nederst i kidsbook.rb
post '/behandle-login' do
p params # skriv ut skjema data
redirect to("/") # omdiriger til startsiden
end
Prøv å logg inn nå og se hva som kommer ut i terminalvinuet.
Vi har nå en måte å få tak i navnet til brukeren vår. For å lagre dette skal vi bruke en kjeks (cookie).
Kjeksen er en liten datapakke som følger brukerens trafikk frem og tilbake
Når vi bruker kjeks lagres ingen informasjon i sinatra
Siden kjeksen blir sendt frem og tilbake skal vi passe på at den ikke inneholder store datamengder.
Faktisk er hver kjeks begrenset til 4 kilobyte
Start med å skru på kjeks i Sinatra
enable(:sessions)
set(:session_secret, '--__KIDSAKODER__--')
Følg opp med å endre post koden til dette:
post '/behandle-login' do
session[:avsender] = params[:avsender]
redirect to("/")
end
Og for å se om vår session er blitt satt kan vi endre indeks metoden vår slik
get '/' do
p session
erb :index
end
Kjør koden og se at vi nå holder styr på avsenderen
Frivillig oppgave: Lag en link for å logge ut. Det greieste er å sette
session[:avsender] til nil
Det neste vi ønsker å gjøre er å endre layout slik at man får enten en link til pålogging, eller teksten 'Velkommen Tenderlove!'
ERB er en måte å blande Ruby kode med HTML.
<% if session[:avsender] %>
Trykk <a href="/ny">her</a> for å skrive et nytt innlegg
<% else %>
For å skrive innlegg må man være logget inn.
Trykk <a href="/login">her</a> for å logge inn.
<% end %>
Erb kommer i to varianter
<% if 1 > 10 %>
<p>Verden går under!</p>
<% end %>
kode inne i slike bli kjørt i stillhet
Erb kommer i to varianter
Svaret er: <%= 1000 + 1000 %>
kode inne i slike skriver ut resultatet av Ruby koden
Siden ERB filene allerede er ganske komplekse, forsøker vi å legge mest mulig kode i Ruby filen vår (kidsbook.rb)
Vi kan sende @variable fra .rb filen til .erb filen
get '/' do
@avsender = session[:avsender]
erb :index
end
...sammen med .erb filen...
<% if @avsender %>
Trykk <a href="/ny">her</a> for å skrive et nytt innlegg
<% else %>
For å skrive innlegg må man være logget inn.
Trykk <a href="/login">her</a> for å logge inn.
<% end %>
@codinghorror: Everyone is like whee fun programming! What they don't tell you is that your computer is a total asshole.
Vi bruker metoder til å gruppere kodebiter for bedre oversikt og for å slippe å kopiere tekst.
Vi definerer og bruker en metode slik:
def pluss_sammen(a, b, c)
a + b + c
end
> pluss_sammen(1, 2, 3)
=> 6
> pluss_sammen(4, 5, 6)
=> 15
Vi skal skrive en kode som skal lagre alle innleggene til fil, og lese de tilbake
Det finnes mange muligheter til å lagre innleggene. Vi skal bruke en metode som er innebygd i Ruby. Koden for å skrive ser da omtrent slik ut:
require 'yaml/store'
LAGRING = YAML::Store.new "lagring.yaml"
LAGRING.transaction do
LAGRING[:mine_data] = ["her", "er", "mine", "data"]
end
Ved å bruke dette biblioteket slipper vi å tenke på linjeskift og slikt. Det vi legger inn på en nøkkel vil være det samme som vi henter ut
Etter å ha kjørt koden vil dette være innholdet i filen `lagring.yaml`:
---
:mine_data:
- her
- er
- mine
- data
Når vi skal lese tilbake innholdet kjører vi denne koden:
require 'yaml/store'
LAGRING = YAML::Store.new "lagring.yaml"
LAGRING.transaction do
LAGRING.fetch(:mine_data, "denne verdien om nøkkelen ikke fins")
end
=> ["her", "er", "mine", "data"]
Legg til posting av innlegg og lagring til fil i kidsbook.rb. For å få det til skal dere kikke på løsningsforslaget og kopiere over den koden dere trenger til ditt eget prosjekt.
For å skrive ut alle innleggene, sender vi dem til erb filen fra kidsbook.rb via en @variabel.
get '/' do
@innlegg = les_alle_innlegg
erb :index
end
...og...
<% @innlegg.each do |et_innlegg| %>
<p class="innlegg-tekst">
<%= et_innlegg[:tekst] %>
</p>
<p class="avsender">
Hilsen: <%= et_innlegg[:avsender] %>
</p>
<% end %>
Det finnes heldigvis og beklageligvis veldig mange forskjellige programmeringsspråk. Jeg skal gå gjennom noen synspunkter på de vanligste språkene.
(mer info om språk her)