conditional convert options paperclip
Asked Answered
E

5

7

After some research I was able to add styles based on my image_class column.

Model.rb

has_attached_file :image,
                  :styles => lambda { |attachment| attachment.instance.decide_styles }

def decide_styles
  styles = {}

  case self.image_class
    when "poster"
      styles[:thumb] = ["30x45!", :jpg]
      styles[:standard] = ["185x278!", :jpg]
      styles[:expanded] = ["372x559!", :jpg]
      styles[:big] = ["600x900!", :jpg]
    when "cover"
      styles[:thumb] = ["30x45!", :jpg]
      styles[:standard] = ["300x1200!", :jpg]
  end

  styles
end

This works smoothly, now I wanted to add conditional convert_options as well. This somehow fails.

has_attached_file :image,
                  :styles => lambda { |attachment| attachment.instance.decide_styles }, 
                  :convert_options => lambda { |attachment| attachment.instance.decide_convert_options }

def decide_styles
  ...
end

def decide_convert_options

  opshunz = {}
  case self.image_class
    when "poster"
      opshunz[:thumb] = "-flop"
      opshunz[:standard] = "-flop"
      opshunz[:expanded] = "-flop"
      opshunz[:big] = "-flop"

    when "cover"
      opshunz[:thumb] = "-enhance"
      opshunz[:standard] = "-enhance"
  end

  opshunz
end

Error:

NoMethodError: undefined method `instance' for :all:Symbol

from /Users/AnsPoluke/Sites/nulike/app/models/movie_image.rb:8:in `block in <class:MovieImage>'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:431:in `[]'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:431:in `process_options'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:423:in `extra_options_for'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/style.rb:56:in `convert_options'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/style.rb:79:in `block in processor_options'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/style.rb:78:in `each'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/style.rb:78:in `processor_options'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:462:in `block in post_process_style'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:461:in `each'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:461:in `inject'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:461:in `post_process_style'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:454:in `block in post_process_styles'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:453:in `each'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:453:in `post_process_styles'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:445:in `block (2 levels) in post_process'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:393:in `_run__3861360263242897910__image_post_process__callbacks'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:80:in `run_callbacks'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/callbacks.rb:36:in `run_paperclip_callbacks'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:443:in `block in post_process'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:383:in `_run__3861360263242897910__post_process__callbacks'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:80:in `run_callbacks'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/callbacks.rb:36:in `run_paperclip_callbacks'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:442:in `post_process'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:114:in `assign'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/paperclip-4.1.1/lib/paperclip/has_attached_file.rb:66:in `block in define_setter'
from (irb):2
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/railties-4.0.2/lib/rails/commands/console.rb:90:in `start'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/railties-4.0.2/lib/rails/commands/console.rb:9:in `start'
from /Users/AnsPoluke/.rvm/gems/ruby-2.1.0/gems/railties-4.0.2/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'

Any ideas why it works perfectly with styles but fails with convert_options?

Europa answered 22/4, 2014 at 13:33 Comment(3)
I found a few solutions, but they actually reported exactly the same error as you see!Octavalent
Where'd you find them? And how is it a solution when throwing an error? :)Europa
lol I didn't mean "solution", I meant another Q where someone found a similar error & attempted to resolve!Octavalent
H
9

note: haven't verified that on working code

It seems that the argument to the block passed in :convert_options is already an instance, not the attachment (as opposed to styles option, where it is an attachment)

Try:

convert_options: lambda { |instance| instance.decide_convert_options }

Btw your code would look much better if you extract the configuration data, for example:

has_attached_file :image,
  styles: lambda { |attachment| attachment.instance.image_options[:styles] }, 
  convert_options: lambda { |instance| instance.image_options[:convert_options] }


IMAGE_OPTIONS = {
  poster: {
    styles: {
      thumb: ["30x45!", :jpg],
      standard: ["185x278!", :jpg],
      expanded: ["372x559!", :jpg]
      big: ["600x900!", :jpg]
    },
    convert_options: {
      thumb: "-flop",
      standard: "-flop",
      expanded: "-flop",
      big: = "-flop"
    }
  },
  cover: {
    styles: {
      thumb: ["30x45!", :jpg],
      standard: ["300x1200!", :jpg]
    },
    convert_options: {
      thumb: "-enhance",
      standard: "-enhance"
    }
  }
}

def image_options
  IMAGE_OPTIONS[self.image_class]
end

I hope that helps

Update:

it looks like your convert_options are not being set here: https://github.com/thoughtbot/paperclip/blob/a93dfc773b4fd649db4d1281b42a2a71b1ae72ff/lib/paperclip/style.rb#L55

it seems they recommend passing convert_options with styles, like in this spec: https://github.com/thoughtbot/paperclip/blob/263a498195d47563a6227be18cf4463c4c6e7903/spec/paperclip/style_spec.rb#L41

can you try this? so remove convert_options entirely, and in your configuration return hash like:

