我在Rails应用程序中使用Paperclip来验证文件附件并将它们加载到AWS S3中。期望的行为是用户在提交记录表单时能够上传多个“RecordAttachments”(文件附件)。Rails:在保存父项之前保存子元素
问题在于,只要用户选择要使用文件选择器上载的文件,无论用户是否提交了“记录”表单,我都希望立即开始上传RecordAttachments。我也想确保每个RecordAttachment都被映射到它所属的记录。这一定是可能的,但我还不确定如何构建逻辑。
目前,我可以允许用户在填写并提交记录表单时创建多个RecordAttachments,但我想立即开始上传文件,以便我可以向用户显示表单页面上的每个上载进度。下面是允许用户提交多个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
并且子元素:
#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
记录控制器:
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
我的形式如下:
<%= 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 %>
考虑到此设置,是否有人知道任何方法,只要用户选择它们就可以开始上传RecordAttachments,而不是在他们提交记录表单时?
在用下面的@ShamSUP对此进行了说明之后,以下是我的想法:在页面加载时,检查用户是否有Record_id为零的任何RecordAttachments。如果是这样,请删除它们。然后用户选择一个或多个文件。对于每一个,将recordAid设置为nil的RecordAttachment表中保存一行。然后,如果/当用户成功提交其记录表单时,找到所有具有record_id == nil的用户的RecordAttachments,并将每个record_id设置为当前Record的id。
这似乎是一个合理的解决方案吗?有更好/更简单的方法吗?我非常感谢他人在这个问题上提供的任何帮助!
请注意,我没有太多关于ruby-specifics的信息,但这是客户端部分应该如何工作的。实际的上传脚本我不会帮助,但希望这可以指导您正确的方向。 – shamsup
感谢ShamSUP!在页面加载中将记录ID分配给记录是否是线程安全的?此外,恶意用户是否能够使用类似Chrome开发工具的方式来编辑隐藏字段中的recordid,从而使RecordAttachments指向错误的Record ID?想到我可以保存RecordAttachments,将他们返回的ID传递给当前用户的会话散列,然后在记录表单完成时,更新用户刚刚上传的每个RecordAttachment的record_id字段,是否疯了? – duhaime
会话变量肯定会走,我完全由于某种原因而使用它。 – shamsup