Coś bardziej zaawansowanego
Stworzymy teraz projekt, dla którego struktura modelu wczytana będzie z bazy danych.Tworzymy nowy projekt
Do stworzenia projektu wykorzystamy wspomnianej wcześniej wtyczki do Eclipse'a: "RadRails"Zaczynamy, tworzymy nowy projekt i nazywamy go "depot":

Baza danych:
Jak już wspomnieliśmy, chcemy model dla naszego projektu wczytać z bazy danych. W tym celu musimy stworzyć konieczne tabelki, zatem pobieramy 2 skrypty do stworzenia bazy danych i tabel i umieszczamy je w katalogudb
w naszym projekcie.Skrypty możemy odpalić przez phpmyadmin lub za pomocą konsoli:
mysql –u root –p
>source sciezka_do_pliku/createDB.sql

przełączamy sie do bazy danych
use depot_development
I wczytujemy skrypt do stworzenia tabel w bazie danych.
>source sciezka_do_pliku/create.sql

Konfiguracja aplikacji:
Aby aplikacja wiedziała co się dzieje w bazie danych, należy wyedytować plik config/database.yml.
Wstawiamy odpowiednie wartości czyli localhost user name i password.
Czas wygenerować model na podstawie dodanych tabel.
depot> ruby script/generate scaffold Product Admin
depot> ruby script/server
I czas na odrobinę czarów:http://localhost:3000/admin

Jak widać na powyższym obrazku, możemy dodawać, usuwać i edytować nowe produkty.
Wszystko za sprawą kilku linii kodu. No dobrze, skoro już mamy możliwość dodania produktów, to przeprowadźmy mały test. Spróbujmy dodać produkt bez nazwy.
Walidacja
Otrzymaliśmy komunikat o błędzie, co nie jest może zaskoczeniem, ale warto zwrócić uwagę na rodzaj tego błędu. Nasz system starał się dodać do bazy danych rekord z pustą wartością wymaganą. Jest to "groźna" przypadłość, której należy się jakoś pozbyć. O czym każdy wie, należy sprawdzić pola formularza przed wysłaniem. O czym nie każdy wie, możemy to wykonać za pomocą jednej linijki w modelu produktu, ponieważ wszelkie dane jakie przychodzą i wychodzą z aplikacji do bazy idą (a przynajmniej powinny ) przez model.Otwieramy
app/models/product.rb
class Product < ActiveRecord::Base
end
Po ilości kodu łatwo domyślić się iż cała obsługa została odziedziczona z klasy bazowej. Dodajmy do naszej klasy linijkę walidującą:
class Product < ActiveRecord::Base
validates_presence_of :title, :description, :image_url
end
Możliwości walidacji jest oczywiście więcej. Możemy np. sprawdzać, czy podana wartość jest liczbą, przy użyciu :
validates_numericality_of :price
Dzięki tym zabiegom, przy próbie dodania błędnych danych, system poinformuje nas "ładnym" komunikatem o błędach:

Jak już walidujemy, to ustawiamy jeszcze aby tytuł był unikalny
validates_uniqueness_of :title
Możemy oczywiście napisać własne reguły walidacyjne.
Sprawdźmy np. czy ścieżki obrazków zaczynały sie http I kończyły gif, jpg, lub png
validates_format_of :image_url,
:with => %r{^http:.+\.(gif|jpg|png)$}i,
:message => "popraw ścieżkę do obrazka"
Teraz jeszcze tylko sprawdzimy czy cena jest większa od zera.
protected
def validate
errors.add(:price, "Ustaw cene wieksza od zera") unless price.nil? || price >
0.0
end
Na koniec nasza klasa powinna wyglądać tak:

Wygląd
Czas najwyższy poprawić wygląd naszej storny.Jeśli oddaliśmy już kilka produktów, to zdajemy sobie sprawę, iż należało by zmienić sposób ich listowania. Jeśli zajrzymy do katalogu
app/views/admin/
to zobaczymy tam 5 plików o rozszerzeniu .rhtml.W przeciwieństwie do poprzedniego projektu, w którym nasz plik rhtml był całą stroną, tu mamy do czynienia, z plikami odpowiedzialnymi tylko za część. Nas interesuje plik odpowiedzialny za wylistowanie czyli
list.rhtml
.Aby go nie przepisywać, proponuję zastąpić go tym. Zanim odpalimy naszą stronę by sprawdzić "nową jakość", niezbędna będzie zmiana w pliku
scaffold.css
, którą
znów najłatwiej będzie wykonać poprzez zastąpienia pliku public/stylesheets/scaffold.css
wersją ze strony:scaffold.css.
Zanim omówimy zmiany, sprawdźmy efekt: http://localhost:3000/admin/list

No dobrze, a czemu zawdzięczamy ten efekt?

Z ciekawych rzeczy, które się wydarzyły to polecam bliższej uwadze:
-
for product in @products
- pozwala na wygodne przechodzenie po rekordach -
<tr valign="top" class="ListLine<%= odd_or_even %>">
- ta linijka w łatwy sposób rozwiązuje sprawę kolorowania wierszy różnymi kolorami - przy różnych polach mamy do czynienia z różnym formatowaniem przy pomocy funkcji -
sprintf()
h(product.title)
- funkcja h() pozwala przetworzyć tekst w sposób bezpieczny dla przeglądarki np. zamiana > na >- godnym zauważenia jest także
<%= link_to 'New product', :action => 'new' %>
- jest to mechanizm tworzenia linków do stron odpowiadających odpowiednim akcjom
Drugi kontroler
By nasz projekt stał się nieco ciekawszy, stworzymy teraz drugi kontroler odpowiedzialny za dostęp dla listy produktów, dla klientów naszego internetowego sklepu.Zaczynamy zatem standardowo od stworzenia kontrolera:
depot> ruby script/generate controller Sklep index
Jak widać poprosiliśmy o stworzenie dodatkowo akcji index. Akcja ta jest domyślną akcją odpalaną na kontrolerze, dlatego to w niej umieścimy kod odpowiedzialny za wylistowanie produktów.
Aby uczynić nasz przykład "ciekawszym", będziemy przedstawiać tylko produkty dostępne. W tym celu musimy stworzyć metodę klasową na Klasie Product. Należy zatem w pliku
app/models/product.rb
dodać metodę:
Dwie nowe rzeczy pojawiły się w tym kawałku kodu:
- słowo
self
- jest to sposób wprowadzania metod klasowych - metoda
find
- która na kształt zapytań SQL zwraca nam kolekcję obiektów spełniających odpowiednie warunki, w zadanym porządku
Jesteśmy gotowi do dodania logiki do naszej akcji index w kontrolerze Sklep:

Oczywiście nie obejdzie się bez zmiany domyślnego widoku. Zastąpmy zatem nasz plik
app/views/sklep/index.rhtml
plikiem index.rhtml.Sprawdźmy co otrzymaliśmy http://localhost:3000/sklep/
Do ostatecznego wyniku brakuje nam już tylko dwóch kroków. Jak wspomnieliśmy wcześniej przy edycji widoku dla kontrolera Admin, Możemy stworzyć główny template, który aplikowany jest dla każdej akcji z danego kontrolera. Stwórzmy zatem plik sklep.rhtml i umieśćmy go w katalogu
app/views/layouts

Poza całym mnóstwem magii, w naszym templejcie znajduje sie linijka
<%= @content_for_layout %>
- to w to miejsce
zostanie wstawiona treść widoku konkretnych akcji. Na koniec dodajemy jeszcze jeden CSS depot.css
i zastępujemy nasz plik index.rhtml
nowym plikiem index.rhtmlJeśli wszystko poszło zgodnie z planem, to możemy sprawdzić efekt naszej pracy http://localhost:3000/sklep/
Projekt jest dostępny w formie paczki tutaj.