IMAGE_OPTIONS = {
      poster: {
        styles: {
          thumb: {
            geometry: "30x45!",
            format: :jpg,
            convert_options: '-flop',
          },
          standard: {...}
          expanded: {...}
          big: {...}
        }
      },
      cover: {
        styles: {...}
Horripilate answered 26/4, 2014 at 14:58 Comment(3)
I can see the exception is coming out from console / irb. What do you call there that causes the exception?Horripilate
Thanks allot! The last update solved the problem. Well deserved bounty :)Europa
I think this is not working anymore :( instance was replaced by the symbol (:all)Nonanonage
S
2

Apply it to all since that's what you're doing anyway?

:convert_options => {:all => "-flop"}

failing that you might be looking at creating a Paperclip Processor

Seamaid answered 25/4, 2014 at 9:37 Comment(2)
Thanks! The exact convert options of the newly added cover isn't clear yet, so I changed it to enhanced as it will surely differ from the posterEuropa
what about putting this in decide_styles: styles[:thumb] = ["30x45!", :jpg, {:convert_options => {:all => "-flop"}}] I think you can define convert_options within an individual styleSeamaid
B
2

The approved answer doesn't work. It can be read in the comments and the author acknowledges that it hasn't been tested in code.

This code does work:

has_attached_file :image,
                  :styles => lambda { |attachment|

                    thumb_convert_options = case attachment.instance.image_class
                      when "poster"
                        "-flop"
                      when "cover"
                        "-enhance"
                    end

                    {
                      thumb: {
                        convert_options: thumb_convert_options
                      }
                    }
                  }

The correct approach is to have convert_options inside the styles lambda; having it as a separate lambda does not work, at least for Paperclip version 4.1 and higher.

To keep my answer in one place, I've put all the code inline and omitted all styles beside thumb. Obviously to implement this you should keep the method decide_convert_options.

Bookcraft answered 14/1, 2015 at 11:39 Comment(3)
the code worked for me... What didn't work at yours?Europa
I kept getting NoMethodError: undefined method 'instance' for :all:Symbol until I changed it to the code above.Bookcraft
hmm strange, I do remember that it worked for me... but great to have another solution!Europa
C
1

Add the convert_options into the styles themselves. Here is an example for a generic rails Image model which contains two styles and corresponding booleans to enable these styles.

# == Schema Information
#
# Table name: images
#
#  id                 :integer          not null, primary key
#  image_file_name    :string(255)
#  image_content_type :string(255)
#  image_file_size    :integer
#  hero_style         :boolean 
#  thumb_style        :boolean 
#  image_updated_at   :datetime
#  created_at         :datetime         not null
#  updated_at         :datetime         not null
#

class Image < ActiveRecord::Base

  # These are the postprocessing options. 
  # The boolean <stylename>_style? attributes controls which styles are created. 

  STYLES = {
    hero: {geometry: "2500x800#", convert_options: "-quality 75 -strip", source_file_options: ""},
    thumb: {geometry: "312x100#", convert_options: "-quality 75 -strip", source_file_options: ""}  
  }

  has_attached_file :image,
    styles: 
      lambda { |file|
        r = {}
        STYLES.keys.each do |stylename|
          r[stylename] = STYLES[stylename] if file.instance.method("%s_style?" % stylename).call
        end
        return r
      }

  validates_attachment :image, :presence => true,
  content_type: { content_type: ["image/jpeg", "image/png"] },
  file_name: {matches: [/png\Z/, /jpe?g\Z/]}



end
Cursory answered 7/11, 2015 at 22:31 Comment(0)
B
1

You can also specify convert_options in styles:

class Image < ActiveRecord::Base
  has_attached_file :image, styles: -> (attachment) { attachment.instance.paperclip_styles }

  private

  def image_ratio
    # logic to define the image ratio
  end

  def paperclip_styles
    vitrina_geometry = image_ratio > 1.2 ? '268x156>' : '268x156^'
    vitrina_convert_options = if image_ratio > 1.2
      "-quality 75 -gravity center -crop '268x156+0+0'"
    else
      "-quality 75 -strip -gravity center -background '#FFFFFF' -extent 268x156"
    end

    {
      medium: { 
        geometry: '500x500>',
        convert_options: '-quality 75 -strip'
      },
      thumb: {
        geometry: '256x148>',
        convert_options: '-quality 75 -strip'
      },
      small: {
        geometry: '120x120>',
        convert_options: '-quality 75 -strip'
      },
      course_thumb: {
        geometry: '395x220^',
        convert_options: '-quality 75 -gravity center -crop \'395x220+0+0\''
      },
      :vitrina => {
        geometry: vitrina_geometry,
        convert_options: vitrina_convert_options
      }
    }
  end
end
Bak answered 20/11, 2018 at 20:17 Comment(1)
Thanks. This took way too long to find that this is possible. We also transcode video and applying convert_options to the main has_attached_file messes up the video transcoding. This works great because we can apply the convert_options only to the image styles. Btw, here's the docs that indicate this option is present on the Style object: rubydoc.info/github/thoughtbot/paperclip/…Protection

© 2022 - 2024 — McMap. All rights reserved.