Paperclip i wiele zdjęć

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 :wink:
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 :slight_smile:

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 :wink:

  1. To jest kwestia front-endu jak najbardziej. :slight_smile:
    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.
  1. 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 :wink: ) )?
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 :wink:

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

dzieki 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.html

Po 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.html

Po 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 :slight_smile:

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 dzieki

Całkiem dobry sposób jeśli ktoś nie potrzebuje AJAX’a:

necromancer casts: revive