使用 Rails 和 Paperclip 文件附件和处理验证错误

发布于 2024-12-23 13:12:20 字数 188 浏览 5 评论 0原文

我有一个表格可以发送带有附件的消息。

  • 用户选择要附加的文件
  • 按提交并等待(很长时间)直到所有文件上传
  • 用户忘记输入消息,因此验证失败
  • 用户需要再次上传所有文件(很长时间)

有没有一种简单的方法可以使Rails 记住已经上传的文件? (我一直用回形针)

I have a form to send a message with attachments.

  • User select files to attach
  • Press submit and wait (long time) until all the file are uploaded
  • The user forgot to type the message so the validation failed
  • The user need to upload all the files again (long time)

Is there a simple way to make rails to remember the already uploaded files? (I have been using paperclip)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

却一份温柔 2024-12-30 13:12:20

一种方法是在开始上传文件时最初使用默认(传递)值创建 Message 对象,然后仅发出 PUT 请求以使用表单更新消息对象。

这样,Message 对象在创建时就有效,并且您唯一要验证的是更新信息也有效(如果不是,则消息将仅具有默认值,并且用户不必重新上传文件)。

您可以设置数据库属性(通过 Rails 迁移)以设置默认值,这样您就不必在控制器中执行此操作。

change_column_default(:messages, :content, "You have a new message!")

One way would be to create the Message object initially with default (passing) values when you start uploading the file and then just issue a PUT request to update the message object using the form.

This way, the Message object is valid upon creation and the only thing you're validating is that the update information is valid as well (if it's not, the message will just have the default value and the user won't have to re-upload the file).

You can set up the database attribute (via a Rails migration) to have a set default value so you don't have to do this in the controller.

change_column_default(:messages, :content, "You have a new message!")
感情旳空白 2024-12-30 13:12:20

我必须在最近的一个项目中使用 PaperClip 来解决这个问题。这有点 hacky 但它确实有效。我尝试在模型中使用 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: ''}

I had to fix this on a recent project using PaperClip. It's a bit hacky but it works. I've tried calling cache_images() using after_validation and before_save in the model but it fails on create for some reason that I can't determine so I just call it from the controller instead. Hopefully this saves someone else some time!

model:

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

controller:

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

view:

= f.file_field :logo
= f.hidden_field :logo_cache

- if @shop.logo.file?
  %img{src: @shop.logo.url, alt: ''}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文