2012-03-29 11 views
19

Muszę skopiować plik z jednego obiektu fali nośnej do innego. Są to różne tabele i różne typy przesyłających.Jaki jest właściwy sposób kopiowania pliku carrierwave z jednego rekordu do drugiego?

Zacząłem:

user.avatar = image.content 

(gdzie użytkownik i obraz są modelowe przypadki, awatar i treści są carrierwave zamontowany przesyłające), który pracował czasami. Wydaje się działać cały czas lokalnie, z pamięcią plików, ale sporadycznie, gdy używa się mgły i s3.

W mailing list post znalazłem ten kod:

user.avatar = image.content.file 

że znowu pracował czasami.

Mam roztwór roboczy tak daleko jest:

require "open-uri" 

begin 
    user.avatar = open(image.url) 
rescue Errno::ENOENT => e 
    begin 
    user.avatar = open(image.path) 
    rescue Errno::ENOENT => e 
    # Ok, whatever. 
    end 
end 

który jest nie tylko brzydkie, ale nie przejdzie walidację przedłużacza ponieważ otwarcie pliku zdalnego nie utrzymuje rozszerzenie (jpg, png, etc. .).

Odpowiedz

12

Być może jednym ze sposobów jest ustawienie zdalnego adresu URL obrazu zgodnie z the Carrierwave gem documentation?

user.remote_avatar_url = image.url 
+0

Czy obraz image.content.url? Nie jestem pewien, czy to zadziała, ponieważ awatar ma wiele wersji z różnymi procesami, które wymagają lokalnego pliku do pracy, i nie chcę, aby oba rekordy wskazywały na ten sam plik, chcę kopię pliku. – Pablo

+1

Sposób działania remote_blah_url polega na tym, że zasadniczo "pobiera" plik z tego adresu URL i przetwarza go ponownie. Zobacz na przykład http://stackoverflow.com/questions/5007575/how-to-assign-a-remote-file-to-carrierwave. – Ibrahim

+3

Nie działa, jeśli obraz nie jest wyświetlany przez HTTP. Otrzymasz następujący komunikat: 'Ikona próbująca pobrać plik, który nie jest obsługiwany przez HTTP' – Pioz

5

Od rozwiązań omawianych tu stworzyłem prosty CopyCarrierwaveFile gem to zrobić

wykorzystanie jest coś takiego:

original_resource = User.last 
new_resource  = User.new 

CopyCarrierwaveFile::CopyFileService.new(original_resource, new_resource, :avatar).set_file  

new_resource.save 
nev_resource.avatar.url # https://...image.jpg 
0

Oto (aczkolwiek hacky) rozwiązanie, które nie wymaga Prośba HTTP o pobranie obrazu:

module UploadCopier 
    def self.copy(old, new) 
    new.instance_variable_set('@_mounters', nil) 

    old.class.uploaders.each do |column, uploader| 
     new.send("#{column}=", old.send(column)) 
    end 
    end 
end 

old_user = User.last 
new_user = User.new 
UploadCopier.copy(old_user, new_user) 
new_user.save 
0

Chciałem tylko skopiować awatara odniesienia z jednego obiektu do drugiego, i co pracował dla mnie było:

objectB.avatar.retrieve_from_store!(objectA.avatar.identifier) 
objectB.save 
1

Musiałem skopiować odwołanie od jednego modelu do innego modelu, a ja z powodzeniem w stanie to zrobić w następujący sposób:

my_new_model.update_column('attachment', my_other_model.attributes["attachment"]); 

W tym scenariuszu nie chciałem zrobić kopii pliku, nie obchodzi mnie, że 2 rekordy zostały teraz połączone z tym samym plikiem (mój system nigdy nie usuwa ani nie modyfikuje plików po przesłaniu).

Może to być przydatne dla każdego, kto chce po prostu skopiować referencję do pliku z jednego modelu do innego modelu za pomocą tego samego programu do przesyłania.

+0

Nie działa dla mnie. https://stackoverflow.com/questions/45901396/carrierwave-sharing-an-image-between-two-models – Dercni

+1

@Dercni robi dobrą notatkę - ta metoda działa tylko wtedy, gdy żadne inne pola z wyjątkiem pola 'attachment' nie są używane ustal, gdzie znajduje się plik. – PressingOnAlways

+0

Po godzinach zmagań ze zdalnym adresem URL postanowiłem użyć twojego rozwiązania i mieć wspólną ścieżkę dla obu modeli i po prostu udostępnić plik, jak pokazałeś. – Dercni

Powiązane problemy