Carrierwave宝石。如何在重新创建后重命名上传的图像版本?

时间:2018-01-06 11:58:42

标签: ruby-on-rails carrierwave

我有RailsCasts中描述的类似模型:

应用程序/模型/ resident.rb:

class Resident < ActiveRecord::Base
  include PhotoConcern
end

应用程序/模型/ employee.rb:

class Employee < ActiveRecord::Base
  include PhotoConcern
end

应用程序/模型/关切/ photo_concern.rb:

module PhotoConcern
  extend ActiveSupport::Concern

  included do
    mount_uploader :photo, PhotoUploader

    attr_accessor :photo_crop_x, :photo_crop_y, :photo_crop_w, :photo_crop_h

    after_save :crop_photo

    def crop_photo
      photo.recreate_versions! if photo_crop_x.present?
    end
  end
end

应用程序/上传/ photo_uploader.rb:

class PhotoUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  version :cropped do
    process :crop
  end

  version :thumb, from_version: :cropped do
    process resize_to_fill: [100, 100]
  end

  version :avatar, from_version: :cropped do
    process resize_to_fill: [200, 200]
  end

  def crop
    return if model.photo_crop_x.blank?

    resize_to_limit(500, nil)
    resize_to_fit(500, nil)

    manipulate! do |img|
      size = model.photo_crop_w << 'x' << model.photo_crop_h
      offset = '+' << model.photo_crop_x << '+' << model.photo_crop_y

      img.crop("#{size}#{offset}")
      img
    end
  end
end

应用程序/视图/雇员/ show.slim

= image_tag (@employee.photo.present? ? @employee.photo.url(:avatar) : "client_#{@employee.sex}.png"), class: 'img-circle img-responsive'

我想在裁剪后重命名版本文件,这样我的用户就不会对缓存感到困难。它在CarrierWave wiki中描述了如何重命名文件,但 it's written &#34;为了保存新生成的文件名,您必须调用save!在recreate_versions之后的模型上!&#34;。

如何重命名版本文件?我无法再次在我的员工save!中拨打after_save,因为有更多的挂钩不应该被调用两次。此外,PhotoConcern还包含在另一个类中。

相关的wiki文章:

2 个答案:

答案 0 :(得分:5)

  

为了保存新生成的文件名,您必须调用save!在recreate_versions之后的模型上!。

所以我相信你怀疑的答案包含在Carrierwave rubydocumentation

  

recreate_versions!(*versions) ⇒ Object

     

重新创建版本并重新处理它们。如果它们的参数以某种方式发生了变化,这可用于重新创建版本。

如果未省略*versions,则此方法将存储cached file,否则将存储# File 'lib/carrierwave/uploader/versions.rb', line 216 def recreate_versions!(*versions) # Some files could possibly not be stored on the local disk. This # doesn't play nicely with processing. Make sure that we're only # processing a cached file # # The call to store! will trigger the necessary callbacks to both # process this version and all sub-versions if versions.any? file = sanitized_file if !cached? # the file will be stored store_versions!(file, versions) else cache! if !cached? # If new_file is omitted, a previously cached file will be stored. store! end

store!(new_file = nil) ⇒ Object

store!做了什么?

这是the rubydoc page about store!

  

class PhotoUploader < CarrierWave::Uploader::Base

     

通过将文件传递给此Uploader的存储引擎来存储文件。   如果省略new_file,则将存储先前缓存的文件

此方法包含在with_callbacks中,并使用:store使用回调# File 'lib/carrierwave/uploader/store.rb', line 53 def store!(new_file=nil) cache!(new_file) if new_file && ((@cache_id != parent_cache_id) || @cache_id.nil?) if !cache_only and @file and @cache_id with_callbacks(:store, new_file) do new_file = storage.store!(@file) if delete_tmp_file_after_storage @file.delete unless move_to_store cache_storage.delete_dir!(cache_path(nil)) end @file = new_file @cache_id = nil end end end 存储您的文件。回调会触发此方法。

store_versions!

def store_versions!(new_file, versions=nil) if versions active = Hash[active_versions] versions.each { |v| active[v].try(:store!, new_file) } unless active.empty? else active_versions.each { |name, v| v.store!(new_file) } end end 方法做什么?

 after :store, :store_versions!

什么是Carrierwave回调以及如何使用它们?

after :store, :my_method

SO explainswiki上的这个问题解释了回调的工作原理,通过在version :low do区块内执行my_method,您将仅在after :store执行:store {1}}回调(仅适用于该版本)。

store!回调对应于@filename的执行。

recreate_versions!属性是什么? @filename如何编码文件名?

filename是使用lib/carrierwave/uploader/store.rb

中的方法## # Override this in your Uploader to change the filename. # # Be careful using record ids as filenames. If the filename is stored in the database # the record id will be nil when the filename is set. Don't use record ids unless you # understand this limitation. # # Do not use the version_name in the filename, as it will prevent versions from being # loaded correctly. # # === Returns # # [String] a filename # def filename @filename end 定义的
def filename

来自carrierwave的指南建议在使用recreate_version!重新创建版本时使用save!重新创建唯一的文件名。

此方法无法保存到数据库,要保存到数据库,您需要在appropriata Carrierwave回调上调用Carrierwave,而不会让您$user = wp_get_current_user(); if ( in_array( 'administrator', (array) $user->roles ) ) { //This user is administrator } GEM

我没有解决此问题的方法,但没有相关文档,我们应该开始构建它。

答案 1 :(得分:0)

对于那些希望在保存后更改上载文件名的人,您以某种方式重命名了磁盘上的文件。您可以直接在数据库中更改记录而无需回调,然后重新加载activerecord。

例如,

photo.update_column(:attachment_file_name, "new_name.jpg")
photo.reload