validate remove rails ruby-on-rails validation file-upload

ruby-on-rails - rails - remove image carrierwave



Cómo persistir los campos de carga de archivos después de un error de validación de los rieles. (6)

Bien - Pensé en tomar un enfoque diferente a esto; En lugar de almacenar temporalmente el archivo en el servidor, ¿por qué no volver a enviarlo al cliente para volver a enviarlo cuando el usuario solucione los problemas de validación?

Esto aún podría necesitar un poco de refinamiento, pero es el concepto general:

# in the controller - save the file and its attributes to params def create # ... if params[:doc] # a regular file uploaded through the file form element # when the form re-renders, it will have those additional params available to it params[:uploaded_file] = params[:doc].read # File contents params[:uploaded_file_original_filename] = params[:doc].original_filename params[:uploaded_file_headers] = params[:doc].headers params[:uploaded_file_content_type] = params[:doc].content_type elsif params[:uploaded_file] # a file coming through the form-resubmit # generate an ActionDispatch::Http::UploadedFile tempfile = Tempfile.new("#{params[:uploaded_file_original_filename]}-#{Time.now}") tempfile.binmode tempfile.write CGI.unescape(params[:uploaded_file]) #content of the file / unescaped tempfile.close # merge into the params params.merge!(doc: ActionDispatch::Http::UploadedFile.new( :tempfile => tempfile, :filename => params[:uploaded_file_original_filename], :head => params[:uploaded_file_headers], :type => params[:uploaded_file_content_type] ) ) end #... # params (including the UploadedFile) can be used to generate and save the model object end # in the form (haml) - if !params[:uploaded_file].blank? # file contents in hidden textarea element = text_area_tag(:uploaded_file, CGI.escape(params[:uploaded_file]), style: ''display: none;'') #escape the file content = hidden_field_tag :uploaded_file_headers, params[:uploaded_file_headers] = hidden_field_tag :uploaded_file_content_type, params[:uploaded_file_content_type] = hidden_field_tag :uploaded_file_original_filename, params[:uploaded_file_original_filename]

Tengo formulario con varias cargas de archivos. El problema es que cuando envío el formulario y se produce un error de validación, se restablece el campo de entrada del archivo.

Básicamente, quería conservar esos archivos dentro del campo de entrada del archivo para el proceso completo.

También he pasado por algunos enlaces

¿Cómo puedo "mantener" la imagen cargada en un error de validación de formulario?

Por favor, hágame saber cuáles son las diversas opciones en tales casos que uno puede seguir.




Tomé un enfoque completamente diferente a las otras soluciones que se ofrecen aquí, ya que no me apetecía cambiar a CarrierWave o usar otra gema para implementar un truco para evitar esto.

Básicamente, defino placeholders para mensajes de error de validación y luego hago una llamada AJAX al controlador relevante. si fallara la validación, simplemente llenaría los marcadores de posición del mensaje de error, esto deja todo en el lado del cliente, incluyendo la entrada del archivo lista para volver a enviar.

A continuación, se muestra un ejemplo de una organización con un modelo de dirección anidada y un modelo de logotipo anidado (que tiene un archivo adjunto); esto se ha reducido para abreviar:

organizaciones / _form.html.erb

<%= form_for @organisation, html: {class: ''form-horizontal'', role: ''form'', multipart: true}, remote: true do |f| %> <%= f.label :name %> <%= f.text_field :name %> <p class=''name error_explanation''></p> <%= f.fields_for :operational_address do |fa| %> <%= fa.label :postcode %> <%= fa.text_field :postcode %> <p class=''operational_address postcode error_explanation''></p> <% end %> <%= f.fields_for :logo do |fl| %> <%= fl.file_field :image %> <p class=''logo image error_explanation''></p> <% end %> <% end %>

organisations_controller.rb

def create if @organisation.save render :js => "window.location = ''#{organisations_path}''" else render :validation_errors end end

organizaciones / validation_errors.js.erb

$(''.error_explanation'').html(''''); <% @organisation.errors.messages.each do |attribute, messages| %> $(''.<%= attribute %>.error_explanation'').html("<%= messages.map{|message| "''#{message}''"}.join('', '') %>"); <% end %>


Tuve que arreglar esto en un proyecto reciente usando Paperclip Gem. Es un poco hacky pero funciona. Intenté llamar a cache_images () usando after_validation y before_save en el modelo pero falla al crear por algún motivo que no puedo determinar, así que simplemente lo llamo desde el controlador. ¡Ojalá esto le ahorre a alguien más algo de tiempo!

modelo:

class Shop < ActiveRecord::Base attr_accessor :logo_cache has_attached_file :logo def cache_images if logo.staged? if invalid? FileUtils.cp(logo.queued_for_write[:original].path, logo.path(:original)) @logo_cache = encrypt(logo.path(:original)) end else if @logo_cache.present? File.open(decrypt(@logo_cache)) {|f| assign_attributes(logo: f)} end end end private def decrypt(data) return '''' unless data.present? cipher = build_cipher(:decrypt, ''mypassword'') cipher.update(Base64.urlsafe_decode64(data).unpack(''m'')[0]) + cipher.final end def encrypt(data) return '''' unless data.present? cipher = build_cipher(:encrypt, ''mypassword'') Base64.urlsafe_encode64([cipher.update(data) + cipher.final].pack(''m'')) end def build_cipher(type, password) cipher = OpenSSL::Cipher::Cipher.new(''DES-EDE3-CBC'').send(type) cipher.pkcs5_keyivgen(password) cipher end end

controlador:

def create @shop = Shop.new(shop_params) @shop.user = current_user @shop.cache_images if @shop.save redirect_to account_path, notice: ''Shop created!'' else render :new end end def update @shop = current_user.shop @shop.assign_attributes(shop_params) @shop.cache_images if @shop.save redirect_to account_path, notice: ''Shop updated.'' else render :edit end end

ver:

= f.file_field :logo = f.hidden_field :logo_cache - if @shop.logo.file? %img{src: @shop.logo.url, alt: ''''}


Una solución para esto en lugar de una solución absoluta es usar la validación del lado del cliente para que el archivo no se pierda porque todo el formulario persiste.

Los pocos usuarios que no tienen habilitado JavaScript perderán los archivos entre las solicitudes, pero quizás este% sea tan bajo para que sea un compromiso aceptable. Si esta es la ruta que decides bajar, te recomendaría esta joya

https://github.com/bcardarella/client_side_validations

Lo que hace que todo el proceso sea realmente simple y significa que no tiene que volver a escribir su validación en JavaScript