#134 Paperclip
- Download:
- source codeProject Files in Zip (150 KB)
- mp4Full Size H.264 Video (11.5 MB)
- m4vSmaller H.264 Video (7.81 MB)
- webmFull Size VP8 Video (20.3 MB)
- ogvFull Size Theora Video (15.3 MB)
translated by Paweł Lenart
Poniżej mamy zaprezentowaną stronę produktu w aplikacji typu e-commerce. Chcielibyśmy dodać zdjęcie do produktu i zmodyfikować system zarządzania tak, aby zdjęcie było wczytywane, kiedy produkt jest tworzony lub edytowany. W tym odcinku pokażemy wam, jak użyć wtyczki Paperclip, aby to osiągnąć.
Paperclip umożliwia łatwe dodawanie załączników do modelu. Użyjemy go, aby dodać pole do naszego modelu Product
, także każdy produkt będzie mógł posiadać zdjęcie.
Paperclip jest instalowany w ten sam sposób, co inne wtyczki. Znajdując się w katalogu naszej aplikacji możemy go zainstalować z GitHub’a.
script/plugin install git://github.com/thoughtbot/paperclip.git
Aktualizacja modelu
Teraz, kiedy Paperclip jest zainstalowany, możemy użyć jego generatora, aby dodać pole załącznika do modelu Product
.
script/generate paperclip product photo
Generator wymaga podania dwóch argumentów. Pierwszy to nazwa modelu (w naszym przypadku to nasz model Product
), natomiast drugi to nazwa nowego pola załącznika w modelu. Generator stworzy migrację, która doda cztery nowe pola do modelu.
add_column :products, :photo_file_name, :string add_column :products, :photo_content_type, :string add_column :products, :photo_file_size, :integer add_column :products, :photo_updated_at, :datetime
Cztery nowe pola dodane przez generator Paperclip.
Musimy wydać polecenie rake db:migrate
, aby zaktualizować tabelę produktów w bazie danych.
Następnym krokiem będzie modyfikacja kodu modelu. Użyjemy has_attached_file
, żeby podać modelowi nazwę pola załącznika określoną w migracji.
class Product < ActiveRecord::Base belongs_to :category has_attached_file :photo end
Zmiana widoku
Do formularza, który tworzy lub aktualizuje produkt, musi zostać dodane pole wczytania pliku.
<% form_for @product, :html => { :multipart => true } do |form| %> <ol class="formList"> <!-- Tutaj inne pola... --> <li> <%= form.label :photo, "Photo" %> <%= form.file_field :photo %> <li> <%= form.submit "Submit" %> </li> </ol> <% end %>
Oprócz dodania pola file_field
do formularza musimy zmodyfikować form_for
tak, żeby formularz mógł akceptować pliki. Jest to realizowane poprzez dodanie :multipart => true
do listy :html
, które doda atrybut enctype="multipart/form-data"
do taga otwierającego formularza.
Oczywiście nie ma sensu wczytywać obrazków bez wyświetlania ich, dlatego też musimy dokonać zmiany w widoku show
. żeby dodać obrazek, musimy jedynie dodać image_tag
do strony. Nasz model Product
będzie teraz posiadał obiekt photo
jako właściwość z metodą url
, która przechowuje ścieżkę do obrazka.
<%= image_tag @product.photo.url %>
Następnie możemy wyedytować produkt, dodać do niego obrazek i zobaczyć rezultat.
To działa! Nasz produkt ma zdjęcie, lecz jest ono trochę za duże. żeby mieć pewność, że wczytywane obrazy będą miały poprawny rozmiar, byłoby o wiele łatwiej zmieniać ich rozmiar po stronie serwera, co jest możliwe przy użyciu Paperclip.
Zmiana rozmiaru obrazów
Metoda has_attached_file
, którą dodaliśmy do modelu Product, może przyjmować wiele opcji. Jedną z nich jest styles
, która pozwala nam zdefiniować różne rozmiary naszego obrazu. żeby stworzyć miniaturkę dla każdego obrazu, musimy jedynie zdefiniować styl i określić wymiary.
has_attached_file :photo, :styles => { :small => "150x150>" }
Z nowo dodanym stylem Paperclip wygeneruje dla każdego obrazu miniaturkę, która zmieści się w obszarze o wymiarach 150x150. Znak większości na końcu nakazuje Paperclip’owi zachować proporcje obrazu, tak że nie będzie on zniekształcony podczas zmiany rozmiaru. Proszę mieć na uwadze to, że żeby pozwolić na przeskalowanie musisz mieć zainstalowany ImageMagick na serwerze.
Aby wyświetlić przeskalowany obraz w widoku show
produktu, musimy zmodyfikować image_tag
tak, żeby wskazywał na pomniejszony obrazek.
<%= image_tag @product.photo.url(:small) %>
Jeżeli przekażemy styl do metody url, to zostanie zwrócony właściwy obraz. Mniejszy obrazek jest generowany tylko podczas wczytywania obrazu, więc musimy wyedytować produkt i wysłać plik jeszcze raz, żeby został pomniejszony. Jak tylko to zrobimy, zdjęcie naszego produktu ukaże się w zmniejszonej wersji.
Ustawianie ścieżki Paperclip’a
Domyślnie Paperclip przetrzymuje załączniki w katalogu system
wewnątrz katalogu public
naszej aplikacji.
<img alt="Phone_large" src="http://asciicasts.com/system/photos/1/small/phone_large.jpg?1238845838" />
Paperclip tworzy własną hierarchię do przechowywania plików na podstawie id
produktu oraz stylu
określonego w modelu. W większości przypadków ten katalog powinien być odpowiedni, ale jesli chcemy przechowywać pliki gdzie indziej, to możemy go zmienić.
Aby przechowywać obrazy w innym miejscu, dodajemy jedynie dwie dodatkowe opcje do metody has_attached_file
— adres url i ścieżkę.
has_attached_file :photo, :styles => { :small => "150x150>" }, :url => "/system/:attachment/:id/:style/:basename.:extension", :path => ":rails_root/public/system/:attachment/:id/:style/:basename.:extension"
Powyższy url i ścieżka są domyślnymi dla Paperclip’a. Adres url jest relatywny w stosunku do katalogu public
i znajdują się w nim znaczniki nazwy załącznika, id modelu i stylu. Podobne znaczniki znajdują się w ścieżce. Jeśli chcemy, żeby nasze obrazki były przechowywane w katalogu assets
, musimy zmodyfikować url i ścieżkę.
has_attached_file :photo, :styles => { :small => "150x150>" }, :url => "/assets/products/:id/:style/:basename.:extension", :path => ":rails_root/public/assets/products/:id/:style/:basename.:extension"
Każdy obraz, który zostanie wczytany, będzie teraz przechowywany w katalogu assets, a nie system/photos.
Walidacja załączników
Użyteczną funkcją Paperclip’a jest też to, że może sprawdzać poprawność załączników, które są wczytywane. żeby móc walidować pliki moglibyśmy dodać poniższe walidatory do modelu Product
:
validates_attachment_presence :photo validates_attachment_size :photo, :less_than => 5.megabytes validates_attachment_content_type :photo, :content_type => ['image/jpeg', 'image/png']
W ten sposób sprawdzimy, czy wczytany załącznik jest nie większy niż pięć megabajtów oraz czy jest obrazem JPEG lub PNG. Używając powyższych w prosty sposób sprawdzimy poprawność załącznika, jak każdego innego pola formularza. Rzeczą, którą warto zapamiętać jest to, że Internet Explorer może zgłaszać typ MIME różny od innych przeglądarek. Na przykład pliki JPEG może traktować jako image/pjpeg
, a nie image/jpeg
.