I'm using Paperclip in a Rails app to validate file attachments and load them into AWS S3. The desired behavior is for users to be able to upload multiple "RecordAttachments" (file attachments) when they submit a Record form.
The catch is that I want to start uploading the RecordAttachments as soon as the user selects their files to upload with the file selector, regardless of whether the user has submitted the Record form. I also want to ensure each RecordAttachment is mapped to the Record to which it belongs. This must be possible, but I'm not yet sure how to build out the logic.
Currently, I can allow users to create multiple RecordAttachments when they fill out and submit the Record form, but I'd like to start uploading the files immediately so that I can show users the progress of each upload on the form page. Here's the code that lets users submit a Record with multiple RecordAttachments:
#app/models/record.rb
class Record < ActiveRecord::Base
has_many :record_attachments
accepts_nested_attributes_for :record_attachments
# Ensure user has provided the required fields
validates :title, presence: true
validates :description, presence: true
validates :metadata, presence: true
validates :hashtag, presence: true
validates :release_checked, presence: true
end
And the child element:
#app/models/record_attachment.rb
class RecordAttachment < ActiveRecord::Base
belongs_to :record
validates :file_upload, presence: true
# Before saving the record to the database, manually add a new
# field to the record that exposes the url where the file is uploaded
after_save :set_record_upload_url
# Use the has_attached_file method to add a file_upload property to the Record
# class.
has_attached_file :file_upload
# Validate that we accept the type of file the user is uploading
# by explicitly listing the mimetypes we are willing to accept
validates_attachment_content_type :file_upload,
:content_type => [
"video/mp4",
"video/quicktime"
]
end
Record Controller:
class RecordsController < ApplicationController
# GET /records/new
def new
@record = Record.new
end
def create
# retrieve the current cas user name from the session hash
@form_params = record_params()
@form_params[:cas_user_name] = session[:cas_user]
@record = Record.create( @form_params )
respond_to do |format|
if @record.save
if params[:record_attachments]
params[:record_attachments].each do |file_upload|
@record.record_attachments.create(file_upload: file_upload)
end
end
flash[:success] = "<strong>CONFIRMATION</strong>".html_safe +
": Thank you for your contribution to the archive."
format.html { redirect_to @record }
format.json { render action: 'show',
status: :created, location: @record }
else
format.html { render action: 'new' }
format.json { render json: @record.errors,
status: :unprocessable_entity }
end
end
end
end
My form looks like this:
<%= form_for @record, html: { multipart: true } do |f| %>
<div class="field">
<%= f.label :title, "Title of Material<sup>*</sup>".html_safe %>
<%= f.text_field :title %>
</div>
<!-- bunch of required fields followed by multiple file uploader: -->
<div id="file-upload-container" class="field">
<%= f.label :file_upload, "Upload File<sup>*</sup>".html_safe %>
<div id="placeholder-box">File name...</div>
<%= f.file_field :file_upload,
multiple: true,
type: :file,
name: 'record_attachments[]',
id: "custom-file-upload",
style: "display:none"
%>
<span class="btn btn-small btn-default btn-inverse" id="file-upload-button" onclick="$(this).parent().find('input[type=file]').click();">Browse</span>
</div>
<!-- bunch of fields followed by submit button -->
<%= button_tag(type: 'submit', class: "btn btn-primary blue-button submit-button") do %>
<i class="icon-ok icon-white"></i> SUBMIT
<% end %>
<% end %>
Given this setup, are others aware of any approaches that would allow me to start uploading the RecordAttachments as soon as the user selects them, rather than when they submit the Record form?
After talking this out with @ShamSUP below, here's what I'm thinking: On page load, check if user has any RecordAttachments for which the record_id is nil. If so, delete them. Then user selects one or more files. For each, save a row in the RecordAttachment table with the record_id set to nil. Then, if/when the user successfully submits their Record form, find all of the user’s RecordAttachments that have record_id == nil, and set the record_id of each to the current Record’s id.
Does this seem like a reasonable solution? Is there a better/easier method? I would be very grateful for any help others can offer on this question!