2008.07-08_Serwis zdjęć z wakacji_[Programowanie].pdf

(961 KB) Pobierz
439032784 UNPDF
Programowanie
Ruby/RubyOnRails
Serwis zdjęć z wakacji
Marek Sawerwain
Tworzenie rozbudowanych serwisów internetowych to trudne zadanie. Co więcej, staje się ono bardzo
trudne, jeśli wszystkie elementy będą tworzone od podstaw. Ten problem został bardzo szybko
rozwiązany i powstały tzw. frameworki, czyli gotowe systemy, które wspomagają pracę nad tworzeniem
rozbudowanych serwisów internetowych.
duża. Mniej popularne rozwiązania to systemy
takie jak np. Yaws (napisany w języku Erlang),
czy Seaside opracowany no Smalltaku. Do naj-
bardziej popularnych należą np. Zope, Zend, Apache Coco-
on oraz pakiet RubyOnRails, który w ostatnim czasie zyskał
bardzo wiele na popularności.
RubyOnRails zdobywa coraz większą popularność
dzięki świetnie przemyślanej budowie. Dla wielu typowych
zadań, jakie się napotyka podczas tworzenia serwisów (np.
współpraca z bazą danych) RubyOnRails oferuje gotowe
rozwiązania, co w efekcie przekłada się na przyspieszenie
pracy nad serwisem. Jednakże, każde narzędzie warto po-
znać podczas realizacji choćby najprostszego projektu. Dla-
tego warto spróbować zrealizować prosty projekt, np. ser-
wis, w którym to użytkownicy będą mogli umieszczać zdję-
cia np. z wakacji.
Nasz projekt opracujemy w wersji 1.2.6 pakietu RubyOn-
Rails. Istnieje nowa wersja 2.0 ale jak na razie najbardziej po-
pularna jest wersja 1.2.x. Tym bardziej, iż większość dostęp-
nych książek oraz informacji jakie znajdziemy w Internecie
powołuje się na nieco starszą wersję pakietu RubyOnRails.
Przykład na rozgrzewkę
Nasz pierwszy przykład sprowadzi się do opracowania
aplikacji, która generuje prosty komunikat tekstowy. Jed-
nakże, aby nieco skomplikować zadanie, zrobimy to na
trzy sposoby. Zakładamy, że będziemy pracować z pozio-
mu konsoli - choć trzeba nadmienić, że istnieje specjal-
na odmiana środowiska Eclipse o nazwie Aptana wraz z
rozszerzeniem do tworzenia aplikacji Rails. Niestety, jego
wadą jest spore zapotrzebowanie na pamięć. 1GB pamię-
ci RAM jest niezbędny do w miarę sprawnej pracy. Na-
tomiast zaletą jest spora wygoda, ponieważ Aptana ofe-
ruje wszystkie elementy do tworzenia serwisów, od wła-
snej implementacji języka Ruby, poprzez niezbędne ser-
wery; oferuje także wbudowany serwer bazy danych oraz
przeglądarkę.
Pierwsza czynność to utworzenie szkieletu aplikacji.
W dowolnym katalogu, nawet w katalogu domowym, z
poziomu konsoli wydajemy polecenie rails App1 . Na-
zwa naszej aplikacji to App1 – możemy naturalnie podać
inną. Wynikiem działania wydanego polecenia jest katalog
zawierający kompletny szkielet naszej aplikacji. Możemy
nawet już w tym momencie uruchomić serwer, przecho-
50
lipiec/sierpień 2008
L ista obecnie dostępnych systemów jest bardzo
439032784.043.png 439032784.044.png 439032784.045.png 439032784.046.png
 
