【问题标题】:multiple paperclip attachements with watermark processor带有水印处理器的多个回形针附件
【发布时间】:2010-09-28 17:52:46
【问题描述】:

我在上传带有回形针的多个附件并使用水印处理它们时遇到了很多麻烦。

我有 2 个模型,广告和照片。 广告 has_many :photos 和照片 belongs_to :ad。

在 /models/ad.rb 中更准确地说,我有:

class Ad < ActiveRecord::Base

  has_many :photos, :dependent => :destroy
  accepts_nested_attributes_for :photos, :allow_destroy => true  
end

我的 photo.rb 文件如下所示:

class Photo < ActiveRecord::Base

belongs_to :ad

has_attached_file :data,
:styles => {
  :thumb => "100x100#",
  :first => {
    :processors => [:watermark],
    :geometry => '300x250#',
    :watermark_path => ':rails_root/public/images/watermark.png',
    :position => 'SouthEast' },
  :large => {
    :processors => [:watermark],
    :geometry => '640x480#',
    :watermark_path => ':rails_root/public/images/watermark.png',
    :position => 'SouthEast' }
}
end

在我看来,我使用它来添加文件字段

<% f.fields_for :photos do |p| %>

  <%= p.label :data, 'Poza:' %> <%= p.file_field :data %>

<% end %>

在我的控制器中,在编辑操作中,我使用4.times {@ad.photos.build} 生成文件字段。

如果我不使用水印处理器,如果我使用普通的 has_attached_file 声明,一切都可以正常工作,就像这样:

has_attached_file :data,
:styles => {
  :thumb => "100x100#",
  :first => '300x250#',
  :large => '640x480#'
}

但是当我使用水印处理器时,我总是收到这个错误:

 NoMethodError in PublicController#update_ad

 You have a nil object when you didn't expect it!
 You might have expected an instance of ActiveRecord::Base.
 The error occurred while evaluating nil.[]
  ..............................
 /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/nested_attributes.rb:350:in `assign_nested_attributes_for_collection_association'
 /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/nested_attributes.rb:345:in `each'
 /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/nested_attributes.rb:345:in `assign_nested_attributes_for_collection_association'
 /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/nested_attributes.rb:243:in `photos_attributes='
 /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2746:in `send'
 /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2746:in `attributes='
 /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2742:in `each'
 /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2742:in `attributes='
 /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2628:in `update_attributes'
 /home/alexg/Sites/vandmasina/app/controllers/public_controller.rb:217
 /home/alexg/Sites/vandmasina/app/controllers/public_controller.rb:216:in `update_ad'

