Esto puede ser un poco tarde para el PO, pero espero que esto ayude a alguien. Necesitaba almacenar una imagen cargada en la sesión del usuario (nuevamente para un formulario de varios pasos), y también comencé con la Railscast #217 de Ryan, pero la aplicación evolucionó rápidamente más allá de eso. Tenga en cuenta que mi entorno era Rails 4 en Ruby 2, utilizando Carrierwave y MiniMagick, así como activerecord-session_store, que explicaré a continuación.
Creo que el problema que tenía OP y yo era que estábamos tratando de agregar todos los parámetros de POST a la sesión del usuario, pero con una carga de archivos, uno de los parámetros era un objeto UploadedFile real, que es a lo grande por eso. El enfoque que se describe a continuación es otra solución a ese problema.
Descargo de responsabilidad: Como es ampliamente notado, no es ideal almacenar objetos complejos en una sesión de usuario, mejor almacenar identificadores de registro u otros datos identificadores (por ejemplo, la ruta de una imagen) y buscar esos datos cuando sea necesario. Dos razones principales para mantener la sesión y los datos de la base de datos/modelo en sincronía (una tarea no trivial), y el almacenamiento de sesión de Rails por defecto (usando cookies) están limitados a 4kb.
mi modelo (submission.rb):
class Submission < ActiveRecord::Base
mount_uploader :image_original, ImageUploader
# ...
end
Controlador (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
Mi cargador de archivos se abastecerse en su mayoría con algún tipo de procesamiento personalizado.
Nota: para reforzar las sesiones, estoy usando activerecord-session_store, que es una joya extraída del núcleo de Rails en v4 que proporciona un almacén de sesión respaldado por la base de datos (aumentando así el límite de 4kb de sesión). Siga the documentation para las instrucciones de instalación, pero en mi caso fue bastante rápido y sencillo configurarlo y olvidarlo. Nota para los usuarios con mucho tráfico: los registros de la sesión sobrante no parecen estar purgados por la gema, por lo que si obtiene suficiente tráfico, esta tabla podría llegar a innumerables filas.
¿de verdad está cargando un archivo de imagen o un archivo de palabra de Microsoft? –
necesito validar el tipo de archivo antes de cargarlo – AlphaB
Debería capturar el 'CarrierWave :: IntegrityError' o usar el método' store() '(without!), Para que no arroje el error. –