Programowanie
Ruby/RubyOnRails
dząc do katalogu i wydając odpowiednie po-
lecenie, co przedstawia się następująco:
pomocą kombinacji klawiszy CTRL-C. Po uru-
chomieniu serwera, co może być dla wielu osób
zaskoczeniem, możemy zacząć tworzyć naszą
pierwszą aplikację. W oddzielnym oknie konsoli
ponowie przechodzimy do katalogu naszej apli-
kacji i wydajemy następujące polecenie:
niem będzie teraz dopisanie metody o nazwie
index , która będzie domyślnie wywoływana
w aplikacji po wpisaniu do przeglądarki ad-
resu http://127.0.0.1:3000/newindex . Metoda
index przedstawia się bardzo prosto: wyko-
rzystując akcję render do pola text wpisuje-
my treść naszego komunikatu (Listing 1.)
I jest to pierwszy sposób w jaki możemy
wyświetlić komunikat. Drugim sposobem jest
umieszczenie komunikatu w pliku html i wyświe-
tlenie jego zawartości w następujący sposób:
cd App1
ruby script/server
Jeśli instalacja języka Ruby oraz pakietu Rails
odbyła się w sposób podobny do opisanego w
ramce, to aplikacja została uruchomiona za po-
mocą serwera Mongrel i jest dostępna lokalnie
pod adresem http://127.0.0.1:3000 . Serwer uru-
chomiony z poziomu konsoli łatwo wyłączyć za
ruby script/generate controller
newindex
Zostanie utworzony obiekt odpowiedzialny za
kontroler o nazwie newindex . Naszym zada-
render :ile => ”ścieżka/do/pliku,html”
Ostatnim sposobem jest utworzenie w meto-
dzie index zmiennej o nazwie np. message-
ToTheWorld w następujący sposób:
def index
@messageToTheWorld = ”treść naszej
wiadomości”
end
Rysunek 1. Wynik działania pierwszej aplikacji oraz domyślna strona serwera
Listing 1. Metoda index odpowiedzialna za
wyświetlenie komunikatu
class NewindexController <
ApplicationController
def index
render : text => a tu
znajduje si ę bardzo ś mieszna
wiadomo ść”
end
end
�����������
�������������
Listing 2. Polecenie SQL tworzące tabelę ze
zdjęciami
create table photos (
id int primary key auto_
increment ,
picture mediumblob ,
description text ,
name text );
�������������� ������������
�����������
���������
�������
�������������
�������������������
������
Listing 3. Przykładowa zawartość pliku data-
base.yml pozbawiona sekcji test development:
adapter : mysql
database : photodb
url : localhost
username : root
password : root
production :
adapter : jdbc
driver : org . apache . derby . jdbc . C
lientDriver
url : jdbc : derby : // localhost /
RubyTest1_production ; create = true
username : app
password : app
����������������
�������
����������������
����������
�������
Rysunek 2. Schemat funkcjonowania naszego serwisu ze zdjęciami
www.lpmagazine.org
51
439032784.001.png 439032784.002.png 439032784.003.png 439032784.004.png 439032784.005.png 439032784.006.png 439032784.007.png 439032784.008.png 439032784.009.png 439032784.010.png 439032784.011.png 439032784.012.png 439032784.013.png 439032784.014.png 439032784.015.png 439032784.016.png 439032784.017.png 439032784.018.png 439032784.019.png 439032784.020.png
Programowanie
Ruby/RubyOnRails
Wywołanie akcji index spowoduje utworzenie
zmiennej, ale aby wyświetlić jej zawartość na-
leży utworzyć dodatkowy plik który zajmie się
wyświetleniem zawartości zmiennej. Dodat-
kowy plik o nazwie index .rhtml tworzymy w
podkatalogu app\views\newindex . Ostatni ele-
ment ścieżki, czyli newindex to naturalnie na-
zwa kontrolera. Nazwa tego pliku, a dokładniej
rozszerzenie rhtml , zdradza, iż plik ten zostanie
poddany dodatkowej obróbce przez Ruby'ego:
Fragment kodu objętego tagami <% oraz %> .
To naturalnie program w języku Ruby. Jest
to analogiczne rozwiązane jak w przypad-
ku PHP.
W podanym przykładzie podajemy tylko
nazwę zmiennej, to wystarczy aby komunikat
został wyświetlony przez przeglądarkę. Ten
prosty przykład pokazuje, jak następuje prze-
twarzanie informacji.
Zostało ono podzielone na dwa etapy. Etap
pierwszy to przetwarzanie pliku z implementacją
metody index . W drugim etapie utworzone in-
formacje mogą zostać przeniesione do formatki.
Listing 4. Fragmenty klasy kontrolera
class PhotosController <
ApplicationController
def get_photo
@ photo = Photo . ind ( params [: id ])
send_data ( @ photo . picture , :
type => ' image / jpeg ' )
end
def show
@ photo = Photo . ind ( params [:
id ])
end
def new
@ photo = Photo . new
end
def create
@ photo = Photo . new ( params [:
photo ])
if @ photo . save
lash [: notice ] = ' Zdj ę cie
oraz opis zosta ł y wpisane do bazy
danych .'
redirect_to : action =>
' list '
else
render : action => ' new '
end
end
def edit
@ photo = Photo . ind ( params [:
id ])
end
def update
@ photo = Photo . ind ( params [:
id ])
if @ photo . update_
attributes ( params [: photo ])
lash [: notice ] = ' Zdj ę cie
oraz opis zosta ł y uaktualnione .'
redirect_to : action =>
' show ', : id => @ photo
else
render : action => ' edit '
end
end
end
<h1>Bardzo ważny komunikat</h1>
<%= @messageToTheWorld %>
Instalacja języka Ruby oraz pakiety RubyOnRails
Wiele dystrybucji oferuje gotowe pakiety z językiem Ruby, toteż nie trzeba samo-
dzielnie instalować odpowiedniego pakietu. Jednak z drugiej strony może się oka-
zać, iż wersja dostępna w pakiecie może być nieco nowsza niż dostępna w systemie.
W takim przypadku warto zainstalować Ruby'ego samodzielnie ze źródeł.
Nie jest to trudne zadanie. W pierwszej kolejności ściągamy ze strony głównej pro-
jektu Ruby najnowszą wersję stabilną. Następnie dekompresujemy archiwum:
tar zxvpf ruby-1.8.6.tar.gz
Ponieważ obecny jest skrypt conigure , za pomocą trzech poleceń dokonamy koniguracji,
kompilacji oraz instalacji w systemie:
./conigure –preix=/opt
make
make install
Drugim ważnym krokiem jest instalacja pakietu gem, za pomocą którego można instalować
dodatkowe rozszerzenia do Ruby'ego. Tym razem ściągamy archiwum o nazwie np. ru-
bygems-1.0.1.tgz . Dekompresujemy archiwum, ale sposób instalacji jest innym, bowiem
należy wydać polecenie:
ruby setup.rb
Powyższe polecenie wykona wszystkie niezbędne czynności związane z instalacją gema .
W tym momencie możemy zainstalować dodatkowy program, użyteczny podczas pracy z
pakietem RubyOnRails, w następujący sposób:
gem install rake
Kolejny krok to instalacja środowiska Rails za pomocą następującego polecenia:
gem install -v=1.2.6 rails --include-dependencies
Zgodnie z naszymi ustaleniami instalujemy wersję 1.2.6, natomiast opcja --include-de-
pendencies zapewnia, iż zostaną zainstalowany dodatkowe pakiety np. ActiveRecord uła-
twiający obsługę bazy danych.
Nasza aplikacja wymaga jeszcze instalacji sterownika do bazy MySQL oraz serwera
Mongrel, co wykonamy w następujący sposób:
Listing 5. Trywialna formatka odpowiedzialna za
wyświetlenie nazw poszczególnych kolumn
< tr >
<% for column in Photo . content_
columns %>
< th ><%= column . human_name
%>< / th >
<% end %>
< / tr >
gem install mysql
gem install mongrel --include-dependencies
Należy jeszcze dokonać instalacji bazy danych MySQL. Jednakże najlepiej zainstalować ba-
zę z pakietów dostępnych w danej dystrybucji ponieważ zaoszczędzi nam to trochę czasu.
52
lipiec/sierpień 2008
439032784.021.png 439032784.022.png 439032784.023.png 439032784.024.png
 
