Trouble with Paperclip and Ajax with Rails 3.2.8

白昼怎懂夜的黑 提交于 2020-01-05 09:25:09

问题


I am writting an application 100% ajax with rails 3.2.8

Everything was going great until I tried to upload photos of the employees to the employee management module.

This is part of my code:

At the Controller:

class EmpleadosController < ApplicationController
  respond_to :js
  before_filter :require_user

  def index
    @empleados = Empleado.paginate( page: params[ :page ],
                                    joins: [:user,:contacto],
                                    select: 'empleados.id as id, empleados.user_id, empleados.contratado_el, empleados.despedido_el, empleados.nss, empleados.sueldo_base_semanal, empleados.comentarios, empleados.foto_file_name, empleados.foto_content_type, empleados.foto_file_size, empleados.foto_updated_at, users.username as username, contactos.salutacion_id as salutacion_id, contactos.id as contacto_id, contactos.nombres as nombres, contactos.apellidos as apellidos'
                                  ).sorted( params[ :sort ] )
  end


  def new
    @empleado = Empleado.new
  end

  def create
    @empleado = Empleado.new(params[:empleado])
    @empleado.sueldo_base_semanal = params[:empleado][:sueldo_base_semanal].gsub(',','').gsub('$','').to_f
    if @empleado.save
      redirect_to empleados_path
    else
      render action: 'new'
    end
  end
...

Now for the view (I am using HAML):

= form_for( @empleado, remote: true, html: {multipart: true} ) do |f|
  = show_me_the_errors @empleado

  %table.captura
    %tr
      %td.etiqueta
        = f.label :user_id
      %td.campo
        = f.select  :user_id,
                    User.usuarios_no_asignados,
                    { include_blank: true },
                    { tabindex: 1 }
        = image_tag 'nuevo_24.png',
                    style: 'vertical-align: bottom;',
                    id: 'empleado_nuevo_usuario'
... ( 5 more text fields ) ...

    %tr
      %td.etiqueta
        = f.label :foto
      %td.campo
        = f.file_field :foto,
                       accept: 'image/png,image/gif,image/jpeg'

The thing is that while there is not selected file for upload, everything works fine, the command respond_to :js works as it should be in all interactions between create with index and new.

But, when you select an image, all the interactions after create with index and new become HTML completely ignoring the respond_to :js, I mean, the form for behaves just like if the remote: true wasn't there

When everything works well, the URL is localhost:3000 and never changes, but when I select an image to upload, the URL after crete becomes localhost:3000/empleados

Does any one have any clue about this? I have been trying to solve this for the last 3 dyas and failed.

Thaks in advance.


回答1:


OK, after several days trying to find the problem I started working on a workaround. So this is it:

1) I created a DB Table for temprary storage, with the ID field set without autoincrement, and with the normal field names:

mysql> describe imagens;
+---------------------+--------------+------+-----+---------+-------+
| Field               | Type         | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+-------+
| id                  | int(11)      | NO   | PRI | NULL    |       |
| imagen_file_name    | varchar(500) | YES  |     | NULL    |       |
| imagen_content_type | varchar(500) | YES  |     | NULL    |       |
| imagen_file_size    | int(11)      | YES  |     | NULL    |       |
| imagen_updated_at   | datetime     | YES  |     | NULL    |       |
| created_at          | datetime     | NO   |     | NULL    |       |
| updated_at          | datetime     | NO   |     | NULL    |       |
| lock_version        | int(11)      | NO   |     | 0       |       |
+---------------------+--------------+------+-----+---------+-------+
8 rows in set (0.00 sec)

2) at the view (_form.html.haml):

-# this variable will be used as primary key for identifying the image to upload in the database
- ale = Time.now.to_i 

3) at the view (_form.html.haml):

I separated the file_field tag

-# FORM for general data input
= form_for( @empleado, remote: true ) do |f|
  ...

then, inside that form I add, a hidden file with the variable ale and a pretty small iframe

-# I use it in order to find out for wich record to search at the temporary DBTable 
= hidden_field_tag :ale, ale
-# this IFRAME will be used to catch the error message returned by rails when uploading the image, it will be invisible
%iframe{src: '#', frameborder:0, height: 0, width: 0, id: 'nulo', name: 'nulo'}

and encapsulated in its own form_for tag, but without any kind of submit or commit button.

= form_for( @imagen, remote: true, html: {multipart: true, target: 'nulo'} ) do |f|
  -# used to set the primary key to this value
  = hidden_field_tag :ale, ale
  = f.file_field :imagen, {style: 'vertical-align: middle;'}

then a little javascript to upload the image when the user choose one, it does the submit by an event trigger:

:javascript
  $('#imagen_imagen').change(function(){
    $('#new_imagen').submit();
  });

4) this is the content of the model for imagen (models/imagen.rb):

class Imagen < ActiveRecord::Base
  attr_accessible :imagen
  has_attached_file :imagen,
                    styles: { t100: '100x100>', t300: '300x300X', t600: '600x600' },
                    convert_options: { all: '-strip' },
                    path: ":rails_root/public/system/:class/:attachment/:id/:style/:filename",
                    url: "/system/:class/:attachment/:id/:style/:filename",
                    hash_secret: 'topsecret'
  validates_attachment_size :imagen,
                            less_than: 250.kilobytes,
                            message: (I18n.t :mensajes)[:paperclip][:grande]
end

5) this is the code at controllers/imagens_controller.rb :

class ImagensController < ApplicationController

  respond_to :js
  # by the way, this sline is from authlogic, a great gem to control the access to your site
  before_filter :require_user

  def create
    @imagen = Imagen.new(params[:imagen])
    @imagen.id = params[:ale]
    @imagen.save
    render text: ''
  end

end

6) now, in controller/empleados_controller.rb the code is:

def create
  @empleado = Empleado.new(params[:empleado])
  if @empleado.save
    imagen = Imagen.find(params[:ale].to_i)
    if imagen
      @empleado.foto = imagen.imagen
      @empleado.save
      imagen.destroy
    end
    redirect_to empleados_path
  else
    @imagen = Imagen.new
    render action: 'new'
  end
end

7) Glosary:

imagen = image

empleado = employee

empleados = staff

ale = short name for aleatorio, I mean, random

foto = picture o photograpy

8) Conclussion:

It works !!!

9) To-Do:

The drawback is that after you upload an image, it will be stored at the database, and then you can cancel the form or change page, that will leave the record and picture alive.

At the beginning I will make a link in my admin module that destroys all records from the Table holding the temporary images, with something like Imagen.all.each{|x| x.destroy }

Later on, I will write a script that at 2:00 a.m. executes that code.



来源:https://stackoverflow.com/questions/12955288/trouble-with-paperclip-and-ajax-with-rails-3-2-8

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!