2012-04-27 19 views
6

Chcę zbudować 3-stopniową rejestrację użytkownika z załadowaniem awatara na drugim etapie. Więc podążam za przewodnikiem Ryana Batesa http://railscasts.com/episodes/217-multistep-forms. Używam klejnotu CarrierWave do obsługi wysyłania. Ale wydaje się, że nie mogę przechowywać przesłanych informacji o pliku w sesji użytkownika (nie mogę zrzucić błędu pliku). Używam następujące techniki w kontrolerzeFormularz wielostopniowy z przesyłającym obrazem

To rzeczywiście pomaga. Ale kiedy przesłać awarii zabronione typ pliku wszystko jest na tej linii

@uploader.store!(params[:user][:img_path]) 

z tym błędem

CarrierWave::IntegrityError in UsersController#create 
You are not allowed to upload "docx" files, allowed types: ["jpg", "jpeg", "gif", "png"] 

zamiast zwykłego błędu walidacji formularza.

Jak mogę rozwiązać ten problem? Dzięki !

+0

czy faktycznie przesyłasz plik obrazu lub plik ze słowami Microsoft Word? –

+0

Muszę sprawdzić typ pliku przed przesłaniem go. – AlphaB

+0

Powinieneś złapać 'CarrierWave :: IntegrityError' lub użyć metody' store() '(bez!), Aby nie wyświetlać błędu. –

Odpowiedz

3

Właściwie to rozwiązałem mój problem. Oto kod działa dla form wieloetapowych z przesyłania plików za pomocą carrierwave

if params[:user][:img_path] 
    @uploaded = params[:user][:img_path] 
    params[:user].delete(:img_path) 
end 
session[:user_data].deep_merge!(params[:user]) if params[:user] 
@user = User.new(session[:user_data])  

if @uploaded 
    # here how validation will work 
    @user.img_path = @uploaded 
end 
@user.current_stage = session[:register_stage] 
if @user.valid? 
    if @user.last_stage? 
    @user.img_path = session[:img] if @user.last_stage? 
    @user.save 
    else 
    @user.next_stage 
    end 
    # now we can store carrierwave object in session 
    session[:img] = @user.img_path 
    session[:register_stage] = @user.current_stage 
end 
+0

Gratulacje dla poprawki!Kiedy będziesz w stanie, upewnij się, że Twoja odpowiedź jest oznaczona jako "zaakceptowana", aby inni mogli uczyć się na Twoim sukcesie. Pozdrawiam ~ –

1

To może być trochę za późno na PO, ale mam nadzieję, że ktoś pomaga. Musiałem zapisać przesłany obraz w sesji użytkownika (ponownie dla formularza wieloetapowego), a ja też zacząłem od Ryana Railscast #217, ale aplikacja szybko wykroczyła poza to. Zauważ, że moje środowisko było Rails 4 na Ruby 2, używając Carrierwave i MiniMagick, a także activerecord-session_store, które wyjaśnię poniżej.

Uważam, że problemem, z którym miałem do czynienia zarówno z OP, jak i ze mną, było to, że próbowaliśmy dodać wszystkie parametry POST do sesji użytkownika, ale przy przesyłaniu pliku, jednym z parametrów był rzeczywisty obiekt UploadedFile, który jest sposobem na to duże. Podejście opisane poniżej jest kolejnym rozwiązaniem tego problemu.

Zastrzeżenie: Jak powszechnie wiadomo, nie jest idealne przechowywanie złożonych obiektów w sesji użytkownika, lepiej przechowywać identyfikatory rekordów lub inne dane identyfikatora (np. Ścieżkę obrazu) i wyszukiwać te dane, gdy jest to potrzebne. Dwa główne powody, dla których synchronizacja sesji i modelu/danych bazy danych jest zsynchronizowana (zadanie nietrywialne), a domyślny magazyn sesji Rails (z wykorzystaniem plików cookie) jest ograniczony do 4 kb.

mojego modelu (submission.rb):

class Submission < ActiveRecord::Base 
    mount_uploader :image_original, ImageUploader 
    # ... 
end 

Controller (submissions_controller.rb):

def create 
    # If the submission POST contains an image, set it as an instance variable, 
    # because we're going to remove it from the params 
    if params[:submission] && params[:submission][:image_original] && !params[:submission][:image_original].is_a?(String) 
    # Store the UploadedFile object as an instance variable 
    @image = params[:submission][:image_original] 
    # Remove the uploaded object from the submission POST params, since we 
    # don't want to merge the whole object into the user's session 
    params[:submission].delete(:image_original) 
    end 

    # Merge existing session with POST params 
    session[:submission_params].deep_merge!(params[:submission]) if params[:submission] 

    # Instantiate model from newly merged session/params 
    @submission = Submission.new(session[:submission_params]) 
    # Increment the current step in the session form 
    @submission.current_step = session[:submission_step] 

    # ... other steps in the form 

    # After deep_merge, bring back the image 
    if @image 
    # This adds the image back to the Carrierwave mounted uploader (which 
    # re-runs any processing/versions specified in the uploader class): 
    @submission.image_original = @image 
    # The mounted uploader now has the image stored in the Carrierwave cache, 
    # and provides us with the cache identifier, which is what we will save 
    # in our session: 
    session[:submission_params][:image_original] = @submission.image_original_cache 
    session[:image_processed_cached] = @submission.image_original.url(:image_processed) 
    end 

    # ... other steps in the form 

    # If we're on the last step of the form, fetch the image and save the model 
    if @submission.last_step? 
    # Re-populate the Carrierwave uploader's cache with the cache identifier 
    # saved in the session 
    @submission.image_original_cache = session[:submission_params][:image_original] 
    # Save the model 
    @submission.save 
    # ... render/redirect_to ... 
    end 
end 

Mój plik uploader był głównie zapasy z pewnym przetwarzania niestandardowej.

Uwaga: aby rozbudować sesji, używam ActiveRecord-session_store, który jest klejnotem, który był ekstrahowany z rdzenia Rails w V4, który dostarcza sklep sesji bazy danych oparciem (zwiększając limit sesji 4KB). Postępuj zgodnie z the documentation, aby uzyskać instrukcje instalacji, ale w moim przypadku było to dość szybkie i bezbolesne, aby ustawić i zapomnieć. Uwaga dla użytkowników o dużym natężeniu ruchu: pozostałe rekordy sesji nie wydają się być usuwane przez klejnot, więc jeśli uzyskasz wystarczający ruch, ta tabela może potencjalnie zostać wypełniona niezliczoną liczbą wierszy.

+0

Miałem do czynienia z tym samym problemem. proste rozwiązanie. Dzięki – Anwar