当自定义插值改变时,强制Paperclip重命名文件

4
我使用Paperclip来管理Rails 3中某个模型的上传图像。这个模型是另一个模型的附属品。我想让我的图像路径反映这种关系,所以我为此创建了一个自定义插值器。
问题在于,我也想能够编辑belongs_to对象的名称,并希望Paperclip相应地重命名文件。
以下是一个简单的示例:
class Make < ActiveRecord:Base
  attr_accessible :name

  has_many :models
end

class Model < ActiveRecord:Base
  attr_accessible :img, :make, :name

  belongs_to :make
  has_attached_file :img, :style => { :thumb => "100x100" },
                    :path => "/cars/:make_name/:name/:style/:hash.png",
                    :hash_secret => "blabla"

  Paperclip.interpolates :make_name do |attachment, style|
    attachment.instance.make.name
  end

  Paperclip.interpolates :name do |attachment, style|
    attachment.instance.name
  end
end 

假设我创建了一个名为Chevrolet和一个型号为Camaro的汽车,我的图片路径将是/cars/chevrolet/camaro/thumb/my_hash.png
如果我决定将Chevrolet条目名称更改为Chevy,Rails会尝试在/cars/chevy/camaro/thumb/my_hash.png位置查找图像,但由于图像未重命名,因此无法找到。
当条目被重命名时,如何强制Paperclip更新所有图像路径?
谢谢!
2个回答

2
更强大的文件路径可以使用制造商ID而不是制造商名称。例如,/cars/:make_id/:name/:style/:hash.png 在更改制造商名称时仍将继续工作。

是的,那就是我最终做的。 - nbarraille
我不能这样做,否则我会失去所有现有的数据... 难道没有其他解决办法吗? - Augustin Riedinger

0

我找到了几种解决办法。让我来解释一下。

首先,我认为这个问题发生在我们中的许多人身上,将它作为默认的paperclip功能是有道理的。

有两种解决方案:

  1. 将文件移动/重命名到新逻辑:更清洁,使用的CPU更少(无需图像重新处理),但更多是按情况而定(取决于插值、本地存储与S3存储等)并且有风险(当存在生产服务器时)

    以下是当人们决定移动文件时的答案:

  2. 创建一个新的,并销毁旧的。这是我选择的方法。

所以首先,你需要在文件逻辑移动时进行拦截。在我的情况下,我有一个 before_save :generate_slug 方法,如果用户的slug发生了变化,它会重新生成用户的slug。这就是我应该放置paperclip重新生成逻辑的地方,因为我的interpolation包含slug

唯一需要做的hacky事情是将http://localhost:3000添加到user.avatar.url中,因为当在本地时,它返回文件的本地路径,而不是用于执行URI.parseURI。我在生产中使用S3,所以在那种情况下它可以工作。
这是我的generate_slug方法:
  def generate_slug
    if !(self.slug == self.fullname.parameterize) # Changed
      if self.avatar.exists? # There actually is an avatar to move
        if self.avatar.url.include? "http"
          avatar_url = self.avatar.url
        else # means url is local path ==> needs to add localhost to have a correct URI
          avatar_url = 'http://localhost:3000' + self.avatar.url
        end
        self.avatar.clear # To remove the former file
      end

      self.slug = self.fullname.parameterize

      if !avatar_url.blank?
        self.avatar = URI.parse(avatar_url)
      end
    end
  end

希望它有所帮助,但愿有更简洁的解决方案!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接