Programmering i Ruby

Den Pragmatiske Programmerers Veiledning

Forrige < Innhold ^
Neste >

Ruby og World Wide Web



Ruby er ikke fremmed for Internet. Ikke bare kan du skrive egne SMTP, FTP eller web servere i Ruby, men du kan også bruke Ruby for mer dagligdagse oppgaver som CGI programmering eller som et alternativ til PHP.

Skrive CGI skript

Det er veldig enkelt og greitt å skrive CGI skript i Ruby. For å generere HTML utput fra et Ruby skript, trenger du kun

#!/usr/bin/env ruby
print "HTTP/1.0 200 OK\r\n"
print "Content-type: text/html\r\n\r\n"
print "<html><body>Hello World!</body></html>\r\n"

Du kunne brukt Ruby sine regulære uttrykk til å analyse de innkommende forespørselsstrengene, sjekke opp miljøvariable, sjekke taggene, sette inn tekst i en mal, omskrive spesielle tegn med escape sekvenser, formattere HTML dokumentet og skrive hele greia ut.

Eller du kan bruke klassen CGI.

Bruk av cgi.rb

Klassen CGI støtter skriving av CGI skript. Med klassen kan du manipulere skjemaer (forms), cookies og miljøet rundt, opprettholde sesjoner med tilstand og så videre. Klassen dokumenteres i detalj i referanseseksjonen som starter på side 497(??), men we tar et kjapt blikk på dens muligheter her.

Sitering

Når man håndterer URL'er og HTML kode, må man være påpasselig med å sitere visse tegn. For eksempel, et skråstrek tegn (``/'') har spesiell betydning i en URL, så man må bytte den ut med en skiftsekvens (kjent som å ``escape'' den) hvis den ikke er en del av stien. Dette betyr at alle ``/'' i forespørselsdelen av URL'en vil bli byttet ut med strengen ``%2F'' og må byttes tilbake til en ``/'' når du skal bruke den. Mellomrom og og-tegn (``&'') er også spesielle tegn. For å ta seg av dette, tilbyr CGI metodene CGI.escape and CGI.unescape:

require 'cgi'
puts CGI.escape( "Nicholas Payton/Trumpet & Flugel Horn" )
produserer:
Nicholas+Payton%2FTrumpet+%26+Flugel+Horn

Tilsvarende kan du ønske å bytte ut spesielle HTML tegn med skiftsekvenser:

require 'cgi'
puts CGI.escapeHTML( '<a href="/mp3">Click Here</a>' )
produserer:
&lt;a href=&quot;/mp3&quot;&gt;Click Here&lt;/a&gt;

Om du ønsker å være veldig sær, kan du begrense hvilke elementer i en streng som skal byttes ut med skiftsekvenser:

require 'cgi'
puts CGI.escapeElement('<hr><a href="/mp3">Click Here</a><br>','A')
produserer:
<hr>&lt;a href=&quot;/mp3&quot;&gt;Click Here&lt;/a&gt;<br>

Her blir bare ``A'' taggene påvirket; de øvrige taggene endres ikke. Hver av disse metodene har en tilsvarende ``un-'' metode som gir deg tilbake den opprinnelige strengen.

Skjemaer

Klassen CGI gir deg to former for tilgang til HTML forespørselsparameterne. La oss si at vi har fått en URL som ser ut som /cgi-bin/lookup?player=Miles%20Davis&year=1958. Du kan da få tak i parameterne ``player'' og ``year'' ved å bruke CGI#[] direkte:

require 'cgi'
cgi = CGI.new
cgi['player'] » ["Miles Davis"]
cgi['year'] » ["1958"]

Alternativt kan du hente ut alle parameterene som en Hash:

require 'cgi'
cgi = CGI.new
h = cgi.params
h['player'] » ["Miles Davis"]

Lage HTML skjemaer

CGI har en mengde metoder som kan brukes for å lage HTML---en metode per tagg. For å kunne bruke disse metodene, må du lage et CGI objekt ved å kalle CGI.new, og angi som innparameter den ønskede versjonen HTML. I disse eksemplene vil vi bruke ``html3''.

For å gjøre det enklere å nøste taggene, bruker disse metodene kodeblokker for å angi innholdet. Kodeblokken bør returnere en String, som vil bli innholdet i taggen. I dette eksempelet har vi lagt til noen ekstra linjeskift for å få utskriften til å passe inn på siden.

require "cgi"
cgi = CGI.new("html3")  # legg til HTML genereringsmetoder
cgi.out{
  cgi.html{
    cgi.head{ "\n"+cgi.title{"This Is a Test"} } +
    cgi.body{ "\n"+
      cgi.form{"\n"+
        cgi.hr +
        cgi.h1 { "A Form: " } + "\n"+
        cgi.textarea("get_text") +"\n"+
        cgi.br +
        cgi.submit
      }
    }
  }
}
produserer:
Content-Type: text/html
Content-Length: 302

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML><HEAD> <TITLE>This Is a Test</TITLE></HEAD><BODY> <FORM ENCTYPE="application/x-www-form-urlencoded" METHOD="post"> <HR><H1>A Form: </H1> <TEXTAREA NAME="get_text" COLS="70" ROWS="10"></TEXTAREA> <BR><INPUT TYPE="submit"></FORM></BODY></HTML>

