Пользовательская обрезка в Rails с помощью Paperclip

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

Можно ли сгенерировать это фоновое изображение с помощью обработчика эскизов Paperclip по умолчанию, или мне нужно будет создать свой собственный обработчик? Я уже пытался создать собственный процессор, который является подклассом Paperclip::Processor, но я не понял, как правильно использовать метод Paperclip.run. Теперь я пытаюсь создать подкласс Paperclip::Thumbnail на основе 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

person Avram    schedule 13.10.2010    source источник


Ответы (2)


Если кому интересно, мне удалось заставить это работать. Единственное, что действительно помогло мне исправить это, — это консоль отладки 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
person Avram    schedule 14.10.2010

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

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

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

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

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

to

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

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

person Sourcebits    schedule 14.10.2010