我有一个表单来发送带有附件的消息。
- 用户选择附加文件
- 按"提交"并等待(长时间),直到所有文件上传完毕
- 用户忘记键入消息,因此验证失败
- 用户需要重新上传所有文件(长时间)
是否有一个简单的方法使rails记住已经上传的文件?(我一直在用回形针)
一种方法是在开始上传文件时使用默认(传递)值初始创建Message
对象,然后仅发出PUT请求以使用表单更新消息对象。
这样,Message
对象在创建时是有效的,您要验证的唯一一件事就是更新信息也是有效的(如果不是,则消息将具有默认值,用户不必重新上传文件)。
您可以设置数据库属性(通过Rails迁移)以设置默认值,因此您不必在控制器中这样做。
change_column_default(:messages, :content, "You have a new message!")
我不得不在最近的一个使用回形针的项目中修复这个问题。虽然有点俗气,但很管用。我试过在模型中使用after_validation和before_save调用cache_images(),但由于某种原因,我无法确定,所以我只是从控制器调用它。希望这能为其他人节省一些时间!
模型:
class Shop < ActiveRecord::Base
attr_accessor :logo_cache
has_attached_file :logo
def cache_images
if logo.staged?
if invalid?
FileUtils.cp(logo.queued_for_write[:original].path, logo.path(:original))
@logo_cache = encrypt(logo.path(:original))
end
else
if @logo_cache.present?
File.open(decrypt(@logo_cache)) {|f| assign_attributes(logo: f)}
end
end
end
private
def decrypt(data)
return '' unless data.present?
cipher = build_cipher(:decrypt, 'mypassword')
cipher.update(Base64.urlsafe_decode64(data).unpack('m')[0]) + cipher.final
end
def encrypt(data)
return '' unless data.present?
cipher = build_cipher(:encrypt, 'mypassword')
Base64.urlsafe_encode64([cipher.update(data) + cipher.final].pack('m'))
end
def build_cipher(type, password)
cipher = OpenSSL::Cipher::Cipher.new('DES-EDE3-CBC').send(type)
cipher.pkcs5_keyivgen(password)
cipher
end
end
控制器:
def create
@shop = Shop.new(shop_params)
@shop.user = current_user
@shop.cache_images
if @shop.save
redirect_to account_path, notice: 'Shop created!'
else
render :new
end
end
def update
@shop = current_user.shop
@shop.assign_attributes(shop_params)
@shop.cache_images
if @shop.save
redirect_to account_path, notice: 'Shop updated.'
else
render :edit
end
end
视图:
= f.file_field :logo
= f.hidden_field :logo_cache
- if @shop.logo.file?
%img{src: @shop.logo.url, alt: ''}