Denne koden vil lage et HTML skjema med tittelen ``This Is a Test,'' fulgt av en horisontal skillestrek, en overskrift på nivå en, et innput tekstområde for testing og tilslutt en knapp for å sende inn forespørselen. Når forespørselen kommer tilbake, vil du ha en CGI parameter kalt ``get_text'' som holder på teksten som brukeren skrev in.

Cookies

Du kan lagre mye interessant på en intetanende maskin som surfer innom sidene dine ved å bruke cookies. Du kan lage et navngitt cookie-objekt og lagre et sett verdier i det. For å sende den over til nettleseren, sett en ``cookie'' hodelinje i kallet til CGI#out.

require "cgi"
cookie = CGI::Cookie.new("rubyweb", "CustID=123", "Part=ABC");
cgi = CGI.new("html3")
cgi.out( "cookie" => [cookie] ){
  cgi.html{
    "\nHTML content here"
  }
}
produserer:
Content-Type: text/html
Content-Length: 86
Set-Cookie: rubyweb=CustID%3D123&Part%3DABC; path=

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML> HTML content here</HTML>

Neste gang brukeren kommer innom denne siden, kan du hente ut cookie verdiene til CustID og Part, som vist i HTML-koden.

require "cgi"
cgi = CGI.new("html3")
cgi.out{
  cgi.html{
    cgi.pre{
      cookie = cgi.cookies["rubyweb"]
        "\nCookies are\n" + cookie.value.join("\n")
    }
  }
}
produserer:
Content-Type: text/html
Content-Length: 111

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML><PRE> Cookies are CustID=123 Part=ABC</PRE></HTML>

Sesjoner

Alene trenger cookies litt mer arbeid for å være brukendes. Det vi egentlig ønsker oss er en sesjon: en persistent tilstand knyttet til en websurfer. Sesjoner håndteres med CGI::Session (dokumentasjon begynner på side 504(??)), som bruker cookies men tilbyr en høyere grad av abstraksjon.

require "cgi" require "cgi/session"

cgi = CGI.new("html3") sess = CGI::Session.new( cgi, "session_key" => "rubyweb",                           "session_id"  => "9650",                           "new_session" => true,                           "prefix" => "web-session.") sess["CustID"] = 123 sess["Part"] = "ABC"

cgi.out{   cgi.html{     "\nHTML content here"   } }

Dette sender en cookie med navnet ``rubyweb'' med verdien 9650 til brukeren. En fil vil også bli laget på disken i $TMP/web-session.9650 med nøkkel, verdi par for CustID og Part.

Når brukeren kommer tilbake, trenger du bare en parameter for å identifisere sesjonen. I dette eksempelet er det rubyweb=9650. Med den verdien i parametrene har du mulighet for å hente hele settet med lagrede sesjonsdata.

require "cgi"
require "cgi/session"

cgi = CGI.new("html3") sess = CGI::Session.new( cgi, "session_key" => "rubyweb",                                "prefix" => "web-session.") cgi.out{   cgi.html{     "\nCustomer #{sess['CustID']} orders an #{sess['Part']}"   } }

Ruby innebygd i HTML

Inntil nå har vi kun brukt Ruby til å lage HTML-kode, men vi kan snu dette problemet på hodet; vi kan faktisk inkludere Ruby-kode i et HTML dokument.

Det finnes flere modulpakker som lar deg bygge Ruby-kode inn i et eller annet dokument, spesielt HTML sider. Generelt er dette kjent som ``eRuby.'' Mer spesifikt er det flere implementeringer av eRuby, deriblant eruby og erb. Resten av denne seksjonen vil ta for seg eruby, som er skrevet av Shugo Maeda.

Innebygging av Ruby i HTML er et kraftig konsept---det gir oss noe som tilsvarer ASP, JSP eller PHP, men med all styrken til Ruby tilgjengelig.

Bruk av eruby

eruby fungerer som et filter, enkelt og greitt. All tekst i innputfilen går igjennom urørt, med følgende unntak:

Uttrykk Beskrivelse
<% ruby kode %> Koden mellom separatortegnene byttes ut med utputten den produserer.
<%= ruby uttrykk %> Uttrykket mellom separatortegnene byttes ut med verdien til uttrykket.
<%# ruby kode %> Koden mellom separatortegnene ignoreres. (Kjekt for testing)

Du kaller eruby slik:

eruby [
            opsjoner
            ] [
            dokument
            ]

