Пользовательская обрезка в Rails с помощью Paperclip - PullRequest
2 голосов
/ 14 октября 2010

В настоящее время я использую Paperclip для загрузки изображения и автоматического создания эскиза. Теперь я также хотел бы добавить второй стиль, который генерирует изображение шириной в один пиксель, используя крайний левый столбец пикселей в загруженном изображении (он также должен иметь ту же высоту, что и исходное изображение). Я буду использовать изображение размером в один пиксель в качестве повторяющегося фона с помощью CSS.

Можно ли сгенерировать это фоновое изображение с помощью стандартного процессора миниатюр Paperclip, или мне нужно будет создать собственный процессор? Я уже пытался создать собственный процессор, который подклассов Paperclip::Processor, но я не понимал, как правильно использовать метод Paperclip.run. Сейчас я пытаюсь создать подкласс Paperclip::Thumbnail на основе Ryan Bate's Railcast здесь: http://railscasts.com/episodes/182-cropping-images,, но это выдает эту ошибку:

NoMethodError (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]):
app/controllers/images_controller.rb:11:in `create'

Строка 11 images_controller.rb:

@image = @review.images.build(params[:image])

Строка 11 файла images_controller.rb работает нормально, если я не пытаюсь использовать собственный процессор Autobackground, поэтому ошибка должна быть в коде процессора.

Вот мой код:

#/app/models/image.rb
class Image < ActiveRecord::Base
   belongs_to :review

   has_attached_file :image, :styles => {
      :thumb => "32x32#",
      :auto_bg => { :processors => [:autobackground] }
   }
end

#/lib/paperclip_processors/Autobackground.rb
module Paperclip
   class Autobackground < Thumbnail
      def transformation_command
         if crop_command
            crop_command + super.sub(/ -crop \S+/, '')
         else
            super
         end
      end

      def crop_command
         target = @attachment.instance
         if target.cropping?
            " -crop '1x#{target.height}+0+0'"
         end
      end
   end
end

Ответы [ 2 ]

2 голосов
/ 14 октября 2010

Если кому-то интересно, мне удалось заставить это работать. Единственное, что действительно помогло мне больше всего исправить это консоль отладки Rails (которую я наконец-то начал правильно использовать), которая позволила мне более внимательно взглянуть на переменные в классе Paperclip :: Thumbnail , который мой Autobackground класс наследуется от.

Вот что я сделал: я изменил стиль :auto_bg, чтобы он указывал на специальную строку, которую я мог идентифицировать в своем процессоре. Поскольку мой процессор имеет подклассы от Paperclip::Thumbnail, строка, на которую указывает стиль, сохраняется в @options[:geometry]. Все, что мне нужно сделать в переопределенном методе transformation_command, это проверить, установлен ли @options[:geometry] в специальную строку auto_bg, а затем запустить мой метод create_auto_bg вместо того, чтобы позволить классу Thumbnail делать это как обычно. Мой старый метод create_auto_bg не создавал должным образом массив строк, который необходим Thumbnail для создания команды ImageMagick, поэтому я переписал его и использовал переменную @current_geometry, чтобы найти высоту исходного изображения вместо ошибочного target = @attachment.instance метод, который я скопировал из Railscast Райана Бэйта (не уверен, как это работает в его коде).

Я уверен, что есть более элегантное решение для этого, но я все еще новичок в Ruby и RoR, так что сейчас это нужно сделать. Надеюсь, это поможет любому, кто столкнулся с подобной проблемой:)

#/app/models/image.rb
class Image < ActiveRecord::Base
   belongs_to :review
   has_attached_file :image, :styles => { :thumb => "32x32#", :auto_bg => "auto_bg" }, :processors => [:autobackground]
end

#/lib/paperclip_processors/Autobackground.rb
module Paperclip
   class Autobackground < Thumbnail
      def transformation_command
         if @options[:geometry] == "auto_bg"
            create_auto_bg
         else
            super
         end
      end

      def create_auto_bg
         #debugger
         height = @current_geometry.height.to_i.to_s
         trans = []
         trans << "-crop" << "1x#{height}+0+0"
         trans
      end
   end
end
1 голос
/ 14 октября 2010

Я бы предложил вам написать вспомогательный метод и вызвать его с фильтром ...

Есть несколько доступных инструментов, которые могут творить эту магию для вас ...

еще одинкомментарий о стиле кодирования ...

Я бы предпочел написать код в стиле ruby, например

def crop_command
    target = @attachment.instance
    if target.cropping?
        " -crop '1x#{target.height}+0+0'"
    end
end

до

def crop_command
    target = @attachment.instance
    " -crop '1x#{target.height}+0+0'" if target.cropping?
end

везде, где это возможно, пожалуйста, используйтеособый стиль рубина ...

...