我在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