lib/technoweenie/attachment_fu.rb in tdd-attachment_fu-0.9.6 vs lib/technoweenie/attachment_fu.rb in tdd-attachment_fu-0.9.9.b

- old
+ new

@@ -44,11 +44,24 @@ # * <tt>:content_type</tt> - Allowed content types. Allows all by default. Use :image to allow all standard image types. # * <tt>:min_size</tt> - Minimum size allowed. 1 byte is the default. # * <tt>:max_size</tt> - Maximum size allowed. 1.megabyte is the default. # * <tt>:size</tt> - Range of sizes allowed. (1..1.megabyte) is the default. This overrides the :min_size and :max_size options. # * <tt>:resize_to</tt> - Used by RMagick to resize images. Pass either an array of width/height, or a geometry string. - # * <tt>:thumbnails</tt> - Specifies a set of thumbnails to generate. This accepts a hash of filename suffixes and RMagick resizing options. + # * <tt>:jpeg_quality</tt> - Used to provide explicit JPEG quality for thumbnail/resize saves. Can have multiple formats: + # * Integer from 0 (basically crap) to 100 (basically lossless, fat files). + # * When relying on ImageScience, you can also use one of its +JPEG_xxx+ constants for predefined ratios/settings. + # * You can also use a Hash, with keys being either thumbnail symbols (I repeat: _symbols_) or surface boundaries. + # A surface boundary is a string starting with either '<' or '>=', followed by a number of pixels. This lets you + # specify per-thumbnail or per-general-thumbnail-"size" JPEG qualities. (which can be useful when you have a + # _lot_ of thumbnail options). Surface example: +{ '<2000' => 90, '>=2000' => 75 }+. + # Defaults vary depending on the processor (ImageScience: 100%, Rmagick/MiniMagick/Gd2: 75%, + # CoreImage: auto-adjust). Note that only tdd-image_science (available from GitHub) currently supports explicit JPEG quality; + # the default image_science currently forces 100%. + # * <tt>:thumbnails</tt> - Specifies a set of thumbnails to generate. This accepts a hash of filename suffixes and + # RMagick resizing options. If you have a polymorphic parent relationship, you can provide parent-type-specific + # thumbnail settings by using a pair with the type string as key and a Hash of thumbnail definitions as value. + # AttachmentFu automatically detects your first polymorphic +belongs_to+ relationship. # * <tt>:thumbnail_class</tt> - Set what class to use for thumbnails. This attachment class is used by default. # * <tt>:path_prefix</tt> - path to store the uploaded files. Uses public/#{table_name} by default for the filesystem, and just #{table_name} # for the S3 backend. Setting this sets the :storage to :file_system. # * <tt>:storage</tt> - Use :file_system to specify the attachment data is stored with the file system. Defaults to :db_system. @@ -249,10 +262,17 @@ tmp.binmode tmp.write data tmp.close end end + + def polymorphic_relation_type_column + return @@_polymorphic_relation_type_column if defined?(@@_polymorphic_relation_type_column) + # Checked against ActiveRecord 1.15.6 through Edge @ 2009-08-05. + ref = reflections.values.detect { |r| r.macro == :belongs_to && r.options[:polymorphic] } + @@_polymorphic_relation_type_column = ref && ref.options[:foreign_type] + end end module InstanceMethods def self.included(base) base.define_callbacks *[:after_resize, :after_attachment_saved, :before_thumbnail_saved] if base.respond_to?(:define_callbacks) @@ -451,11 +471,26 @@ # Cleans up after processing. Thumbnails are created, the attachment is stored to the backend, and the temp_paths are cleared. def after_process_attachment if @saved_attachment if respond_to?(:process_attachment_with_processing) && thumbnailable? && !attachment_options[:thumbnails].blank? && parent_id.nil? temp_file = temp_path || create_temp_file - attachment_options[:thumbnails].each { |suffix, size| create_or_update_thumbnail(temp_file, suffix, *size) } + attachment_options[:thumbnails].each { |suffix, size| + if size.is_a?(Symbol) + parent_type = polymorphic_parent_type + next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s) && respond_to?(size) + size = send(size) + end + if size.is_a?(Hash) + parent_type = polymorphic_parent_type + next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s) + size.each { |ppt_suffix, ppt_size| + create_or_update_thumbnail(temp_file, ppt_suffix, *ppt_size) + } + else + create_or_update_thumbnail(temp_file, suffix, *size) + end + } end save_to_storage @temp_paths.clear @saved_attachment = nil callback :after_attachment_saved @@ -506,9 +541,30 @@ end # Removes the thumbnails for the attachment, if it has any def destroy_thumbnails self.thumbnails.each { |thumbnail| thumbnail.destroy } if thumbnailable? + end + + def polymorphic_parent_type + rel_name = self.class.polymorphic_relation_type_column + rel_name && send(rel_name) + end + + def get_jpeg_quality(require_0_to_100 = true) + quality = attachment_options[:jpeg_quality] + if quality.is_a?(Hash) + sbl_quality = thumbnail && quality[thumbnail.to_sym] + sbl_quality = nil if sbl_quality && require_0_to_100 && !sbl_quality.to_i.between?(0, 100) + surface = (width || 1) * (height || 1) + size_quality = quality.detect { |k, v| + next unless k.is_a?(String) && k =~ /^(<|>=)(\d+)$/ + op, threshold = $1, $2.to_i + surface.send(op, threshold) + } + quality = sbl_quality || size_quality && size_quality[1] + end + return quality && (!require_0_to_100 || quality.to_i.between?(0, 100)) ? quality : nil end end end end