Programowanie
Ruby/RubyOnRails
Listing 6. Formatka odpowiedzialna za wyświetlanie listy zdjęć wprowadzonych do bazy danych
Plan naszej aplikacji
Naszym głównym zadaniem jest opracowa-
nie nieskomplikowanego systemu, w którym
użytkownik będzie mógł umieszczać dane:
zdjęcie, jego opis oraz imię i nazwisko auto-
ra. Zostaną one umieszczone w bazie danych,
w naszym przypadku będzie to baza danych
oparta o serwer MySQL.
Oznacza to konieczność utworzenia tabe-
li. Dla naszej bardzo prostej bazy danych jest
to kilka linii, co potwierdza Listing 2. Ma-
my cztery proste pola. Pierwszym jest id ,
czyli główny klucz tabeli. Drugie pole o na-
zwie picture będzie zawierać zdjęcie prze-
słane przez użytkownika. Jego opis znajdzie
się w polu description , a imię i nazwisko
w polu name .
Możliwości naszej aplikacji nie bę-
dą zbyt duże, tzn. użytkownik będzie mógł
tylko wgrać plik ze zdjęciem do naszej ba-
zy. Będzie można wyświetlić listę wszyst-
kich zdjęć dostępnych w bazie z podziałem
na strony. Pojedyncze zdjęcie będzie można
usunąć bądź zmienić, jak również będzie ist-
niała możliwość zmiany opisu. Dla ułatwie-
nia nie będziemy wprowadzać kont użytkow-
nika, które naturalnie w prawdziwym serwi-
sie byłyby niezbędne.
< h1 > Dost ę pne zdj ę cia < / h1 >
< table >
< tr >
< th > Zdj ę cie < / th >
< th > Opis < / th >
< th > Imi ę i nazwisko < / th >
< / tr >
<% for photo in @ photos %>
< tr >
< td >
< img src = "<%=url_for( :action => " get_photo ", :id => photo.id ) %>"
height = "100" / >
< / td >
< td >
<%= photo . send ( "description" ) %>
< / td >
< td >
<%= photo . send ( "name" ) %>
< / td >
< td ><%= link_to ' Poka ż', : action => ' show ', : id => photo %>< / td >
< td ><%= link_to ' Edycja ', : action => ' edit ', : id => photo %>< / td >
< td ><%= link_to ' Skasuj zdj ę cie ', { : action => ' destroy ', : id => photo
} , : conirm => ' Czy na pewno ?', : post => true %>< / td >
< / tr >
<% end %>
< / table >
<%= link_to ' Poprzednia strona ', { : page => @ photo_pages . current . previous
} if @ photo_pages . current . previous %>
<%= link_to ' Nast ę pna strona ', { : page => @ photo_pages . current . next } if
@ photo_pages . current . next %>
< br / >
<%= link_to ' Nowe zdj ę cie ', : action => ' new ' %>
Koniguracja bazy danych
Tworzenie aplikacji powinniśmy zacząć od
utworzenia bazy danych. Użyć możemy np.
programu mysql i z poziomu konsoli utwo-
rzyć odpowiednią tabelę. Warto także sko-
rzystać z narzędzi graicznych takich jak My-
SQL GUI, gdzie łatwo będzie utworzyć tablę
oraz poddać ją edycji. Będzie można także
sprawdzić nowe rekordy, które będą wpisy-
wane z poziomu naszej aplikacji sieciowej.
Drugim elementem jest określenie sposo-
bu dostępu do danych z poziomu naszej apli-
kacji sieciowej. Należy poddać edycji plik da-
tabase.yml , który znajduje się w katalogu con-
ig . W tym pliku określamy nazwę użytkow-
nika, hasło, nazwę bazy danych oraz nazwę
hosta na którym został uruchomiony serwer.
Podczas pracy nad aplikacją serwer MySQL
warto naturalnie uruchamiać na lokalnej ma-
szynie. Ogólne warto wspomnieć, iż aplikacje
Rails są uruchamiane w trzech podstawowych
trybach: test , development oraz production
(o tym, w jakim trybie uruchamiana jest apli-
kacja decyduje wartość zmiennej środowisko-
wej RAILS_ENV ). Pierwszy tryb jest przezna-
czony tylko do testów, drugi tryb jest stosowa-
ny podczas tworzenia aplikacji i ten tryb bę-
dziemy stosować. Ostatni tryb – produkcyj-
ny – przeznaczony jest do codziennej pracy
aplikacji.
Listing 7. Metoda o nazwie up, która tworzy tabelę ze zdjęciami
def self . up
create_table : photos do | t |
t . column : picture , : mediumblob
t . column : description , : text
t . column : name , : text
end
end
Listing 8. Formularz za pomocą którego wprowadzamy nowe zdjęcie do bazy
<%= start_form_tag ( { : action => ' create ' } , : multipart => true ) %>
<%= render : partial => ' form ' %>
<%= submit_tag "Nowe zdjęcie" %>
<%= end_form_tag %>
<%= link_to ' Lista fotograii ', : action => ' list ' %>
Listing 9. Fragment formularza odpowiedzialnego za tabelę ze zdjęciami
<%= error_messages_for ' photo ' %>
< p >< label for = "photo_picture" > Zdj ę cie < / label >< br / >
<%= ile_ield ' photo ', ' photo ' %>< / p >
www.lpmagazine.org
53
439032784.025.png 439032784.026.png 439032784.027.png 439032784.028.png 439032784.029.png 439032784.030.png 439032784.031.png 439032784.032.png 439032784.033.png 439032784.034.png 439032784.035.png 439032784.036.png 439032784.037.png
 
