谁可以解释这个代码块是如何工作的:Carrierwave MD5作为文件名

时间:2014-01-02 12:16:30

标签: ruby sinatra carrierwave

我正在使用带有Sinatra应用的Carrierwave gem来上传和存储图片。

我关注How to: Use file's MD5 as filename,一切都按预期工作。但是,我不明白如何在操作方法页面上提供以下代码:

class ImageUploader < CarrierWave::Uploader::Base
  storage :file
  def md5
    chunk = model.send(mounted_as)
    @md5 ||= Digest::MD5.hexdigest(chunk.read)
  end
  def filename
    @name ||= "#{md5}#{File.extname(super)}" if super
  end
end

我特别不明白model.send(mounted_as)的作用,||=运算符的含义,以及使用if super条件的原因(及其作用)。

有人可以向我解释一下吗?

1 个答案:

答案 0 :(得分:1)

比如说,例如模型是Person,ImageUploader作为头像安装。

class Person < ActiveRecord::Base
  mount_uploader :avatar, ImageUploader
end

然后,md5方法将调用chunk = person.avatar的影响并使用它来计算文件内容的哈希值,这是你想要的名称。

filename方法检查是否存在@filename实例变量,如CarrierWave :: Uploader :: Store类中所定义。

class CarrierWave::Uploader::Store
  def filename
    @filename
  end
end

然后再次调用此方法以获取要在构造的文件名中使用的文件扩展名。 @name变量只是名称的临时缓存,因此将来对方法的调用不需要再次计算整个事物。

编辑:

carrierwave上传器具有模型的方法/实例变量(例如Person实例)和模型中声明的挂载点(例如avatar)。这些来自您的活动记录模型中的mount_uploader声明。

module CarrierWave::Uploader::Mountable
  attr_reader :model, :mounted_as

  def initialize(model=nil, mounted_as=nil)
    @model = model
    @mounted_as = mounted_as
  end
end

这些用于各种事物,以及让我们可以像你正在尝试的那样做。它只是一种调用person.avatar的抽象方式,它返回文件(文件实例不是字符串路径)。然后将其读入MD5 lib,它提供了hexdigest。

用更简单的术语重写

class ImageUploader < CarrierWave::Uploader::Base
  def md5
    uploaded_file = model.send(mounted_as) # person.avatar (File instance)
    @md5 ||= Digest::MD5.hexdigest(uploaded_file.read) # hexdigest of file content
  end
end