Dersom dokument utelates, vil eruby lese fra standard innput. Kommandolinjeopsjonene til eruby vises i tabell 14.1 på side 149.
Kommandolinje opsjoner til eruby
Opsjon Beskrivelse
-d, --debug Setter $DEBUG variabelen til true.
-K kcode Angir et alternativt tegnsett (se side 137(??)).
-M modus Angir modus for kjøringen, en av:

f filter modus
c CGI modus (skriver ut feil som HTML, setter $SAFE=1)
n NPH-CGI modus (skriver ut ektra HTTP hodelinjer, setter $SAFE=1)
-n, --noheader Slår av utskriving av CGI hode.
-v, --verbose Slår på ordrik modus.
--version Skriver ut versjonsinformasjon og avslutter.

La oss ta en titt på noen enkle eksempler. Vi kjører eruby på følgende innput.

This text is <% a = 100; puts "#{a}% Live!" %>

eruby bytter ut uttrykket mellom separatortegnene og produserer

This text is 100% Live!

Når du bruker <%= varianten, blir utput som om du skrev ut verdien til uttrykket. For eksempel gir følgende innput

<%a = 100%>This text is almost <%=a%> degrees! Cool!

bytter ut =a med verdien til a.

This text is almost 100 degrees! Cool!

Du kan selvfølgelig også bygge Ruby-kode inn i mer kompliserte typer dokument, slik som HTML.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>eruby example</title>
</head>
<body>
<h1>Enumeration</h1>
<ul>
<%(1..10).each do|i|%>
  <li>number <%=i%></li>
<%end%>
</ul>
<h1>Environment variables</h1>
<table>
<%ENV.keys.sort.each do |key|%>
  <tr>
    <th><%=key%></th><td><%=ENV[key]%></td>
  </tr>
<%end%>
</table>
</body>
</html>

Installere eruby i Apache

Du kan konfigurere en Apache webserver til å automatisk analyse dokumenter med innebygd Ruby-kode ved hjelp av eRuby, omtrent på samme måte som med PHP. Du lagrer filene med innebygd Ruby-kode med endelsen ``.rhtml'' og setter opp webserveren til å kjøre eruby på disse dokumentene for å generere den ønskede HTML utput.

For å bruke eruby sammen med Apache webserveren, må du gjøre følgende steg.

Og det var det! Du kan nå skrive HTML dokumenter som inneholder innebygd Ruby-kode for å lage skjemaer og innhold dynamisk. Husk å ta en titt på CGI biblioteket, som dokumenteres på side 497(??).

Bedre ytelse

Du kan bruke Ruby til å skrive CGI programmer for verdensveven, men som med de fleste CGI programmer, er standard konfigurasjon å starte opp en ny kopi av Ruby for hver enkelt cgi-bin side som hentes frem. Det kan fort spise opp minnet og CPU syklene til maskinen samt gjøre det smertefult tregt for de som surfer på sidene. Apache webserveren løser dette problemet ved å tillatte lastbare moduler.

Disse modulene blir typisk lastet inn dynamisk og utgjør en del av den kjørende webserverprosessen---dermed er det ikke noe behov for å starte nye prosesses for å kjøre fortolkeren om igjen og om igjen for å ta seg av forespørsler; webserveren er fortolkeren.

Dette leder oss frem til mod_ruby (tilgjengelig fra applikasjonsarkivene), en Apache modul som lenker en komplett Ruby fortolker inn i selve Apache webserveren. README filen som følger med mod_ruby gir detaljert informasjon om hvordan det skal kompileres og innstalleres.

Når mod_ruby er innstallert og konfigurert kan du kjøre Ruby-skript akkurat som før, men de vil komme opp mye raskere.

( In progress translation to Norwegian by NorwayRUG. $Revision: 1.8 $ )
$Log: web.xml,v $
Revision 1.8  2003/08/08 10:36:02  kent
Fikser noen overskrifter, figurer og legger inn kapittelnummerering.

Revision 1.7  2002/08/12 18:15:50  kent
Første kladd ferdig.

Revision 1.6  2002/08/12 16:21:04  kent
Frem til Installing eruby in Apache

Revision 1.5  2002/08/12 14:25:30  kent
Frem mot embedding Ruby i HTML.

Revision 1.4  2002/08/11 07:58:06  kent
Fram til Forms.


Forrige < Innhold ^
Neste >

Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide".
Translation to norwegian by Norway Ruby User Group.
Copyright for the english original authored by David Thomas and Andrew Hunt:
Copyright © 2001 Addison Wesley Longman, Inc.
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at
http://www.opencontent.org/openpub/).

(Please note that the license for the original has changed from the above. The above is the license of the original version that was used as a foundation for the translation efforts.)

Copyright for the norwegian translation:
Copyright © 2002 Norway Ruby User Group.
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at
http://www.opencontent.org/openpub/).
Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.
Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.