# encoding: utf-8 module Paperclip # The Style class holds the definition of a thumbnail style, applying # whatever processing is required to normalize the definition and delaying # the evaluation of block parameters until useful context is available. class Style attr_reader :name, :attachment, :formats # Creates a Style object. +name+ is the name of the attachment, # +definition+ is the style definition from has_attached_file, which # can be string, array or hash def initialize name, definition, attachment @name = name @attachment = attachment if definition.is_a? Hash @geometry = definition.delete(:geometry) self.format = definition.delete(:format) @processors = definition.delete(:processors) @other_args = definition else @geometry, @format = [definition, nil].flatten[0..1] @other_args = {} end @format = nil if @format.blank? end # retrieves from the attachment the processors defined in the has_attached_file call # (which method (in the attachment) will call any supplied procs) # There is an important change of interface here: a style rule can set its own processors # by default we behave as before, though. # if a proc has been supplied, we call it here def processors @processors.respond_to?(:call) ? @processors.call(attachment.instance) : (@processors || attachment.options.processors) end # retrieves from the attachment the whiny setting def whiny attachment.options.whiny end # returns true if we're inclined to grumble def whiny? !!whiny end def convert_options attachment.send(:extra_options_for, name) end def source_file_options attachment.send(:extra_source_file_options_for, name) end # returns the geometry string for this style # if a proc has been supplied, we call it here def geometry @geometry.respond_to?(:call) ? @geometry.call(attachment.instance) : @geometry end # Supplies the hash of options that processors expect to receive as their second argument # Arguments other than the standard geometry, format etc are just passed through from # initialization and any procs are called here, just before post-processing. def processor_options args = {} @other_args.each do |k,v| args[k] = v.respond_to?(:call) ? v.call(attachment) : v end [:processors, :geometry, :format, :whiny, :convert_options, :source_file_options].each do |k| (arg = send(k)) && args[k] = arg end args end # Supports getting and setting style properties with hash notation to ensure backwards-compatibility # eg. @attachment.options.styles[:large][:geometry]@ will still work def [](key) if [:name, :convert_options, :whiny, :processors, :geometry, :format, :formats, :animated, :source_file_options].include?(key) send(key) elsif defined? @other_args[key] @other_args[key] end end def []=(key, value) if [:name, :convert_options, :whiny, :processors, :geometry, :format, :formats, :animated, :source_file_options].include?(key) send("#{key}=".intern, value) else @other_args[key] = value end end def formats=(formats) @formats = formats.respond_to?(:split) ? formats.split(/\s+/) : formats.flatten end alias_method :format=, :formats= def format if @formats.present? && (filename = attachment.original_filename) ext = File.extname(filename)[1..-1] @formats.include?(ext) ? ext : @formats.first else nil end end end end