Witam,
jestem po lekturze tutoriala do paperclip oraz screencastu z railscasts - obydwa przypadki dotyczą jednak relacji jeden produkt- jedno zdjęcie. Chciałbym jednak dodać więcej zdjęć (w ogóle: N w szczególe: narazie 5) - czy mógłbym prosić o jakąś pomoc, jak tego dokonać? z góry dziękuję za pomoc
Nie znam paperclip, więc może istnieje też inna możliwość, ale na pewno możesz stworzyć dodatkową klasę, ProductImage, która będzie zawierała jeden obrazek. A w klasie Product deklarujesz
has_many :product_images
I to chyba będzie najlepsze i najbardziej logiczne rozwiązanie.
ok, znalazłem ponownie czas, żeby przysiąść do tego zadania… wybaczcie za podstawowe pytania, ale dopiero zaczynam przygodę z railsami
w odróżnieniu od przykładu, u mnie relacja wygląda następująco:
jest kontroller profile, który korzysta z modelu user(który przechowuje dane o użytkowniku) oraz teraz dodałem model photo(do przechowywania zdjęć)
w modelu user zadeklarowałem:
has_many :photos
w photo
belongs_to :user
has_attached_file :photo,
:styles => {
:small => "150x150>",
:large => "500x500>" },
:url => "/photos/:id/:style/:basename.:extension",
:path => ":rails_root/public/photos/:id/:style/:basename.:extension"
end
teraz zapewne należałoby stworzyć photos, z danymi dotyczącymi każdego zdjęcia- to wiem, jak zrobić, ale wolę jednak spytać, czy dobrze rozumuję - jeśli tak, to jak potem mam się odwoływać do każdego zdjęcia (w widoku) ? z góry dziękuję za odpowiedź
np tak
<% @user.photos.each do |photo| %>
<%= image_tag(photo.photo.url(:small)) %>
<% end %>
Niestety w paperclip jak model ma wiele zdjęć to jest problem z sensownym nazwaniem tego. Bo robisz model Photo i do niego musisz jeszcze podać nazwę załącznika, która u ciebie też jest photo i trzeba się odwoływać photo.photo. Brzmi to trochę głupio. Ja sobie nazwałem załącznik data, czyli mam
has_attached_file :data
Chciałem nazwać go file, ale wtedy w bazie kolumny muszą mieć nazwy typu file_filename i file_filesize
ok, ta część już działa… jednak jeszcze do ideału troszkę zostało, mianowicie takie pytania:
1.aktualnie ścieżka jest taka jak dwa posy wyżej, czyli de facto każde zdjęcie jest w osobnym folderze - czy da się do ścieżki przekazać jakoś parametr @user.id, żeby każdy użytkownik miał zdjęcia w swoim folderze?
2. kwestia backendu, zarządzania zdjęciami:
w chwili obecnej mam “zwykły” formularz z jedym polem photo(file_field,formularz ustawiony prawidłowo do wysyłania plików) -docelowo chciałbym mieć 5 pól (lepiej ogólniej: N pól, bo w przyszłości ilość zdjęć może się zmienić, a nie chciałbym, żeby to powodowało rozwalenie się całego algorytmu) dzięki którym będzie można zarządzać tymi 5-ma zdjęciami. tzn. nie chciałbym, że użytkownik wyśle np. 5 zdjęć, robi refresh, i może kolejne 5 zdjęć wysłać, tylko wrzutka będzie zamieniała konkretne zdjęcie - mam nadzieje, że rozumiecie, o co chodzi - z góry przepraszam jeszcze raz za poziom pytań, ale na chwilę obecną jeszcze nie jestem z railsami na ty
- To jest kwestia front-endu jak najbardziej.
Możesz to osiągnąć na dwa sposoby:
- Dynamiczne dodawanie pól formularza do wskazywania kolejnych zdjęć, a potem jedno zbiorowe wysyłanie kiedy użytkownik już wskaże które zdjęcia chciał uploadować
- Upload per-zdjęcie, asynchronicznie (bez przeładowywania strony)
Łatwiejsze i chyba fajniejsze od strony usability będzie wcześniejsze rozwiązanie. Łatwe do ogarnięcia jeśli po prostu pola nazwiesz nie photo[data], tylko photo[data][] (wtedy masz wszystkie dostępne w postaci tablicy po stronie railsów). Ewentualnie możesz numerować każde z pól (tj. photo[data][5] na przykład), ale to już wymaga trochę więcej zabaw z javascriptem.
- Można przekazać id użytkownika (przynajmniej tak mi się wydaje :)). Musisz sobie otworzyć plik lib/paperclip/attachment.rb w katalogu gdzie masz zainstalowany ten plugin. Jest tam metoda interpolations, do której musisz dodać swoje mapowanie np.
:user_id => lambda { |attachment, style| attachment.instance.user.id }
No i teraz możesz sobie używać :user_id przy definiowaniu gdzie mają się zapisywać zdjęcia
@ronin - działa, dzięki
@tomash -w sensie, że nie muszę się martwić o to, jak model obsłuży kilka zdjęć naraz? (w sensie, że rails automatycznie sobie taką tablicę odpowiednio potraktuje - co trzeba, wrzuci do bazy, a resztę wrzuci do odpowiedniego folderu i przeskaluje odpowiednio(to juz robota paperclipa ) )?
i jeszcze takie pytania- bonusy:
w jaki sposób mam nazywać pola ze zdjęciami?
aktualnie mam jeden file_field nazwany user[photo], jednak wysyłając formularz wylatuje mi attributeError - domyślam się zatem, że musi to być nazwane photo[photo] (tak, wiem, troszkę głupio, ale już żeby nie mieszać narazie zostawię taką konwencję)? i jeśli tak, jak za pomocą file_field mogę utworzyć taką nazwę?
@Krzyzak: musisz, po prostu sobie przeiterujesz po kolekcji jaką dostaniesz z formularza i dla każdego z elementów stworzysz i zapiszesz nowy paperclipowy model ze zdjęciem.
ok, czyli rozumiem, w jaki sposób mam się bawić w modelu - teraz tylko pytanie, jak nazwać dane z formularza, żeby je potem wykorzystać w modelu (photo[photo][1]) czy user[photo][1] ? ) i w jaki sposób za pomocą erb’a (i file_field) stworzyć nazwę pola typu photo[1] ?
Witam, mam taki problem wiec napisze tutaj, nie chce robic balaganu na forum tzn sprawa dodtyczy galerii.Do rzeczy
mam kontroler galleries, oraz pictures, modele gallery
[code]class Gallery < ActiveRecord::Base
has_many :pictures, :dependent => :destroy
end[/code]
i picture
[code]class Picture < ActiveRecord::Base
belongs_to :gallery
has_attached_file :pic,
:styles => {
:small => “150x150>”,
:large => “500x500>” }
end[/code]
oraz widok
[code]
New picture
<% form_for @picture, :html => { :multipart => true } do |f| %>
<%= f.error_messages %>
<%= f.file_field :pic %>
<%= f.submit "Create" %>
<% end %><%= link_to ‘Back’, pictures_path %>[/code]
i teraz jak chce dodac zdjecie to wyskakuje mi blad
Mysql::Error: Column 'gallery_id' cannot be null: INSERT INTO `pictures` (`gallery_id`, `pic_content_type`, `pic_updated_at`, `pic_file_name`, `pic_file_size`) VALUES(NULL, 'image/jpeg', '2009-02-22 12:23:41', 'Creek.jpg', 264409)
Chcialbym aby w widoku miec opcje wyboru np id galerii (id_gallery), aby dodawane zdjecie bylo zapisane do galerii, o wybranym przeze mnie id.
Problem, ze nie wiem jak do konca to zrobic.
<% for gallery in @galleries %>
<select name="name[gallery_id]">
<option value="">wybor galerii</option>
<option value="1" selected="selected"><%= gallery_id %></option>
</select>
<% end %>
Oczywiscie moja koncepcja nie dziala, wiec prosilbym o porady
Spróbuj tak:
[code=ruby]
wybor galerii <% for gallery in @galleries %> <%= gallery.id %> <% end %> [/code] no i oczywiście w kontrolerze musisz wczytać wszystkie galerie do zmiennej @galleriesdzieki ronin jestes wielki:)
ale mam pytanie jeszcze jedno, teraz musze w kontrolerze picture.rb dokonac zmian aby polaczyc ta wartosc id ktora wyciagam czy moge jakos w widoku to zrobic (na skroty) ?
jesli zmian to robic to na metodzie ‘create’ czy dodac nowa typu def add_picutre … end?
[quote=ronin]Spróbuj tak:
[code=ruby]
wybor galerii <% for gallery in @galleries %> <%= gallery.id %> <% end %> [/code] no i oczywiście w kontrolerze musisz wczytać wszystkie galerie do zmiennej @galleries[/quote] Nie po to jest helper select? http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.htmlPo za tym w Twoim przykładzie, która galeria (id) będzie zaznaczona?
pozdrawiam
[quote=punkracy][quote=ronin]Spróbuj tak:
[code=ruby]
wybor galerii <% for gallery in @galleries %> <%= gallery.id %> <% end %> [/code] no i oczywiście w kontrolerze musisz wczytać wszystkie galerie do zmiennej @galleries[/quote] Nie po to jest helper select? http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.htmlPo za tym w Twoim przykładzie, która galeria (id) będzie zaznaczona?
pozdrawiam[/quote]
No masz rację, ja poprostu przerobiłem na szybkości to co było
[quote=666bialy666]ale mam pytanie jeszcze jedno, teraz musze w kontrolerze picture.rb dokonac zmian aby polaczyc ta wartosc id ktora wyciagam czy moge jakos w widoku to zrobic (na skroty) ?
jesli zmian to robic to na metodzie ‘create’ czy dodac nowa typu def add_picutre … end?[/quote]
nie bardzo wiem o Ci chodzi
chodzi mi o to ze teraz w widoku mam do wyboru moje galerie, ktore sobie wczesniej dodalem, ale przy dodaniu zdjecia ‘submit’ mam, ze nie znaleziono gallery_id(ten blad co wyzej). teraz chyba powinienem dodac akcje ktora przy wcisnieciu ‘submit’ pokazywala to gallery_id, i pytalem wlasnie czy tak trzeba czy mozna jakos szybciej na skroty to zrobic np w samym widoku;)
zrobilem tak jak doradzil @punkracy i skorzystalem z helper select
widok.rhtml
[code]<% form_for @picture, :html => { :multipart => true } do |f| %>
<%= f.error_messages %>
<%= select("picture", "gallery_id", @galleries.collect {|g| [ g.name, g.id ] }, {:include_blank => 'Wybierz galerię:'}) %>
<%= f.file_field :pic %>
<%= f.submit "Dodaj", :disable_with => "Proszę czekać..." %>
<% end %>[/code] problem w tym, ze nie dziala mi walidacja jak mam ta linie [code]<%= select("picture", "gallery_id", @galleries.collect {|g| [ g.name, g.id ] }, {:include_blank => 'Wybierz galerię:'}) %>[/code] wywala mi nil'a [code]You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.collect[/code] Ktos wie, jak to rozwiazac ? Z gory dziekiCałkiem dobry sposób jeśli ktoś nie potrzebuje AJAX’a:
necromancer casts: revive