Multistage form with image downloader

I want to create a three-step user registration with loading an avatar in the second step. Therefore, I follow the guide of Ryan Bates http://railscasts.com/episodes/217-multistep-forms . I use the CarrierWave gem to handle downloads. But it seems that I can not save the information about the downloaded file in the user session (I get can not reset the file error). I use the following technique in the controller

if params[:user][:img_path] @uploader = FirmImgUploader.new @uploader.store!(params[:user][:img_path]) session[:img] = @uploader params[:user].delete(:img_path) end 

It really helps. But when I load the forbidden file type, all the crashes in this line

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

with this error

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

instead of the usual form validation.

How can I solve this problem? Thanks!

+6
source share
2 answers

Actually, I solved my problem. Here's the working code for multi-stage forms with file loading using a carrier.

 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 
+3
source

It may be a little late for the OP, but hopefully this helps someone. I needed to save the downloaded image in a user session (again for a multi-stage form), and I also started with Ryan Railscast # 217 , but the application quickly evolved beyond that. Note that my environment was Rails 4 on Ruby 2 using Carrierwave and MiniMagick, as well as activerecord-session_store , which I will explain below.

I believe that the problem with the OP and me was that we tried to add all the POST parameters to the user session, but when the file was uploaded, one of the parameters was the actual UploadedFile object, which is a great way to do this. Another solution to this problem is the approach described below.

Disclaimer: as is widely known, it is not ideal for storing complex objects in a user session, it is better to store record identifiers or other identifier data (for example, the path to the image) and look for this data when necessary. The two main reasons for this: synchronizing the session and model / database data (non-trivial task), as well as the default Rails session store (using cookies) is limited to 4 KB.

My model (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 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 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 

My bootloader file was basically stock with some user processing.

Note. To strengthen the sessions, I use activerecord-session_store, which is a stone that was extracted from the Rails kernel in version 4, which provides a session storage with database support (thus increasing the 4kb session limit). Follow the documentation for the installation instructions, but in my case it was pretty quick and painless to install it and forget it. Note for users with high traffic: the remaining session entries do not seem to be cleared with a gem, so if you get enough traffic, this table could potentially flip to countless rows.

+1
source

Source: https://habr.com/ru/post/914358/


All Articles