tdd-attachment_fu 0.9.6 → 0.9.9.b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +8 -0
- data/README +101 -45
- data/lib/technoweenie/attachment_fu.rb +58 -2
- data/lib/technoweenie/attachment_fu/processors/core_image_processor.rb +7 -6
- data/lib/technoweenie/attachment_fu/processors/gd2_processor.rb +4 -7
- data/lib/technoweenie/attachment_fu/processors/image_science_processor.rb +1 -1
- data/lib/technoweenie/attachment_fu/processors/mini_magick_processor.rb +10 -6
- data/lib/technoweenie/attachment_fu/processors/rmagick_processor.rb +5 -7
- data/test/basic_test.rb +60 -10
- data/test/fixtures/attachment.rb +51 -3
- data/test/processors/core_image_test.rb +10 -2
- data/test/processors/gd2_test.rb +9 -2
- data/test/processors/image_science_test.rb +9 -2
- data/test/processors/mini_magick_test.rb +9 -3
- data/test/processors/rmagick_test.rb +9 -3
- data/test/schema.rb +2 -0
- data/test/test_helper.rb +24 -1
- metadata +16 -7
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
* Mar 15, 2010 *
|
2
|
+
* Added a symbol syntax for parent-type-based size spec: calls the corresponding method on the current asset instance to
|
3
|
+
get a Hash of required thumbnails. Lets us dynamically specify what would otherwise be hard-coded, which is useful
|
4
|
+
when the set of thumbnails for a given parent type varies depending on the usage context.
|
5
|
+
|
6
|
+
* Aug 6, 2009 *
|
7
|
+
* JPEG quality control finalized across processors (although CoreImage applies it in a rather fuzzy-logic way), with tests.
|
8
|
+
|
1
9
|
* Aug 4, 2009 *
|
2
10
|
* Supports the :aspect/'!' geometry flag in all processors
|
3
11
|
(thanks to http://www.deepcalm.com/writing/cropped-thumbnails-in-attachment_fu-using-imagescience)
|
data/README
CHANGED
@@ -22,43 +22,80 @@ attachment_fu models
|
|
22
22
|
====================
|
23
23
|
|
24
24
|
For all three of these storage options a table of metadata is required. This table will contain information about the file (hence the 'meta') and its location. This table has no restrictions on naming, unlike the extra table required for database storage, which must have a table name of db_files (and by convention a model of DbFile).
|
25
|
-
|
25
|
+
|
26
26
|
In the model there are two methods made available by this plugins: has_attachment and validates_as_attachment.
|
27
27
|
|
28
28
|
has_attachment(options = {})
|
29
29
|
This method accepts the options in a hash:
|
30
|
-
:content_type
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
:
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
:
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
:
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
30
|
+
:content_type # Allowed content types.
|
31
|
+
# Allows all by default. Use :image to allow all standard image types.
|
32
|
+
#
|
33
|
+
:min_size # Minimum size allowed.
|
34
|
+
# 1 byte is the default.
|
35
|
+
#
|
36
|
+
:max_size # Maximum size allowed.
|
37
|
+
# 1.megabyte is the default.
|
38
|
+
#
|
39
|
+
:size # Range of sizes allowed.
|
40
|
+
# (1..1.megabyte) is the default. This overrides the :min_size and :max_size options.
|
41
|
+
#
|
42
|
+
:resize_to # Used by RMagick to resize images.
|
43
|
+
# Pass either an array of width/height, or a geometry string.
|
44
|
+
#
|
45
|
+
:thumbnails # Specifies a set of thumbnails to generate.
|
46
|
+
# This accepts a hash of filename suffixes and RMagick resizing options.
|
47
|
+
# This option need only be included if you want thumbnailing.
|
48
|
+
# If you have a polymorphic parent relationship, you can provide parent-type-specific
|
49
|
+
# thumbnail settings by using a pair with the type string as key and a Hash of thumbnail
|
50
|
+
# definitions, or a method symbol, as value. The method symbol will call the named
|
51
|
+
# method in order to get a dynamically-built Hash of thumbnail definitions, which gives
|
52
|
+
# you full flexibility.
|
53
|
+
# AttachmentFu automatically detects your first polymorphic +belongs_to+ relationship.
|
54
|
+
#
|
55
|
+
:thumbnail_class # Set which model class to use for thumbnails.
|
56
|
+
# This current attachment class is used by default.
|
57
|
+
#
|
58
|
+
:jpeg_quality # Used to provide explicit JPEG quality for thumbnail/resize saves. Can have multiple
|
59
|
+
# formats:
|
60
|
+
# * Integer from 0 (basically crap) to 100 (basically lossless, fat files).
|
61
|
+
# * When relying on tdd-image_science, you can also use one of its +JPEG_xxx+ constants
|
62
|
+
# for predefined ratios/settings.
|
63
|
+
# * You can also use a Hash, with keys being either thumbnail symbols (I repeat:
|
64
|
+
# _symbols_) or surface boundaries. A surface boundary is a string starting with either
|
65
|
+
# '<' or '>=', followed by a number of pixels. This lets you specify per-thumbnail or
|
66
|
+
# per-general-thumbnail-"size" JPEG qualities. (which can be useful when you have a
|
67
|
+
# _lot_ of thumbnail options). Surface example: +{ '<2000' => 90, '>=2000' => 75 }+.
|
68
|
+
#
|
69
|
+
# Defaults vary depending on the processor (ImageScience: 100%,
|
70
|
+
# Rmagick/MiniMagick/Gd2: 75%, CoreImage: auto-adjust).
|
71
|
+
# Note that only tdd-image_science (available from GitHub) currently supports explicit
|
72
|
+
# JPEG quality; the default image_science currently forces 100%.
|
73
|
+
#
|
74
|
+
:path_prefix # Path to store the uploaded files in.
|
75
|
+
# Uses public/#{table_name} by default for the filesystem, and just #{table_name} for the
|
76
|
+
# S3 and Cloud Files backend.
|
77
|
+
# Setting this sets the :storage to :file_system.
|
78
|
+
#
|
79
|
+
:partition # Whether to partiton files in directories like /0000/0001/image.jpg. Default is true.
|
80
|
+
# Only applicable to the :file_system backend.
|
81
|
+
#
|
82
|
+
:storage # Specifies the storage system to use..
|
83
|
+
# Defaults to :db_file. Options are :file_system, :db_file, :s3, and :cloud_files.
|
84
|
+
#
|
85
|
+
:cloudfront # If using S3 for storage, this option allows for serving the files via Amazon CloudFront.
|
86
|
+
# Defaults to false.
|
87
|
+
#
|
88
|
+
:processor # Sets the image processor to use for resizing of the attached image.
|
89
|
+
# Options include ImageScience, Rmagick, MiniMagick, Gd2 and CoreImage. Default is
|
90
|
+
# whatever is installed.
|
91
|
+
#
|
92
|
+
:uuid_primary_key # If your model's primary key is a 128-bit UUID in hexadecimal format, then set this to
|
93
|
+
# true.
|
94
|
+
#
|
95
|
+
:association_options # attachment_fu automatically defines associations with thumbnails with has_many and
|
96
|
+
# belongs_to. If there are any additional options that you want to pass to these methods,
|
97
|
+
# then specify them here.
|
98
|
+
|
62
99
|
|
63
100
|
Examples:
|
64
101
|
has_attachment :max_size => 1.kilobyte
|
@@ -69,7 +106,7 @@ has_attachment(options = {})
|
|
69
106
|
has_attachment :content_type => ['application/pdf', :image], :resize_to => 'x50'
|
70
107
|
has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
|
71
108
|
has_attachment :storage => :file_system, :path_prefix => 'public/files'
|
72
|
-
has_attachment :storage => :file_system, :path_prefix => 'public/files',
|
109
|
+
has_attachment :storage => :file_system, :path_prefix => 'public/files',
|
73
110
|
:content_type => :image, :resize_to => [50,50], :partition => false
|
74
111
|
has_attachment :storage => :file_system, :path_prefix => 'public/files',
|
75
112
|
:thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
|
@@ -77,9 +114,28 @@ has_attachment(options = {})
|
|
77
114
|
has_attachment :store => :s3, :cloudfront => true
|
78
115
|
has_attachment :storage => :cloud_files
|
79
116
|
|
117
|
+
# Let's say we have a polymorphic belongs_to, e.g. called 'imageable', where imageable_type (or whatever the
|
118
|
+
# :foreign_type option was set to) can be, among other things, 'Product', 'User' or 'Editorial', each of which
|
119
|
+
# should have extra thumbnails:
|
120
|
+
|
121
|
+
has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50',
|
122
|
+
:products => { :large_thumb => '169x169!', :zoomed => '500x500>' },
|
123
|
+
:editorials => { :fullsize => '150x100>' },
|
124
|
+
:users => { :avatar => '64x64!' } }
|
125
|
+
|
126
|
+
# JPEG qualities…
|
127
|
+
|
128
|
+
has_attachment :jpeg_quality => 75
|
129
|
+
has_attachment :jpeg_quality => 80 | ImageScience::JPEG_PROGRESSIVE
|
130
|
+
has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' },
|
131
|
+
:jpeg_quality => { nil => 75, :thumb => 90, :geometry => 90 }
|
132
|
+
has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' },
|
133
|
+
:jpeg_quality => { '<2000' => 90, '>=2000' => 75 }
|
134
|
+
}
|
135
|
+
|
80
136
|
validates_as_attachment
|
81
137
|
This method prevents files outside of the valid range (:min_size to :max_size, or the :size range) from being saved. It does not however, halt the upload of such files. They will be uploaded into memory regardless of size before validation.
|
82
|
-
|
138
|
+
|
83
139
|
Example:
|
84
140
|
validates_as_attachment
|
85
141
|
|
@@ -98,12 +154,12 @@ Fields for attachment_fu metadata tables...
|
|
98
154
|
that reference images that will be thumbnailed:
|
99
155
|
parent_id, :integer # id of parent image (on the same table, a self-referencing foreign-key).
|
100
156
|
# Only populated if the current object is a thumbnail.
|
101
|
-
thumbnail, :string # the 'type' of thumbnail this attachment record describes.
|
157
|
+
thumbnail, :string # the 'type' of thumbnail this attachment record describes.
|
102
158
|
# Only populated if the current object is a thumbnail.
|
103
159
|
# Usage:
|
104
160
|
# [ In Model 'Avatar' ]
|
105
|
-
# has_attachment :content_type => :image,
|
106
|
-
# :storage => :file_system,
|
161
|
+
# has_attachment :content_type => :image,
|
162
|
+
# :storage => :file_system,
|
107
163
|
# :max_size => 500.kilobytes,
|
108
164
|
# :resize_to => '320x200>',
|
109
165
|
# :thumbnails => { :small => '10x10>',
|
@@ -112,7 +168,7 @@ Fields for attachment_fu metadata tables...
|
|
112
168
|
# @user.avatar.thumbnails.first.thumbnail #=> 'small'
|
113
169
|
that reference files stored in the database (:db_file):
|
114
170
|
db_file_id, :integer # id of the file in the database (foreign key)
|
115
|
-
|
171
|
+
|
116
172
|
Field for attachment_fu db_files table:
|
117
173
|
data, :binary # binary file data, for use in database file storage
|
118
174
|
|
@@ -126,7 +182,7 @@ There are two parts of the upload form that differ from typical usage.
|
|
126
182
|
1. Include ':multipart => true' in the html options of the form_for tag.
|
127
183
|
Example:
|
128
184
|
<% form_for(:attachment_metadata, :url => { :action => "create" }, :html => { :multipart => true }) do |form| %>
|
129
|
-
|
185
|
+
|
130
186
|
2. Use the file_field helper with :uploaded_data as the field name.
|
131
187
|
Example:
|
132
188
|
<%= form.file_field :uploaded_data %>
|
@@ -154,7 +210,7 @@ Example:
|
|
154
210
|
def readme
|
155
211
|
send_file '/path/to/readme.txt', :type => 'plain/text', :disposition => 'inline'
|
156
212
|
end
|
157
|
-
|
213
|
+
|
158
214
|
See the possible values for send_file for reference.
|
159
215
|
|
160
216
|
|
@@ -167,7 +223,7 @@ Example in controller:
|
|
167
223
|
@attachable_file = AttachmentMetadataModel.new(params[:attachable])
|
168
224
|
if @attachable_file.save
|
169
225
|
flash[:notice] = 'Attachment was successfully created.'
|
170
|
-
redirect_to attachable_url(@attachable_file)
|
226
|
+
redirect_to attachable_url(@attachable_file)
|
171
227
|
else
|
172
228
|
render :action => :new
|
173
229
|
end
|
@@ -176,12 +232,12 @@ Example in controller:
|
|
176
232
|
attachement_fu scripting
|
177
233
|
====================================
|
178
234
|
|
179
|
-
You may wish to import a large number of images or attachments.
|
180
|
-
The following example shows how to upload a file from a script.
|
235
|
+
You may wish to import a large number of images or attachments.
|
236
|
+
The following example shows how to upload a file from a script.
|
181
237
|
|
182
238
|
#!/usr/bin/env ./script/runner
|
183
239
|
|
184
|
-
# required to use ActionController::TestUploadedFile
|
240
|
+
# required to use ActionController::TestUploadedFile
|
185
241
|
require 'action_controller'
|
186
242
|
require 'action_controller/test_process.rb'
|
187
243
|
|
@@ -46,7 +46,20 @@ module Technoweenie # :nodoc:
|
|
46
46
|
# * <tt>:max_size</tt> - Maximum size allowed. 1.megabyte is the default.
|
47
47
|
# * <tt>:size</tt> - Range of sizes allowed. (1..1.megabyte) is the default. This overrides the :min_size and :max_size options.
|
48
48
|
# * <tt>:resize_to</tt> - Used by RMagick to resize images. Pass either an array of width/height, or a geometry string.
|
49
|
-
# * <tt>:
|
49
|
+
# * <tt>:jpeg_quality</tt> - Used to provide explicit JPEG quality for thumbnail/resize saves. Can have multiple formats:
|
50
|
+
# * Integer from 0 (basically crap) to 100 (basically lossless, fat files).
|
51
|
+
# * When relying on ImageScience, you can also use one of its +JPEG_xxx+ constants for predefined ratios/settings.
|
52
|
+
# * You can also use a Hash, with keys being either thumbnail symbols (I repeat: _symbols_) or surface boundaries.
|
53
|
+
# A surface boundary is a string starting with either '<' or '>=', followed by a number of pixels. This lets you
|
54
|
+
# specify per-thumbnail or per-general-thumbnail-"size" JPEG qualities. (which can be useful when you have a
|
55
|
+
# _lot_ of thumbnail options). Surface example: +{ '<2000' => 90, '>=2000' => 75 }+.
|
56
|
+
# Defaults vary depending on the processor (ImageScience: 100%, Rmagick/MiniMagick/Gd2: 75%,
|
57
|
+
# CoreImage: auto-adjust). Note that only tdd-image_science (available from GitHub) currently supports explicit JPEG quality;
|
58
|
+
# the default image_science currently forces 100%.
|
59
|
+
# * <tt>:thumbnails</tt> - Specifies a set of thumbnails to generate. This accepts a hash of filename suffixes and
|
60
|
+
# RMagick resizing options. If you have a polymorphic parent relationship, you can provide parent-type-specific
|
61
|
+
# thumbnail settings by using a pair with the type string as key and a Hash of thumbnail definitions as value.
|
62
|
+
# AttachmentFu automatically detects your first polymorphic +belongs_to+ relationship.
|
50
63
|
# * <tt>:thumbnail_class</tt> - Set what class to use for thumbnails. This attachment class is used by default.
|
51
64
|
# * <tt>:path_prefix</tt> - path to store the uploaded files. Uses public/#{table_name} by default for the filesystem, and just #{table_name}
|
52
65
|
# for the S3 backend. Setting this sets the :storage to :file_system.
|
@@ -251,6 +264,13 @@ module Technoweenie # :nodoc:
|
|
251
264
|
tmp.close
|
252
265
|
end
|
253
266
|
end
|
267
|
+
|
268
|
+
def polymorphic_relation_type_column
|
269
|
+
return @@_polymorphic_relation_type_column if defined?(@@_polymorphic_relation_type_column)
|
270
|
+
# Checked against ActiveRecord 1.15.6 through Edge @ 2009-08-05.
|
271
|
+
ref = reflections.values.detect { |r| r.macro == :belongs_to && r.options[:polymorphic] }
|
272
|
+
@@_polymorphic_relation_type_column = ref && ref.options[:foreign_type]
|
273
|
+
end
|
254
274
|
end
|
255
275
|
|
256
276
|
module InstanceMethods
|
@@ -453,7 +473,22 @@ module Technoweenie # :nodoc:
|
|
453
473
|
if @saved_attachment
|
454
474
|
if respond_to?(:process_attachment_with_processing) && thumbnailable? && !attachment_options[:thumbnails].blank? && parent_id.nil?
|
455
475
|
temp_file = temp_path || create_temp_file
|
456
|
-
attachment_options[:thumbnails].each { |suffix, size|
|
476
|
+
attachment_options[:thumbnails].each { |suffix, size|
|
477
|
+
if size.is_a?(Symbol)
|
478
|
+
parent_type = polymorphic_parent_type
|
479
|
+
next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s) && respond_to?(size)
|
480
|
+
size = send(size)
|
481
|
+
end
|
482
|
+
if size.is_a?(Hash)
|
483
|
+
parent_type = polymorphic_parent_type
|
484
|
+
next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s)
|
485
|
+
size.each { |ppt_suffix, ppt_size|
|
486
|
+
create_or_update_thumbnail(temp_file, ppt_suffix, *ppt_size)
|
487
|
+
}
|
488
|
+
else
|
489
|
+
create_or_update_thumbnail(temp_file, suffix, *size)
|
490
|
+
end
|
491
|
+
}
|
457
492
|
end
|
458
493
|
save_to_storage
|
459
494
|
@temp_paths.clear
|
@@ -509,6 +544,27 @@ module Technoweenie # :nodoc:
|
|
509
544
|
def destroy_thumbnails
|
510
545
|
self.thumbnails.each { |thumbnail| thumbnail.destroy } if thumbnailable?
|
511
546
|
end
|
547
|
+
|
548
|
+
def polymorphic_parent_type
|
549
|
+
rel_name = self.class.polymorphic_relation_type_column
|
550
|
+
rel_name && send(rel_name)
|
551
|
+
end
|
552
|
+
|
553
|
+
def get_jpeg_quality(require_0_to_100 = true)
|
554
|
+
quality = attachment_options[:jpeg_quality]
|
555
|
+
if quality.is_a?(Hash)
|
556
|
+
sbl_quality = thumbnail && quality[thumbnail.to_sym]
|
557
|
+
sbl_quality = nil if sbl_quality && require_0_to_100 && !sbl_quality.to_i.between?(0, 100)
|
558
|
+
surface = (width || 1) * (height || 1)
|
559
|
+
size_quality = quality.detect { |k, v|
|
560
|
+
next unless k.is_a?(String) && k =~ /^(<|>=)(\d+)$/
|
561
|
+
op, threshold = $1, $2.to_i
|
562
|
+
surface.send(op, threshold)
|
563
|
+
}
|
564
|
+
quality = sbl_quality || size_quality && size_quality[1]
|
565
|
+
end
|
566
|
+
return quality && (!require_0_to_100 || quality.to_i.between?(0, 100)) ? quality : nil
|
567
|
+
end
|
512
568
|
end
|
513
569
|
end
|
514
570
|
end
|
@@ -44,16 +44,17 @@ module Technoweenie # :nodoc:
|
|
44
44
|
processor.render do |result|
|
45
45
|
self.width = result.extent.size.width if respond_to?(:width)
|
46
46
|
self.height = result.extent.size.height if respond_to?(:height)
|
47
|
-
|
48
|
-
# Get a new temp_path for the image before saving
|
49
47
|
out_file = random_tempfile_filename
|
50
48
|
temp_paths.unshift Tempfile.new(out_file, Technoweenie::AttachmentFu.tempfile_path).path
|
51
49
|
properties = nil
|
52
|
-
|
53
|
-
|
54
|
-
quality =
|
55
|
-
properties = { OSX::NSImageCompressionFactor => quality / 100.0 } if
|
50
|
+
# We don't check the source image since we're forcing the output to JPEG, apparently…
|
51
|
+
# Beware: apparently CoreImage only takes the percentage as a HINT, using a different actual quality…
|
52
|
+
quality = get_jpeg_quality
|
53
|
+
properties = { OSX::NSImageCompressionFactor => quality / 100.0 } if quality
|
56
54
|
result.save(self.temp_path, OSX::NSJPEGFileType, properties)
|
55
|
+
#
|
56
|
+
# puts "#{self.temp_path} @ #{quality.inspect} -> #{%x(identify -format '%Q' "#{self.temp_path}")}"
|
57
|
+
#
|
57
58
|
self.size = File.size(self.temp_path)
|
58
59
|
end
|
59
60
|
end
|
@@ -44,16 +44,13 @@ module Technoweenie # :nodoc:
|
|
44
44
|
w, h = [img.width, img.height] / size.to_s
|
45
45
|
img.resize!(w, h, false)
|
46
46
|
end
|
47
|
+
self.width = img.width if respond_to?(:width)
|
48
|
+
self.height = img.height if respond_to?(:height)
|
47
49
|
out_file = random_tempfile_filename
|
48
50
|
temp_paths.unshift out_file
|
49
51
|
jpeg = out_file =~ /\.jpe?g\z/i
|
50
|
-
quality =
|
51
|
-
|
52
|
-
self.size = if jpeg && quality.between?(0, 100)
|
53
|
-
img.export(self.temp_path, :quality => quality)
|
54
|
-
else
|
55
|
-
img.export(self.temp_path)
|
56
|
-
end
|
52
|
+
quality = jpeg && get_jpeg_quality
|
53
|
+
self.size = img.export(self.temp_path, quality ? { :quality => quality } : {})
|
57
54
|
end
|
58
55
|
|
59
56
|
end
|
@@ -40,7 +40,7 @@ module Technoweenie # :nodoc:
|
|
40
40
|
self.height = img.height if respond_to?(:height)
|
41
41
|
|
42
42
|
# We don't check for quality being a 0-100 value as we also allow FreeImage JPEG_xxx constants.
|
43
|
-
quality =
|
43
|
+
quality = content_type[/jpe?g/i] && get_jpeg_quality(false)
|
44
44
|
# Traditional ImageScience has a 1-arg save method, tdd-image_science has 1 mandatory + 1 optional
|
45
45
|
if quality && img.method(:save).arity == -2
|
46
46
|
img.save self.temp_path, quality
|
@@ -38,18 +38,13 @@ module Technoweenie # :nodoc:
|
|
38
38
|
# Performs the actual resizing operation for a thumbnail
|
39
39
|
def resize_image(img, size)
|
40
40
|
size = size.first if size.is_a?(Array) && size.length == 1
|
41
|
+
format = img[:format]
|
41
42
|
img.combine_options do |commands|
|
42
43
|
commands.strip unless attachment_options[:keep_profile]
|
43
44
|
|
44
45
|
# GIF is not handled correctly, so we move to PNG, as in other processors…
|
45
|
-
format = img['format']
|
46
46
|
if format == 'GIF'
|
47
47
|
commands.format('PNG')
|
48
|
-
elsif format == 'JPEG'
|
49
|
-
quality = attachment_options[:jpeg_quality]
|
50
|
-
quality = quality ? quality.to_i : -1
|
51
|
-
# FIXME: this DOESN'T work, for whatever reason…
|
52
|
-
commands.quality(quality) if quality.between?(0, 100)
|
53
48
|
end
|
54
49
|
|
55
50
|
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
|
@@ -101,7 +96,16 @@ module Technoweenie # :nodoc:
|
|
101
96
|
commands.resize(size.to_s)
|
102
97
|
end
|
103
98
|
end
|
99
|
+
dims = img[:dimensions]
|
100
|
+
self.width = dims[0] if respond_to?(:width)
|
101
|
+
self.height = dims[1] if respond_to?(:height)
|
102
|
+
# Has to be done this far so we get proper dimensions
|
103
|
+
if format == 'JPEG'
|
104
|
+
quality = get_jpeg_quality
|
105
|
+
img.quality(quality) if quality
|
106
|
+
end
|
104
107
|
temp_paths.unshift img
|
108
|
+
self.size = File.size(self.temp_path)
|
105
109
|
end
|
106
110
|
|
107
111
|
def calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
|
@@ -49,15 +49,13 @@ module Technoweenie # :nodoc:
|
|
49
49
|
else
|
50
50
|
img.change_geometry(size.to_s) { |cols, rows, image| image.resize!(cols<1 ? 1 : cols, rows<1 ? 1 : rows) }
|
51
51
|
end
|
52
|
+
self.width = img.columns if respond_to?(:width)
|
53
|
+
self.height = img.rows if respond_to?(:height)
|
52
54
|
img.strip! unless attachment_options[:keep_profile]
|
53
|
-
|
54
|
-
out_file = write_to_temp_file(img.to_blob {
|
55
|
-
qty = opts[:jpeg_quality]
|
56
|
-
qty = qty ? qty.to_i : -1
|
57
|
-
# FIXME: this DOESN'T work, for whatever reason…
|
58
|
-
self.quality = qty if img.format.to_s[/JPEG/] && qty.between?(0, 100)
|
59
|
-
})
|
55
|
+
quality = img.format.to_s[/JPEG/] && get_jpeg_quality
|
56
|
+
out_file = write_to_temp_file(img.to_blob { self.quality = quality if quality })
|
60
57
|
temp_paths.unshift out_file
|
58
|
+
self.size = File.size(self.temp_path)
|
61
59
|
end
|
62
60
|
end
|
63
61
|
end
|
data/test/basic_test.rb
CHANGED
@@ -4,15 +4,15 @@ class BasicTest < Test::Unit::TestCase
|
|
4
4
|
def test_should_set_default_min_size
|
5
5
|
assert_equal 1, Attachment.attachment_options[:min_size]
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def test_should_set_default_max_size
|
9
9
|
assert_equal 1.megabyte, Attachment.attachment_options[:max_size]
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def test_should_set_default_size
|
13
13
|
assert_equal (1..1.megabyte), Attachment.attachment_options[:size]
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def test_should_set_default_thumbnails_option
|
17
17
|
assert_equal Hash.new, Attachment.attachment_options[:thumbnails]
|
18
18
|
end
|
@@ -20,19 +20,19 @@ class BasicTest < Test::Unit::TestCase
|
|
20
20
|
def test_should_set_default_thumbnail_class
|
21
21
|
assert_equal Attachment, Attachment.attachment_options[:thumbnail_class]
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def test_should_normalize_content_types_to_array
|
25
25
|
assert_equal %w(pdf), PdfAttachment.attachment_options[:content_type]
|
26
26
|
assert_equal %w(pdf doc txt), DocAttachment.attachment_options[:content_type]
|
27
27
|
assert_equal Technoweenie::AttachmentFu.content_types, ImageAttachment.attachment_options[:content_type]
|
28
28
|
assert_equal ['pdf'] + Technoweenie::AttachmentFu.content_types, ImageOrPdfAttachment.attachment_options[:content_type]
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def test_should_sanitize_content_type
|
32
32
|
@attachment = Attachment.new :content_type => ' foo '
|
33
33
|
assert_equal 'foo', @attachment.content_type
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def test_should_sanitize_filenames
|
37
37
|
@attachment = Attachment.new :filename => 'blah/foo.bar'
|
38
38
|
assert_equal 'foo.bar', @attachment.filename
|
@@ -42,29 +42,79 @@ class BasicTest < Test::Unit::TestCase
|
|
42
42
|
|
43
43
|
@attachment.filename = 'f o!O-.bar'
|
44
44
|
assert_equal 'f_o_O-.bar', @attachment.filename
|
45
|
-
|
45
|
+
|
46
46
|
@attachment.filename = 'sheeps_says_bææ'
|
47
47
|
assert_equal 'sheeps_says_b__', @attachment.filename
|
48
48
|
|
49
49
|
@attachment.filename = nil
|
50
50
|
assert_nil @attachment.filename
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def test_should_convert_thumbnail_name
|
54
54
|
@attachment = FileAttachment.new :filename => 'foo.bar'
|
55
55
|
assert_equal 'foo.bar', @attachment.thumbnail_name_for(nil)
|
56
56
|
assert_equal 'foo.bar', @attachment.thumbnail_name_for('')
|
57
57
|
assert_equal 'foo_blah.bar', @attachment.thumbnail_name_for(:blah)
|
58
58
|
assert_equal 'foo_blah.blah.bar', @attachment.thumbnail_name_for('blah.blah')
|
59
|
-
|
59
|
+
|
60
60
|
@attachment.filename = 'foo.bar.baz'
|
61
61
|
assert_equal 'foo.bar_blah.baz', @attachment.thumbnail_name_for(:blah)
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def test_should_require_valid_thumbnails_option
|
65
65
|
klass = Class.new(ActiveRecord::Base)
|
66
66
|
assert_raise ArgumentError do
|
67
67
|
klass.has_attachment :thumbnails => []
|
68
68
|
end
|
69
69
|
end
|
70
|
+
|
71
|
+
class ::ImageWithPolymorphicThumbsAttachment
|
72
|
+
cattr_accessor :thumbnail_creations
|
73
|
+
|
74
|
+
def create_or_update_thumbnail(path, thumb, *size)
|
75
|
+
@@thumbnail_creations[thumb] = size.size == 1 ? size.first : size
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.reset_creations
|
79
|
+
@@thumbnail_creations = {}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_should_handle_polymorphic_thumbnails_option
|
84
|
+
assert_polymorphic_thumb_creation nil,
|
85
|
+
:thumb => [50, 50], :geometry => 'x50'
|
86
|
+
assert_polymorphic_thumb_creation 'Product',
|
87
|
+
:thumb => [50, 50], :geometry => 'x50', :large_thumb => '169x169!', :zoomed => '500x500>'
|
88
|
+
assert_polymorphic_thumb_creation 'Editorial',
|
89
|
+
:thumb => [50, 50], :geometry => 'x50', :fullsize => '150x100>'
|
90
|
+
assert_polymorphic_thumb_creation 'User',
|
91
|
+
:thumb => [50, 50], :geometry => 'x50', :avatar => '64x64!'
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_should_compute_per_thumbnail_jpeg_quality
|
95
|
+
assert_jpeg_quality :thumb, 90
|
96
|
+
assert_jpeg_quality :avatar, 85
|
97
|
+
assert_jpeg_quality :large, 75
|
98
|
+
assert_jpeg_quality :large, 0x200 | 75, false
|
99
|
+
assert_jpeg_quality nil, 75
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
def assert_jpeg_quality(thumbnail, quality, require_0_to_100 = true)
|
104
|
+
klass = ImageWithPerThumbJpegAttachment
|
105
|
+
w, h = if thumbnail
|
106
|
+
klass.attachment_options[:thumbnails][thumbnail].scan(/\d+/)
|
107
|
+
else
|
108
|
+
klass.attachment_options[:resize_to].scan(/\d+/)
|
109
|
+
end
|
110
|
+
attachment = klass.new(:thumbnail => thumbnail, :width => w, :height => h)
|
111
|
+
assert_equal quality, attachment.send(:get_jpeg_quality, require_0_to_100)
|
112
|
+
end
|
113
|
+
|
114
|
+
def assert_polymorphic_thumb_creation(parent, defs)
|
115
|
+
attachment_model ImageWithPolymorphicThumbsAttachment
|
116
|
+
attachment_model.reset_creations
|
117
|
+
attachment = upload_file :filename => '/files/rails.png', :imageable_type => parent.to_s.classify, :imageable_id => nil
|
118
|
+
assert_equal defs, attachment_model.thumbnail_creations
|
119
|
+
end
|
70
120
|
end
|
data/test/fixtures/attachment.rb
CHANGED
@@ -44,6 +44,23 @@ class ImageWithThumbsAttachment < Attachment
|
|
44
44
|
# end
|
45
45
|
end
|
46
46
|
|
47
|
+
class ImageWithPerThumbJpegAttachment < Attachment
|
48
|
+
has_attachment :resize_to => '500x500!',
|
49
|
+
:thumbnails => { :thumb => '50x50!', :large => '300x300!', :avatar => '64x64!' },
|
50
|
+
:jpeg_quality => { :thumb => 90, '<5000' => 85, '>=5000' => 75, :large => 0x200 | 75 }
|
51
|
+
end
|
52
|
+
|
53
|
+
class ImageWithPolymorphicThumbsAttachment < Attachment
|
54
|
+
belongs_to :imageable, :polymorphic => true
|
55
|
+
has_attachment :thumbnails => {
|
56
|
+
:thumb => [50, 50],
|
57
|
+
:geometry => 'x50',
|
58
|
+
:products => { :large_thumb => '169x169!', :zoomed => '500x500>' },
|
59
|
+
:editorials => { :fullsize => '150x100>' },
|
60
|
+
'User' => { :avatar => '64x64!' }
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
47
64
|
class FileAttachment < ActiveRecord::Base
|
48
65
|
has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
|
49
66
|
validates_as_attachment
|
@@ -133,6 +150,14 @@ begin
|
|
133
150
|
:processor => :image_science, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
|
134
151
|
:jpeg_quality => 75
|
135
152
|
end
|
153
|
+
|
154
|
+
class ImageScienceWithPerThumbJpegAttachment < ImageScienceAttachment
|
155
|
+
has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
|
156
|
+
:processor => :image_science,
|
157
|
+
:resize_to => '100x100',
|
158
|
+
:thumbnails => { :thumb => [50, 50], :editorial => '300x120', :avatar => '64x64!' },
|
159
|
+
:jpeg_quality => { :thumb => 90, '<5000' => 80, '>=5000' => 75 }
|
160
|
+
end
|
136
161
|
rescue MissingSourceFile
|
137
162
|
puts $!.message
|
138
163
|
puts "no ImageScience"
|
@@ -145,11 +170,18 @@ begin
|
|
145
170
|
end
|
146
171
|
|
147
172
|
class LowerQualityCoreImageAttachment < CoreImageAttachment
|
148
|
-
set_table_name 'core_image_attachments'
|
149
173
|
has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
|
150
174
|
:processor => :core_image, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
|
151
175
|
:jpeg_quality => 50
|
152
176
|
end
|
177
|
+
|
178
|
+
class CoreImageWithPerThumbJpegAttachment < CoreImageAttachment
|
179
|
+
has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
|
180
|
+
:processor => :core_image,
|
181
|
+
:resize_to => '100x100',
|
182
|
+
:thumbnails => { :thumb => [50, 50], :editorial => '300x120', :avatar => '64x64!' },
|
183
|
+
:jpeg_quality => { :thumb => 90, '<5000' => 80, '>=5000' => 75 }
|
184
|
+
end
|
153
185
|
rescue MissingSourceFile
|
154
186
|
puts $!.message
|
155
187
|
puts "no CoreImage"
|
@@ -160,7 +192,7 @@ begin
|
|
160
192
|
has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
|
161
193
|
:processor => :mini_magick, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
|
162
194
|
end
|
163
|
-
|
195
|
+
|
164
196
|
class ImageThumbnailCrop < MiniMagickAttachment
|
165
197
|
has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
|
166
198
|
:thumbnails => { :square => "50x50c", :vertical => "30x60c", :horizontal => "60x30c"}
|
@@ -194,13 +226,21 @@ begin
|
|
194
226
|
end
|
195
227
|
end
|
196
228
|
|
197
|
-
class LowerQualityMiniMagickAttachment <
|
229
|
+
class LowerQualityMiniMagickAttachment < ActiveRecord::Base
|
198
230
|
set_table_name 'mini_magick_attachments'
|
199
231
|
has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
|
200
232
|
:processor => :mini_magick, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
|
201
233
|
:jpeg_quality => 50
|
202
234
|
end
|
203
235
|
|
236
|
+
class MiniMagickWithPerThumbJpegAttachment < MiniMagickAttachment
|
237
|
+
has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
|
238
|
+
:processor => :mini_magick,
|
239
|
+
:resize_to => '100x100',
|
240
|
+
:thumbnails => { :thumb => [50, 50], :editorial => '300x120', :avatar => '64x64!' },
|
241
|
+
:jpeg_quality => { :thumb => 90, '<5000' => 80, '>=5000' => 75 }
|
242
|
+
end
|
243
|
+
|
204
244
|
rescue MissingSourceFile
|
205
245
|
puts $!.message
|
206
246
|
puts "no Mini Magick"
|
@@ -217,6 +257,14 @@ begin
|
|
217
257
|
:processor => :gd2, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
|
218
258
|
:jpeg_quality => 50
|
219
259
|
end
|
260
|
+
|
261
|
+
class GD2WithPerThumbJpegAttachment < GD2Attachment
|
262
|
+
has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
|
263
|
+
:processor => :gd2,
|
264
|
+
:resize_to => '100x100',
|
265
|
+
:thumbnails => { :thumb => [50, 50], :editorial => '300x120', :avatar => '64x64!' },
|
266
|
+
:jpeg_quality => { :thumb => 90, '<5000' => 80, '>=5000' => 75 }
|
267
|
+
end
|
220
268
|
rescue MissingSourceFile
|
221
269
|
puts $!.message
|
222
270
|
puts "no GD2"
|
@@ -35,12 +35,20 @@ class CoreImageTest < Test::Unit::TestCase
|
|
35
35
|
|
36
36
|
def test_should_handle_jpeg_quality
|
37
37
|
attachment_model CoreImageAttachment
|
38
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
38
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
39
39
|
full_size = attachment.size
|
40
40
|
attachment_model LowerQualityCoreImageAttachment
|
41
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
41
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
42
42
|
lq_size = attachment.size
|
43
43
|
assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
|
44
|
+
|
45
|
+
# FIXME: wait for Marcus' reply to determine whether I can get exact-quality output or need to adjust for CoreImage.
|
46
|
+
# attachment_model CoreImageWithPerThumbJpegAttachment
|
47
|
+
# attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
48
|
+
# assert_file_jpeg_quality attachment, :thumb, 90
|
49
|
+
# assert_file_jpeg_quality attachment, :avatar, 80
|
50
|
+
# assert_file_jpeg_quality attachment, :editorial, 75
|
51
|
+
# assert_file_jpeg_quality attachment, nil, 75
|
44
52
|
end
|
45
53
|
else
|
46
54
|
def test_flunk
|
data/test/processors/gd2_test.rb
CHANGED
@@ -29,12 +29,19 @@ class GD2Test < Test::Unit::TestCase
|
|
29
29
|
|
30
30
|
def test_should_handle_jpeg_quality
|
31
31
|
attachment_model GD2Attachment
|
32
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
32
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
33
33
|
full_size = attachment.size
|
34
34
|
attachment_model LowerQualityGD2Attachment
|
35
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
35
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
36
36
|
lq_size = attachment.size
|
37
37
|
assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
|
38
|
+
|
39
|
+
attachment_model GD2WithPerThumbJpegAttachment
|
40
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
41
|
+
assert_file_jpeg_quality attachment, :thumb, 90
|
42
|
+
assert_file_jpeg_quality attachment, :avatar, 80
|
43
|
+
assert_file_jpeg_quality attachment, :editorial, 75
|
44
|
+
assert_file_jpeg_quality attachment, nil, 75
|
38
45
|
end
|
39
46
|
else
|
40
47
|
def test_flunk
|
@@ -28,16 +28,23 @@ class ImageScienceTest < Test::Unit::TestCase
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def test_should_handle_jpeg_quality
|
31
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
31
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
32
32
|
full_size = attachment.size
|
33
33
|
attachment_model ImageScienceLowerQualityAttachment
|
34
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
34
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
35
35
|
lq_size = attachment.size
|
36
36
|
if ImageScience.instance_method(:save).arity == -2 # tdd-image_science: JPEG quality processing
|
37
37
|
assert lq_size <= full_size * 0.75, 'Lower-quality JPEG filesize should be congruently smaller'
|
38
38
|
else
|
39
39
|
assert_equal full_size, lq_size, 'Unsupported lower-quality JPEG should yield exact same file size'
|
40
40
|
end
|
41
|
+
|
42
|
+
attachment_model ImageScienceWithPerThumbJpegAttachment
|
43
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
44
|
+
assert_file_jpeg_quality attachment, :thumb, 90
|
45
|
+
assert_file_jpeg_quality attachment, :avatar, 80
|
46
|
+
assert_file_jpeg_quality attachment, :editorial, 75
|
47
|
+
assert_file_jpeg_quality attachment, nil, 75
|
41
48
|
end
|
42
49
|
else
|
43
50
|
def test_flunk
|
@@ -66,13 +66,19 @@ class MiniMagickTest < Test::Unit::TestCase
|
|
66
66
|
|
67
67
|
def test_should_handle_jpeg_quality
|
68
68
|
attachment_model MiniMagickAttachment
|
69
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
69
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
70
70
|
full_size = attachment.size
|
71
71
|
attachment_model LowerQualityMiniMagickAttachment
|
72
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
72
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
73
73
|
lq_size = attachment.size
|
74
|
-
puts "FULL: #{full_size} - LQ: #{lq_size}"
|
75
74
|
assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
|
75
|
+
|
76
|
+
attachment_model MiniMagickWithPerThumbJpegAttachment
|
77
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
78
|
+
assert_file_jpeg_quality attachment, :thumb, 90
|
79
|
+
assert_file_jpeg_quality attachment, :avatar, 80
|
80
|
+
assert_file_jpeg_quality attachment, :editorial, 75
|
81
|
+
assert_file_jpeg_quality attachment, nil, 75
|
76
82
|
end
|
77
83
|
else
|
78
84
|
def test_flunk
|
@@ -251,13 +251,19 @@ class RmagickTest < Test::Unit::TestCase
|
|
251
251
|
|
252
252
|
def test_should_handle_jpeg_quality
|
253
253
|
attachment_model ImageWithThumbsAttachment
|
254
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
254
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
255
255
|
full_size = attachment.size
|
256
256
|
attachment_model LowerQualityAttachment
|
257
|
-
attachment = upload_file :filename => '/files/rails.jpg'
|
257
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
258
258
|
lq_size = attachment.size
|
259
|
-
puts "FULL: #{full_size} - LQ: #{lq_size}"
|
260
259
|
assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
|
260
|
+
|
261
|
+
attachment_model ImageWithPerThumbJpegAttachment
|
262
|
+
attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
|
263
|
+
assert_file_jpeg_quality attachment, :thumb, 90
|
264
|
+
assert_file_jpeg_quality attachment, :avatar, 85
|
265
|
+
assert_file_jpeg_quality attachment, :large, 75
|
266
|
+
assert_file_jpeg_quality attachment, nil, 75
|
261
267
|
end
|
262
268
|
else
|
263
269
|
def test_flunk
|
data/test/schema.rb
CHANGED
@@ -2,6 +2,8 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
2
2
|
create_table :attachments, :force => true do |t|
|
3
3
|
t.column :db_file_id, :integer
|
4
4
|
t.column :parent_id, :integer
|
5
|
+
t.column :imageable_id, :integer
|
6
|
+
t.column :imageable_type, :string, :limit => 255
|
5
7
|
t.column :thumbnail, :string
|
6
8
|
t.column :filename, :string, :limit => 255
|
7
9
|
t.column :content_type, :string, :limit => 255
|
data/test/test_helper.rb
CHANGED
@@ -84,7 +84,9 @@ class Test::Unit::TestCase #:nodoc:
|
|
84
84
|
protected
|
85
85
|
def upload_file(options = {})
|
86
86
|
use_temp_file options[:filename] do |file|
|
87
|
-
|
87
|
+
opts = { :uploaded_data => fixture_file_upload(file, options[:content_type] || 'image/png') }
|
88
|
+
opts.update(options.reject { |k, v| ![:imageable_type, :imageable_id].include?(k) })
|
89
|
+
att = attachment_model.create opts
|
88
90
|
att.reload unless att.new_record?
|
89
91
|
return att
|
90
92
|
end
|
@@ -119,6 +121,27 @@ class Test::Unit::TestCase #:nodoc:
|
|
119
121
|
end
|
120
122
|
end
|
121
123
|
|
124
|
+
def assert_file_jpeg_quality(model, thumbnail, expected)
|
125
|
+
filename = if model.respond_to?(:full_filename)
|
126
|
+
model.full_filename(thumbnail)
|
127
|
+
else
|
128
|
+
thumb = thumbnail ? model.thumbnails.find(:first, :conditions => { :thumbnail => thumbnail.to_s }, :include => :db_file) : model
|
129
|
+
unless thumb && thumb.db_file && thumb.db_file.data && thumb.db_file.data.size > 0
|
130
|
+
STDERR.puts "Cannot find DB file data for thumbnail #{thumbnail.inspect} -> Aborting JPEG quality check."
|
131
|
+
return
|
132
|
+
end
|
133
|
+
result = Tempfile.new('dbfile_dump').path
|
134
|
+
File.open(result, 'wb') { |f| f.write(thumb.db_file.data) }
|
135
|
+
result
|
136
|
+
end
|
137
|
+
quality = %x(identify -format '%Q' "#{filename}" 2> /dev/null)
|
138
|
+
if $?.success?
|
139
|
+
assert_equal expected, quality.to_i, "Produced JPEG quality (thumbnail: #{thumbnail.inspect}) is incorrect."
|
140
|
+
else
|
141
|
+
STDERR.puts "ImageMagick's identify not found / not in PATH: can't quickly check produced image quality."
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
122
145
|
def assert_not_created
|
123
146
|
assert_created(0) { yield }
|
124
147
|
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tdd-attachment_fu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: true
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 9
|
8
|
+
- 9
|
9
|
+
- b
|
10
|
+
version: 0.9.9.b
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Rick Olson
|
@@ -10,7 +16,7 @@ autorequire:
|
|
10
16
|
bindir: bin
|
11
17
|
cert_chain: []
|
12
18
|
|
13
|
-
date:
|
19
|
+
date: 2010-03-15 00:00:00 +01:00
|
14
20
|
default_executable:
|
15
21
|
dependencies: []
|
16
22
|
|
@@ -73,7 +79,8 @@ files:
|
|
73
79
|
- vendor/red_artisan/core_image/filters/watermark.rb
|
74
80
|
has_rdoc: true
|
75
81
|
homepage: http://github.com/tdd/attachment_fu
|
76
|
-
licenses:
|
82
|
+
licenses: []
|
83
|
+
|
77
84
|
post_install_message:
|
78
85
|
rdoc_options:
|
79
86
|
- --inline-source
|
@@ -84,18 +91,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
91
|
requirements:
|
85
92
|
- - ">="
|
86
93
|
- !ruby/object:Gem::Version
|
94
|
+
segments:
|
95
|
+
- 0
|
87
96
|
version: "0"
|
88
|
-
version:
|
89
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
98
|
requirements:
|
91
99
|
- - ">="
|
92
100
|
- !ruby/object:Gem::Version
|
101
|
+
segments:
|
102
|
+
- 0
|
93
103
|
version: "0"
|
94
|
-
version:
|
95
104
|
requirements: []
|
96
105
|
|
97
|
-
rubyforge_project:
|
98
|
-
rubygems_version: 1.3.
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.3.6
|
99
108
|
signing_key:
|
100
109
|
specification_version: 2
|
101
110
|
summary: attachment_fu with more geometries, polymorphic-based settings and JPEG quality control.
|