这对于 OP 来说可能有点晚了,但希望这对某人有所帮助。我需要在用户会话中存储上传的图像(同样是多步骤表单),我也是从 Ryan 的Railscast #217开始的,但应用程序很快就超越了这一点。请注意,我的环境是 Ruby 2 上的 Rails 4,使用 Carrierwave 和 MiniMagick 以及activerecord-session_store,我将在下面解释。
我相信 OP 和我都遇到的问题是我们试图将所有 POST 参数添加到用户的会话中,但是通过文件上传,其中一个参数是实际的 UploadedFile 对象,这对于那个来说很大. 下面描述的方法是该问题的另一种解决方案。
免责声明:正如广泛指出的那样,在用户会话中存储复杂对象并不理想,最好存储记录标识符或其他标识符数据(例如图像的路径)并在需要时查找该数据。保持会话和模型/数据库数据同步(一项重要任务)的两个主要原因,以及默认的 Rails 会话存储(使用 cookie)限制为 4kb。
我的模型(submission.rb):
class Submission < ActiveRecord::Base
mount_uploader :image_original, ImageUploader
# ...
end
控制器(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
我的上传文件主要是一些自定义处理的库存。
注意:为了加强会话,我使用了 activerecord-session_store,它是从 v4 中的 Rails 核心提取的一个 gem,它提供了一个数据库支持的会话存储(从而增加了 4kb 的会话限制)。请按照文档获取安装说明,但在我的情况下,设置它并忘记它非常快速且轻松。高流量用户注意:剩余的会话记录似乎没有被 gem 清除,所以如果你获得足够的流量,这个表可能会膨胀到无数行。