我正在使用带有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
条件的原因(及其作用)。
有人可以向我解释一下吗?
答案 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