Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rails how do I handle multiple, polymorphic file uploads with jquery-file-upload and CarrierWave?

In my project I currently have different models (Project, Message, etc) that:

has_many :assets, :as => :attachable, :dependent => :destroy

Each Asset is basically a model with a CarrierWave file. Normally I would just use accepted_nested_attributes on the parent model (Project, Message, etc) and have the file upload fields listed in a fields_for block.

My problem is that since I'm using jQuery-File-Uploader with AJAX the parent model's form will call the parent model's Create method when ever a file is uploaded. The rest of the parent model fields might not be filled out yet. I'm thinking maybe I could have the file uploader call the create method in the Assets controller, but then I would some how have to send the parent model's class so the polymorphic association is stored correctly.

Any ideas of how I might get this working cleanly? Thanks for looking.

like image 481
jklina Avatar asked Oct 11 '22 07:10

jklina


1 Answers

OK.

Step 1

add gem 'carrier wave' to you Gemfile

Step 2

save the code to /lib/flash_session_cookie_middleware.rb

require 'rack/utils'

class FlashSessionCookieMiddleware
  def initialize(app, session_key = '_session_id')
    @app = app
    @session_key = session_key
  end

  def call(env)
    if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
      req = Rack::Request.new(env)
      env['HTTP_COOKIE'] = [ @session_key,
                             req.params[@session_key] ].join('=').freeze unless req.params[@session_key].nil?
      env['HTTP_ACCEPT'] = "#{req.params['_http_accept']}".freeze unless req.params['_http_accept'].nil?
    end

    @app.call(env)
  end
end

Step3

edit session_store.rb add the code to the end of file

Rails.application.config.middleware.insert_before(
  ActionDispatch::Session::CookieStore,
  FlashSessionCookieMiddleware,
  Rails.application.config.session_options[:key]
)

Step4

Download jquery.uploadify.js from Uploadify and unzip it.

Step5

  1. Copy jquery.uploadify.v2.1.4.min.js & swfobject.js to /app/assets/javascripts if you use Rails3.1 or later, to /public/javascripts if you use Rails 3.0 or before version.
  2. Copy uploadify.swf and cancel.png to /app/assets/images/ or /public/images
  3. Copy uploadify.css to /app/assets/stylesheets/ or /public/stylesheets

Step6

Edit your application.js, insert below code to it

//= require swfobject
//= require jquery.uploadify

Step7

In you upload page, add this

<input id="uploadify" name="uploadify" type="file" />

Step8

add this code to you upload page

$(document).ready(function() {
  <% key = Rails.application.config.session_options[:key] %>
  var uploadify_script_data = {};
  var csrf_param = $('meta[name=csrf-param]').attr('content');
  var csrf_token = $('meta[name=csrf-token]').attr('content');
  uploadify_script_data[csrf_param] = encodeURI(encodeURIComponent(csrf_token));
  uploadify_script_data['<%= key %>'] = '<%= cookies[key] %>';

  $('#uploadify').uploadify({
    uploader        : '/assets/uploadify.swf',
    script          : '/photos',
    cancelImg       : '/images/cancel.png',
    auto            : true,
    multi           : true,
    removeCompleted : true,
    scriptData      : uploadify_script_data,
    onComplete      : function(event, ID, fileObj, doc, data) {
    }
  });
});

Step9

Write your controller like this

def create
  @photo = Photo.new(:image => params[:Filedata])
  @photo.save
end
like image 81
VvDPzZ Avatar answered Nov 01 '22 10:11

VvDPzZ