Programowanie
Ruby/RubyOnRails
Listing 3 zawiera przykładowy plik da-
tabase.yml . W sekcji development stosu-
jemy sterownik MySQL, natomiast w sek-
cji production widać jeszcze wpis związa-
ny z dostępem do bazy danych poprzez ste-
rownik jdbc.
Znaczenie pozostałych metod jest nastę-
pujące: metoda get_photo pobiera dane ob-
razu w formacie jpeg, metoda show jest od-
powiedzialna za wyświetlenie zdjęcia oraz
opisu, jednakże ta metoda tylko inicjuje ten
proces – za poprawne wyświetlenie danych
odpowiedzialna jest formatka show.rhtml .
Zadaniem metody create jest umiesz-
czenie danych w bazie danych. Metoda
ta jest wywoływana z poziomu formatki
list.rhtml . Jak widać, oprócz kontrolera
istotną rolę ogrywają formatki, gdzie może-
my reagować na czynności użytkownika.
zostanie tylko jedna z nich odpowiedzialna
za listę zdjęć.
Listing 6 przedstawia cały kod źródłowy
tej formatki. W pewnym sensie składa się ona
z trzech sekcji. Pierwsza to tabela, w której
znajduje się lista zdjęć.
Druga sekcja to menu ze stronami, jeśli
baza zawiera dużą ilość zdjęć. Trzecia sekcji
składa się z jednego przycisku odpowiedzial-
nego za wprowadzanie nowej fotograii.
Pierwszy element tabeli ze zdjęciami to
nagłówek z nazwami kolumn. Rozwiązanie,
jakie prezentuje Listing 6 jest bezpośrednie,
gdyż tworzymy w HTML nagłówek naszej
tabeli wpisując bezpośrednio nazwy kolumn.
Możemy jednak zautomatyzować ten proces
postępując tak jak pokazano na Listingu 5.
Kontroler aplikacji
Wszystkie podstawowe metody obsługują-
ce naszą aplikację znajdują się w kontrolerze
photos . Kontroler ten tworzymy w typowy
dla pakietu Rails sposób (będąc naturalnie w
katalogu naszej aplikacji):
ruby script/generate controller photos
Lista zdjęć
W naszej aplikacji występuje kilka forma-
tek. Z racji ograniczonego miejsca opisana
Obszerne fragmenty kontrolera zawarta
są na Listingu 4. Brakuje tam jednak kil-
ku metod, które pokrótce omówimy w tym
miejscu.
Pierwsza to naturalnie metoda index , któ-
rej zadaniem jest wyświetlenie spisu wprowa-
dzonych do bazy danych zdjęć. Jej kod jest
bardzo krótki i przedstawia się następująco:
def index
list
render :action => 'list'
end
Wywołujemy inną metodę list , bezpośred-
nio odpowiedzialną za obsługę listy zdjęć,
a następnie akcją render niejako przekazu-
jemy sterowanie do akcji list.
Sposób implementacji metody list rów-
nież nie jest zbyt obszerny:
def list
@photo_pages, @photos = paginate
:photos, :per_page => 6
end
Rysunek 3. Pogląd na tabelę ze zdjęciami w programie MySQL GUI
Wykorzystujemy dostępną metodę paginate,
której zadaniem jest podział wszystkich wpi-
sów w bazie na strony po sześć zdjęć na jed-
ną stronę.
Wynikiem działania metody jest obiekt
reprezentujący naszą bazę photos oraz obiekt
photo_pages wykorzystywany do nawigacji
po stronach.
Automatyczne tworzenie tabeli ze zdjęciami
Na początku tworzenia naszej aplikacji tabela z danymi została utworzona przez nas
samodzielnie. Zadanie to może zostać zrealizowane za pomocą RubyOnRails. Nale-
ży bowiem na początku utworzyć specjalny obiekt w następujący sposób:
ruby script/generate migration create_photos
Na płycie CD/DVD
W katalogu db/migration zostanie utworzony 001_create_photos.rb . W tym pliku, trzeba
zmienić deinicję metody self.up na następującą (Listing 7.)
W wywołaniu następującego polecenia:
Na płycie CD/DVD znajdują się wy-
korzystywane biblioteki, kod źródłowy
programu oraz wszystkie listingi z ar-
tykułu.
rake db:migration
tabela ze zdjęciami zostanie samodzielnie utworzona. Wymaga to naturalnie poprawnej
koniguracji dostępu do bazy danych w pliku database.yml .
54
lipiec/sierpień 2008
439032784.038.png 439032784.039.png 439032784.040.png 439032784.041.png 439032784.042.png
 
Zgłoś jeśli naruszono regulamin