【问题标题】:Force paperclip to rename files when custom interpolation change自定义插值更改时强制回形针重命名文件
【发布时间】:2012-10-19 00:08:59
【问题描述】:

我使用 Paperclip 来管理 Rails 3 中某个模型的上传图像。这个模型belongs_to 另一个模型。我希望我的图像路径能够反映这种关系,因此我为此创建了一个自定义插值。

问题是,我还希望能够编辑 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 更新所有图像路径?

谢谢!

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 paperclip


    【解决方案1】:

    更健壮的文件路径可以使用 make id 而不是 make name。即,/cars/:make_id/:name/:style/:hash.png 将在 make 名称更改时继续工作。

    【讨论】:

    • 是的,这就是我最终所做的。
    • 我做不到,或者我丢失了所有现有数据......没有其他办法了吗?
    【解决方案2】:

    我找到了几种方法。让我解释一下。

    首先,我认为我们很多人都遇到过这个问题,将其设为默认回形针功能是有意义的。

    有两种解决方案:

    1. 将文件移动/重命名为新的逻辑:更干净、更少的 CPU 使用(无图像重新处理),但更多的是逐案(取决于插值、本地存储与 S3 存储等)和风险(在生产时)服务器)

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

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

    首先,您需要在文件逻辑移动时进行拦截。在我的例子中,我有一个before_save :generate_slug 方法,如果它发生变化,它会重新生成用户的slug。这是我应该放置回形针再生逻辑的地方,因为我的interpolation 包含slug

    我唯一需要做的就是将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
    

    希望有帮助,希望有更清洁的解决方案!

    【讨论】:

      猜你喜欢
      • 2011-08-02
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      • 2011-12-05
      • 1970-01-01
      • 2018-09-24
      • 1970-01-01
      相关资源
      最近更新 更多