我花了至少两天时间试图解决这个问题,过去几周我真的可以做一点方向,因为我觉得我已经完成了这里和其他地方列出的所有类似问题。
我使用模型关联和嵌套表单进行图像上传的Carrierwave设置,它工作正常。可以上载和更新图像。当我更改Post上的图像并导致表单验证失败时,设置图像缓存值(通过我添加到PostMediaUpload中的 upload_filename_cache =(text)方法确认),缓存值被放置在表单上的隐藏字段内,文件存储在tmp目录中。
当我使用传递验证重新提交表单时,缓存值似乎没有发生任何事情 - 没有错误,旧图像仍然存在。我试图尽可能多地包含信息。我希望这很简单,因为除了上传缓存版本的最后一步之外,一切似乎都按预期工作。
以下是我的模型的简化版本:
发布
has_one :post_media_upload, :dependent => :destroy
accepts_nested_attributes_for :post_media_upload, \
:reject_if => proc {|attributes| attributes['upload_filename'].blank? \
&& attributes['upload_filename_cache'].blank?}
发布媒体上传
class PostMediaUpload < ApplicationRecord
belongs_to :post
mount_uploader :upload_filename, PostImageUploader
validate :file_size_check
def upload_filename_cache=(text)
if upload_filename_cache
byebug
# TODO: We have a cached file, it exists in the hidden form field and the tmp/uploads folder
# On successful form validation, the cached version isn't uploaded to S3 / set to upload_filename.
#upload_filename = nil
#changed_attributes.merge!("upload_filename" => nil)
end
super
end
private
def file_size_check
if upload_filename.size > 5.megabytes
errors.add(:file_size, "should be less than 5MB")
end
end
end
发布媒体上传模式
create_table "post_media_uploads", force: :cascade do |t|
t.integer "post_id", null: false
t.string "upload_filename", null: false
t.string "original_filename", null: false
t.string "media_type", null: false
t.integer "file_size", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["post_id"], name: "index_post_media_uploads_on_post_id", using: :btree
end
PostImageUploader
class PostImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
# Save Original File Name
before :cache, :save_original_filename_and_data
storage :fog
def store_dir
"uploads/posts/#{model.post_id}"
end
# Alter File Name to be Unique
def filename
"#{secure_token}.#{file.extension}" if original_filename.present?
end
# White list of extensions which are allowed to be uploaded.
def extension_white_list
%w(jpg jpeg png)
end
def fog_public
false
end
def fog_authenticated_url_expiration
5.minutes # in seconds from now, (default is 10.minutes)
end
version :large do
process resize_to_limit: [800, 800]
end
version :medium, :from_version => :large do
process resize_to_limit: [500, 500]
end
version :thumb, :from_version => :medium do
process resize_to_fit: [100, 100]
end
version :square do
process :resize_to_fit => [300, nil]
end
protected
def save_original_filename_and_data(file)
model.original_filename ||= file.original_filename if file.respond_to?(:original_filename)
model.media_type = file.content_type
model.file_size = file.size
end
def secure_token
var = :"@#{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, Digest::SHA1.hexdigest([Time.now, rand].join))
end
end
发布表单
<%= f.fields_for :post_media_upload do |h| %>
Browse… <%= h.file_field :upload_filename, :multiple => false, :style => "display: none;", :onchange => "validateImageUpload(this);" %>
<%= h.hidden_field :upload_filename_cache, :value => post.post_media_upload.upload_filename_cache %>
<% end %>
发布白色列表的Params
def post_params
params.require(:post).permit(:title, ..omitted..
:is_private, post_media_upload_attributes: [:id, :post_id, :upload_filename, :upload_filename_cache] )
end
发布更新操作
if @post.update(post_params)
@post.set_pending_changes
redirect_to account_post_path(@post), notice: 'Your post was updated successfully'
else
# Build Nested Resource if not present
@post.build_post_media_upload unless @post.post_media_upload.present?
render :edit
end
提前谢谢!