参数还可以,我可以说

 Parameters:

 {"commit"=>"Salveaza modificarile",
  "ad"=>{"price"=>"6000",
  "oras"=>"9",
  "photos_attributes"=>{"0"=>{"data"=>#<File:/tmp/RackMultipart20100928-5130-b42noe-0>},
  "1"=>{"data"=>#<File:/tmp/RackMultipart20100928-5130-r0ukcr-0>},
  "2"=>{"data"=>#<File:/tmp/RackMultipart20100928-5130-mb23ei-0>},
  "3"=>{"data"=>#<File:/tmp/RackMultipart20100928-5130-1bpkm3b-0>}},

水印处理器 /lib/paperclip_processors/watermark.rb 如下所示:

  module Paperclip
class Watermark < Processor

class InstanceNotGiven < ArgumentError; 
end

def initialize(file, options = {},attachment = nil)
  super
  @file = file
  @current_format = File.extname(@file.path)
  @basename = File.basename(@file.path, @current_format)
  @watermark = ':rails_root/public/images/watermark.png'
  @current_geometry = Geometry.from_file file # This is pretty slow
  @watermark_geometry = watermark_dimensions
end

def watermark_dimensions
  return @watermark_dimensions if @watermark_dimensions
  @watermark_dimensions = Geometry.from_file @watermark
end

def make
  dst = Tempfile.new([@basename, @format].compact.join("."))
  watermark = " \\( #{@watermark} -extract #{@current_geometry.width.to_i}x#{@current_geometry.height.to_i}+#{@watermark_geometry.height.to_i /
                2}+#{@watermark_geometry.width.to_i / 2} \\) "
  command = "-gravity center " + watermark + File.expand_path(@file.path) + " " +File.expand_path(dst.path)

  begin
    success = Paperclip.run("composite", command.gsub(/\s+/, " "))
  rescue PaperclipCommandLineError
    raise PaperclipError, "There was an error processing the watermark for #{@basename}" if @whiny_thumbnails
  end
  dst
end

end
end

我已经在普通应用程序中尝试过处理器,没有多个附件,它运行完美。据我所知,它不适用于nested_attributes。

该应用是带有 ruby​​ 1.8.7 和回形针 2.3.11 的 rails 2.3.5

如果您能提供任何帮助,我们将不胜感激,因为我已经尝试了 2 天了 :)

【问题讨论】:

    标签: ruby-on-rails ruby image-processing paperclip nested-attributes


    【解决方案1】:

    如果您使用 rails 3 和回形针 > 2.3.3,请尝试https://gist.github.com/843418 source。

    【讨论】:

      【解决方案2】:

      哦,伙计,那是一个艰难的过程!

      您的代码中几乎没有错误,并且没有一个与嵌套模型相关。我的解释是针对 Rails 3 和 Paperclip 2.3.3

      a) :rails_root 不起作用。此插值仅用于 url/path 而不是自定义选项。所以你应该用 Rails.root.join("public/images...") 替换它

      b)您只需忽略 :watermark_path 选项并且仅使用硬编码路径(在初始化方法中)。因此,您的 :styles 中的内容并不重要,因为它总是用于 .../images/watermark.png。 :rails_root 又出现了,所以它不能工作。

      c) 当您将参数传递给 Paperclip.run("composite", "foo bar there") 时,它实际上会执行以下命令:

      composite 'foo bar there'
      

      你能看到单引号吗?因此,复合命令将您的参数视为一个巨大的参数并且根本不理解它。如果将其作为数组传递,则每个项目都包含在引号中,而不是整个数组。

      所以这里是水印处理器的改进版:

      module Paperclip
        class Watermark < Processor
      
        class InstanceNotGiven < ArgumentError;
        end
      
        def initialize(file, options = {},attachment = nil)
          super
          @file = file
          @current_format = File.extname(@file.path)
          @basename = File.basename(@file.path, @current_format)
          # PAWIEN: use default value only if option is not specified
          @watermark = options[:watermark_path] || Rails.root.join('public/images/watermark.png')
          @current_geometry = Geometry.from_file file # This is pretty slow
          @watermark_geometry = watermark_dimensions
        end
      
        def watermark_dimensions
          return @watermark_dimensions if @watermark_dimensions
          @watermark_dimensions = Geometry.from_file @watermark
        end
      
        def make
          dst = Tempfile.new([@basename, @format].compact.join("."))
          dst.binmode
      
          begin
            # PAWIEN: change original "stringy" approach to arrayish approach
            # inspired by the thumbnail processor
            options = [
              "-gravity",
              "center",
              "#{@watermark}",
              "-extract",
              "#{@current_geometry.width.to_i}x#{@current_geometry.height.to_i}+#{@watermark_geometry.height.to_i / 2}+#{@watermark_geometry.width.to_i / 2}",
              File.expand_path(@file.path),
              File.expand_path(dst.path)
            ].flatten.compact.join(" ").strip.squeeze(" ")
      
            success = Paperclip.run("composite", options)
          rescue PaperclipCommandLineError
            raise PaperclipError, "There was an error processing the watermark for #{@basename}" if @whiny_thumbnails
          end
          dst
        end
      
        end
      end
      

      希望对你有所帮助!

      更新:您需要使用来自 github 的最新回形针 gem

      gem 'paperclip', '>= 2.3.3', :git => "http://github.com/thoughtbot/paperclip.git"
      

      在此版本中,#run 的格式再次更改,因此我更新了代码。它真的应该可以工作,因为我已经创建了测试应用程序并且它正在做应该做的事情。

      更新 2:带有工作示例的回购:

      git://repo.or.cz/paperclip-mass-example.git
      

      【讨论】:

      • 感谢您的回答。现在似乎好多了,但我仍然收到错误。
      • PublicController#update_ad 中的参数数量错误(3 个中的 8 个)跟踪如下所示:paperclip_processors/watermark.rb:40: in runpaperclip_processors/watermark.rb:40: in @987654327 @controllers/public_controller.rb:217 controllers/public_controller.rb:216:in update_ad我的更新动作是经典的2.3,没有变化。
      • 似乎错误出现在 Paperclip.run(...) 行。最近发生了一些变化,这取决于您使用的回形针版本。只需打开文件 .../lib/paperclip/thumbnail.rb (从您的 gem 中,因此它将位于 ~/.rvm 中的某个位置)并在那里查看。顺便说一句,我运行它没有问题。
      • 啊!!!我会看看。有时我会想念好旧的越野车 RMagick :)) 非常感谢 m8,我会回来提供一些反馈
      【解决方案3】:

      乍一看,watermark_path 应该是“#{Rails.root}/...”,尽管看起来你在这里做了很多事情。

      另外,我看不到您在 form_for 中的表单。确保你有 {:multipart => true}

      【讨论】:

      • 如果你的意思是模型文件中的声明,我会试一试,虽然它没有达到这一点。
      • 在 @atermark 路径的 watermark.rb 中,我曾经拥有 RAILS_ROOT+'/public/images/watermark.png' 但这并没有改变任何东西。据我所知 :rails_root 符号的工作方式相同
      • 把东西放在引号里是一个文字字符串 ':rails_root' 不是一个符号 - 它是一个字符串
      • 嘿,你是对的。错过了那里的报价,只是太累了。会改回来告诉你结果,虽然我不认为这是原因。
      • 试过了,正如我所说,它没有任何区别。它甚至没有到达水印路径部分。问题在于nested_attributes。不知何故,回形针处理器不能很好地与它们配合使用。
      猜你喜欢
      • 1970-01-01
      • 2012-11-26
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多