Commit 02b68349d09c690e9796e9f739b3f706573a6036

Authored by Braulio Bhavamitra
1 parent e65ff0a5

rails4: rename attachment_fu folder to the name of the gem

Showing 110 changed files with 5062 additions and 5062 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 110 files displayed.

vendor/plugins/attachment_fu/CHANGELOG
... ... @@ -1,84 +0,0 @@
1   -* Aug 22, 2013 *
2   -* Added cache-control header option and Ruby 1.9 fix for S3 from tricycle
3   -
4   -* Aug 21, 2013 *
5   -* Added S3 :encrypted_storage option support from cschulte22
6   -
7   -* Jul 5, 2013
8   -* Pull in changes from lchimonji10 to reformat README to RDoc format
9   -
10   -* Apr 10, 2013 *
11   -* Ruby 2 compatibility fix
12   -* Removed some lingering occurrences of RAILS_ROOT and RAILS_ENV
13   -* clean up of gemspec file
14   -* no longer package unnecessary files like the test files
15   -
16   -* Mar 12, 2013 *
17   -* Pull in changes from https://github.com/aalong/attachment_fu to use Ruby 1.9.2 Tempfile naming strategy to fix conflicts with Sprockets (see https://github.com/aalong/attachment_fu/commit/938ec3b8597fbf82b1de8c98de12c4688463450a)
18   -
19   -* Feb 19, 2013 *
20   -* Pull in changes from https://github.com/itkin/attachment_fu fork to fix mini magick
21   -
22   -* Nov 15, 2012 *
23   -* Removed 'crop:' option as already included when prefixing geometry with a 'c'. Add note to docs.
24   -* Added option to sharpen resized images ':sharpen_on_resize'
25   -
26   -* Oct 26, 2012 *
27   -* Merged with https://github.com/tdd/attachment_fu fork to include GEM support for use in Rails 3.2, and bumped version to 3.2.x to indicate Rails 3.2 support.
28   -
29   -* Oct 25, 2012 *
30   -* Fix to support Ruby 1.9.3
31   -* Image cropping support (append 'crop:' to desired file size when resizing)
32   -
33   -* Mar 15, 2010 *
34   -* Added a symbol syntax for parent-type-based size spec: calls the corresponding method on the current asset instance to
35   - get a Hash of required thumbnails. Lets us dynamically specify what would otherwise be hard-coded, which is useful
36   - when the set of thumbnails for a given parent type varies depending on the usage context.
37   -
38   -* Aug 6, 2009 *
39   -* JPEG quality control finalized across processors (although CoreImage applies it in a rather fuzzy-logic way), with tests.
40   -
41   -* Aug 4, 2009 *
42   -* Supports the :aspect/'!' geometry flag in all processors
43   - (thanks to http://www.deepcalm.com/writing/cropped-thumbnails-in-attachment_fu-using-imagescience)
44   -* JPEG quality control on thumbnailing/resizing (still buggy on Rmagick/MiniMagick though).
45   -* Moves from GIF to PNG regardless of the source file extension's case (used to require lowercase)
46   -* Auto-orients image (if EXIF suggests it) prior to processing with RMagickProcessor
47   -* Fixes non-image upload tests (both regular files and Merb files)
48   -* Fixes obsolete failures on RMagick tests (aspect_ratio tested but not initialized anymore due to new callback architecture
49   -
50   -* Apr 17 2008 *
51   -* amazon_s3.yml is now passed through ERB before being passed to AWS::S3 [François Beausoleil]
52   -
53   -* Mar 22 2008 *
54   -* Some tweaks to support Rails 2.0 and Rails 2.1 due to ActiveSupport::Callback changes.
55   - Thanks to http://blog.methodmissing.com/2008/1/19/edge-callback-refactorings-attachment_fu/
56   -
57   -* Feb. 26, 2008 *
58   -* remove breakpoint from test_helper, makes test suite crazy (at least Rails 2+) [Rob Sanheim]
59   -* make S3 test really optional [Rob Sanheim]
60   -
61   -* Nov 27, 2007 *
62   -* Handle properly ImageScience thumbnails resized from a gif file [Matt Aimonetti]
63   -* Save thumbnails file size properly when using ImageScience [Matt Aimonetti]
64   -* fixed s3 config file loading with latest versions of Rails [Matt Aimonetti]
65   -
66   -* April 2, 2007 *
67   -
68   -* don't copy the #full_filename to the default #temp_paths array if it doesn't exist
69   -* add default ID partitioning for attachments
70   -* add #binmode call to Tempfile (note: ruby should be doing this!) [Eric Beland]
71   -* Check for current type of :thumbnails option.
72   -* allow customization of the S3 configuration file path with the :s3_config_path option.
73   -* Don't try to remove thumbnails if there aren't any. Closes #3 [ben stiglitz]
74   -
75   -* BC * (before changelog)
76   -
77   -* add default #temp_paths entry [mattly]
78   -* add MiniMagick support to attachment_fu [Isacc]
79   -* update #destroy_file to clear out any empty directories too [carlivar]
80   -* fix references to S3Backend module [Hunter Hillegas]
81   -* make #current_data public with db_file and s3 backends [ebryn]
82   -* oops, actually svn add the files for s3 backend. [Jeffrey Hardy]
83   -* experimental s3 support, egad, no tests.... [Jeffrey Hardy]
84   -* doh, fix a few bad references to ActsAsAttachment [sixty4bit]
vendor/plugins/attachment_fu/Gemfile
... ... @@ -1,13 +0,0 @@
1   -source 'http://rubygems.org'
2   -
3   -
4   -group :test, :development do
5   - gem 'rails', '~> 3.2'
6   - gem 'sqlite3'
7   - gem 'pothoven-attachment_fu', :path => '.'
8   - gem 'rmagick'
9   - gem 'core_image'
10   - gem 'mini_magick'
11   - gem 'aws-s3', :require => 'aws/s3'
12   - gem 'test-unit'
13   -end
vendor/plugins/attachment_fu/Gemfile.lock
... ... @@ -1,109 +0,0 @@
1   -PATH
2   - remote: .
3   - specs:
4   - pothoven-attachment_fu (3.2.10)
5   -
6   -GEM
7   - remote: http://rubygems.org/
8   - specs:
9   - actionmailer (3.2.14)
10   - actionpack (= 3.2.14)
11   - mail (~> 2.5.4)
12   - actionpack (3.2.14)
13   - activemodel (= 3.2.14)
14   - activesupport (= 3.2.14)
15   - builder (~> 3.0.0)
16   - erubis (~> 2.7.0)
17   - journey (~> 1.0.4)
18   - rack (~> 1.4.5)
19   - rack-cache (~> 1.2)
20   - rack-test (~> 0.6.1)
21   - sprockets (~> 2.2.1)
22   - activemodel (3.2.14)
23   - activesupport (= 3.2.14)
24   - builder (~> 3.0.0)
25   - activerecord (3.2.14)
26   - activemodel (= 3.2.14)
27   - activesupport (= 3.2.14)
28   - arel (~> 3.0.2)
29   - tzinfo (~> 0.3.29)
30   - activeresource (3.2.14)
31   - activemodel (= 3.2.14)
32   - activesupport (= 3.2.14)
33   - activesupport (3.2.14)
34   - i18n (~> 0.6, >= 0.6.4)
35   - multi_json (~> 1.0)
36   - arel (3.0.2)
37   - aws-s3 (0.6.3)
38   - builder
39   - mime-types
40   - xml-simple
41   - builder (3.0.4)
42   - core_image (0.0.3.5)
43   - erubis (2.7.0)
44   - hike (1.2.3)
45   - i18n (0.6.5)
46   - journey (1.0.4)
47   - json (1.8.0)
48   - mail (2.5.4)
49   - mime-types (~> 1.16)
50   - treetop (~> 1.4.8)
51   - mime-types (1.24)
52   - mini_magick (3.6.0)
53   - subexec (~> 0.2.1)
54   - multi_json (1.7.9)
55   - polyglot (0.3.3)
56   - rack (1.4.5)
57   - rack-cache (1.2)
58   - rack (>= 0.4)
59   - rack-ssl (1.3.3)
60   - rack
61   - rack-test (0.6.2)
62   - rack (>= 1.0)
63   - rails (3.2.14)
64   - actionmailer (= 3.2.14)
65   - actionpack (= 3.2.14)
66   - activerecord (= 3.2.14)
67   - activeresource (= 3.2.14)
68   - activesupport (= 3.2.14)
69   - bundler (~> 1.0)
70   - railties (= 3.2.14)
71   - railties (3.2.14)
72   - actionpack (= 3.2.14)
73   - activesupport (= 3.2.14)
74   - rack-ssl (~> 1.3.2)
75   - rake (>= 0.8.7)
76   - rdoc (~> 3.4)
77   - thor (>= 0.14.6, < 2.0)
78   - rake (10.1.0)
79   - rdoc (3.12.2)
80   - json (~> 1.4)
81   - rmagick (2.13.2)
82   - sprockets (2.2.2)
83   - hike (~> 1.2)
84   - multi_json (~> 1.0)
85   - rack (~> 1.0)
86   - tilt (~> 1.1, != 1.3.0)
87   - sqlite3 (1.3.8)
88   - subexec (0.2.3)
89   - test-unit (2.5.5)
90   - thor (0.18.1)
91   - tilt (1.4.1)
92   - treetop (1.4.15)
93   - polyglot
94   - polyglot (>= 0.3.1)
95   - tzinfo (0.3.37)
96   - xml-simple (1.1.2)
97   -
98   -PLATFORMS
99   - ruby
100   -
101   -DEPENDENCIES
102   - aws-s3
103   - core_image
104   - mini_magick
105   - pothoven-attachment_fu!
106   - rails (~> 3.2)
107   - rmagick
108   - sqlite3
109   - test-unit
vendor/plugins/attachment_fu/LICENSE
... ... @@ -1,20 +0,0 @@
1   -Copyright (c) 2009 rick olson
2   -
3   -Permission is hereby granted, free of charge, to any person obtaining
4   -a copy of this software and associated documentation files (the
5   -"Software"), to deal in the Software without restriction, including
6   -without limitation the rights to use, copy, modify, merge, publish,
7   -distribute, sublicense, and/or sell copies of the Software, and to
8   -permit persons to whom the Software is furnished to do so, subject to
9   -the following conditions:
10   -
11   -The above copyright notice and this permission notice shall be
12   -included in all copies or substantial portions of the Software.
13   -
14   -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15   -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16   -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17   -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18   -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19   -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20   -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
vendor/plugins/attachment_fu/README
... ... @@ -1,193 +0,0 @@
1   -attachment-fu
2   -=============
3   -
4   -attachment_fu is a plugin by Rick Olson (aka technoweenie <http://techno-weenie.net>) and is the successor to acts_as_attachment. To get a basic run-through of its capabilities, check out Mike Clark's tutorial <http://clarkware.com/cgi/blosxom/2007/02/24#FileUploadFu>.
5   -
6   -
7   -attachment_fu functionality
8   -===========================
9   -
10   -attachment_fu facilitates file uploads in Ruby on Rails. There are a few storage options for the actual file data, but the plugin always at a minimum stores metadata for each file in the database.
11   -
12   -There are four storage options for files uploaded through attachment_fu:
13   - File system
14   - Database file
15   - Amazon S3
16   - Rackspace (Mosso) Cloud Files
17   -
18   -Each method of storage many options associated with it that will be covered in the following section. Something to note, however, is that the Amazon S3 storage requires you to modify config/amazon_s3.yml, the Rackspace Cloud Files storage requires you to modify config/rackspace_cloudfiles.yml, and the Database file storage requires an extra table.
19   -
20   -
21   -attachment_fu models
22   -====================
23   -
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   -
26   -In the model there are two methods made available by this plugins: has_attachment and validates_as_attachment.
27   -
28   -has_attachment(options = {})
29   - This method accepts the options in a hash:
30   - :content_type # Allowed content types.
31   - # Allows all by default. Use :image to allow all standard image types.
32   - :min_size # Minimum size allowed.
33   - # 1 byte is the default.
34   - :max_size # Maximum size allowed.
35   - # 1.megabyte is the default.
36   - :size # Range of sizes allowed.
37   - # (1..1.megabyte) is the default. This overrides the :min_size and :max_size options.
38   - :resize_to # Used by RMagick to resize images.
39   - # Pass either an array of width/height, or a geometry string.
40   - :thumbnails # Specifies a set of thumbnails to generate.
41   - # This accepts a hash of filename suffixes and RMagick resizing options.
42   - # This option need only be included if you want thumbnailing.
43   - :thumbnail_class # Set which model class to use for thumbnails.
44   - # This current attachment class is used by default.
45   - :path_prefix # Path to store the uploaded files in.
46   - # Uses public/#{table_name} by default for the filesystem, and just #{table_name} for the S3 and Cloud Files backend.
47   - # Setting this sets the :storage to :file_system.
48   - :partition # Whether to partiton files in directories like /0000/0001/image.jpg. Default is true. Only applicable to the :file_system backend.
49   - :storage # Specifies the storage system to use..
50   - # Defaults to :db_file. Options are :file_system, :db_file, :s3, and :cloud_files.
51   - :cloudfront # If using S3 for storage, this option allows for serving the files via Amazon CloudFront.
52   - # Defaults to false.
53   - :processor # Sets the image processor to use for resizing of the attached image.
54   - # Options include ImageScience, Rmagick, and MiniMagick. Default is whatever is installed.
55   - :uuid_primary_key # If your model's primary key is a 128-bit UUID in hexadecimal format, then set this to true.
56   - :association_options # attachment_fu automatically defines associations with thumbnails with has_many and belongs_to. If there are any additional options that you want to pass to these methods, then specify them here.
57   -
58   -
59   - Examples:
60   - has_attachment :max_size => 1.kilobyte
61   - has_attachment :size => 1.megabyte..2.megabytes
62   - has_attachment :content_type => 'application/pdf'
63   - has_attachment :content_type => ['application/pdf', 'application/msword', 'text/plain']
64   - has_attachment :content_type => :image, :resize_to => [50,50]
65   - has_attachment :content_type => ['application/pdf', :image], :resize_to => 'x50'
66   - has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
67   - has_attachment :storage => :file_system, :path_prefix => 'public/files'
68   - has_attachment :storage => :file_system, :path_prefix => 'public/files',
69   - :content_type => :image, :resize_to => [50,50], :partition => false
70   - has_attachment :storage => :file_system, :path_prefix => 'public/files',
71   - :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
72   - has_attachment :storage => :s3
73   - has_attachment :store => :s3, :cloudfront => true
74   - has_attachment :storage => :cloud_files
75   -
76   -validates_as_attachment
77   - 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.
78   -
79   - Example:
80   - validates_as_attachment
81   -
82   -
83   -attachment_fu migrations
84   -========================
85   -
86   -Fields for attachment_fu metadata tables...
87   - in general:
88   - size, :integer # file size in bytes
89   - content_type, :string # mime type, ex: application/mp3
90   - filename, :string # sanitized filename
91   - that reference images:
92   - height, :integer # in pixels
93   - width, :integer # in pixels
94   - that reference images that will be thumbnailed:
95   - parent_id, :integer # id of parent image (on the same table, a self-referencing foreign-key).
96   - # Only populated if the current object is a thumbnail.
97   - thumbnail, :string # the 'type' of thumbnail this attachment record describes.
98   - # Only populated if the current object is a thumbnail.
99   - # Usage:
100   - # [ In Model 'Avatar' ]
101   - # has_attachment :content_type => :image,
102   - # :storage => :file_system,
103   - # :max_size => 500.kilobytes,
104   - # :resize_to => '320x200>',
105   - # :thumbnails => { :small => '10x10>',
106   - # :thumb => '100x100>' }
107   - # [ Elsewhere ]
108   - # @user.avatar.thumbnails.first.thumbnail #=> 'small'
109   - that reference files stored in the database (:db_file):
110   - db_file_id, :integer # id of the file in the database (foreign key)
111   -
112   -Field for attachment_fu db_files table:
113   - data, :binary # binary file data, for use in database file storage
114   -
115   -
116   -attachment_fu views
117   -===================
118   -
119   -There are two main views tasks that will be directly affected by attachment_fu: upload forms and displaying uploaded images.
120   -
121   -There are two parts of the upload form that differ from typical usage.
122   - 1. Include ':multipart => true' in the html options of the form_for tag.
123   - Example:
124   - <% form_for(:attachment_metadata, :url => { :action => "create" }, :html => { :multipart => true }) do |form| %>
125   -
126   - 2. Use the file_field helper with :uploaded_data as the field name.
127   - Example:
128   - <%= form.file_field :uploaded_data %>
129   -
130   -Displaying uploaded images is made easy by the public_filename method of the ActiveRecord attachment objects using file system, s3, and Cloud Files storage.
131   -
132   -public_filename(thumbnail = nil)
133   - Returns the public path to the file. If a thumbnail prefix is specified it will return the public file path to the corresponding thumbnail.
134   - Examples:
135   - attachment_obj.public_filename #=> /attachments/2/file.jpg
136   - attachment_obj.public_filename(:thumb) #=> /attachments/2/file_thumb.jpg
137   - attachment_obj.public_filename(:small) #=> /attachments/2/file_small.jpg
138   -
139   -When serving files from database storage, doing more than simply downloading the file is beyond the scope of this document.
140   -
141   -
142   -attachment_fu controllers
143   -=========================
144   -
145   -There are two considerations to take into account when using attachment_fu in controllers.
146   -
147   -The first is when the files have no publicly accessible path and need to be downloaded through an action.
148   -
149   -Example:
150   - def readme
151   - send_file '/path/to/readme.txt', :type => 'plain/text', :disposition => 'inline'
152   - end
153   -
154   -See the possible values for send_file for reference.
155   -
156   -
157   -The second is when saving the file when submitted from a form.
158   -Example in view:
159   - <%= form.file_field :attachable, :uploaded_data %>
160   -
161   -Example in controller:
162   - def create
163   - @attachable_file = AttachmentMetadataModel.new(params[:attachable])
164   - if @attachable_file.save
165   - flash[:notice] = 'Attachment was successfully created.'
166   - redirect_to attachable_url(@attachable_file)
167   - else
168   - render :action => :new
169   - end
170   - end
171   -
172   -attachement_fu scripting
173   -====================================
174   -
175   -You may wish to import a large number of images or attachments.
176   -The following example shows how to upload a file from a script.
177   -
178   -#!/usr/bin/env ./script/runner
179   -
180   -# required to use ActionController::TestUploadedFile
181   -require 'action_controller'
182   -require 'action_controller/test_process.rb'
183   -
184   -path = "./public/images/x.jpg"
185   -
186   -# mimetype is a string like "image/jpeg". One way to get the mimetype for a given file on a UNIX system
187   -# mimetype = `file -ib #{path}`.gsub(/\n/,"")
188   -
189   -mimetype = "image/jpeg"
190   -
191   -# This will "upload" the file at path and create the new model.
192   -@attachable = AttachmentMetadataModel.new(:uploaded_data => ActionController::TestUploadedFile.new(path, mimetype))
193   -@attachable.save
vendor/plugins/attachment_fu/README.rdoc
... ... @@ -1,352 +0,0 @@
1   -= attachment-fu
2   -
3   -attachment_fu is a plugin by Rick Olson (aka technoweenie
4   -http://techno-weenie.net) and is the successor to acts_as_attachment. To get a
5   -basic run-through of its capabilities, check out {Mike Clark's
6   -tutorial}[http://clarkware.com/cgi/blosxom/2007/02/24#FileUploadFu].
7   -
8   -= attachment_fu functionality
9   -
10   -attachment_fu facilitates file uploads in Ruby on Rails. There are a few
11   -storage options for the actual file data, but the plugin always at a minimum
12   -stores metadata for each file in the database.
13   -
14   -There are four storage options for files uploaded through attachment_fu:
15   -
16   -* File system
17   -* Database file
18   -* Amazon S3
19   -* Rackspace (Mosso) Cloud Files
20   -
21   -Each method of storage many options associated with it that will be covered in
22   -the following section. Something to note, however, is that the Amazon S3 storage
23   -requires you to modify +config/amazon_s3.yml+, the Rackspace Cloud Files storage
24   -requires you to modify +config/rackspace_cloudfiles.yml+, and the Database file
25   -storage requires an extra table.
26   -
27   -= attachment_fu models
28   -
29   -For all three of these storage options a table of metadata is required. This
30   -table will contain information about the file (hence the 'meta') and its
31   -location. This table has no restrictions on naming, unlike the extra table
32   -required for database storage, which must have a table name of +db_files+ (and
33   -by convention a model of +DbFile+).
34   -
35   -Two methods are available to models: +has_attachment+ and
36   -+validates_as_attachment+.
37   -
38   -== has_attachment(options = {})
39   -
40   -This method accepts the options in a hash:
41   -
42   -[:content_type]
43   - Allowed content types.
44   -
45   - By default, all content types are allowed. Use +:image+ to allow all
46   - standard image types.
47   -
48   -[:min_size]
49   - Minimum file size.
50   -
51   - By default, set to +1.byte+.
52   -
53   -[:max_size]
54   - Maximum file size.
55   -
56   - By default, set to +1.megabyte+.
57   -
58   -[:size]
59   - Minimum and maximum file size.
60   -
61   - By default, set to +1..1.megabyte+. Overrides +:min_size+ and
62   - +:max_size+.
63   -
64   -[:resize_to]
65   - Used by RMagick.
66   -
67   - Tells RMagick how to resize images. Pass either an array specifying
68   - width and height or a geometry string. Prefixing the geometry string
69   - with a 'c' will crop the image to the specified size.
70   -
71   -[:sharpen_on_resize]
72   - Used by RMagick.
73   -
74   - If set to true, images are sharpened after being resized.
75   -
76   -[:thumbnails]
77   - A set of thumbnails to generate.
78   -
79   - This accepts a hash of filename suffixes and RMagick resizing options. This
80   - option need only be included if you want thumbnailing.
81   -
82   - If you have a polymorphic parent relationship, you can provide
83   - parent-type-specific thumbnail settings by using a pair with the type string
84   - as key and a Hash of thumbnail definitions, or a method symbol, as value.
85   - The method symbol will call the named method in order to get a
86   - dynamically-built Hash of thumbnail definitions, which gives you full
87   - flexibility. AttachmentFu automatically detects your first polymorphic
88   - +belongs_to+ relationship.
89   -
90   -[:thumbnail_class]
91   - Which model class to use for thumbnails.
92   -
93   - By default, the current attachment class is used.
94   -
95   -[:jpeg_quality]
96   - JPEG quality settings for thumbnail resizes.
97   -
98   - Arguments can be in multiple formats:
99   -
100   - * Integer from 0 (basically crap) to 100 (basically lossless, fat files).
101   -
102   - * When relying on tdd-image_science, you can also use one of its +JPEG_xxx+
103   - constants for predefined ratios/settings.
104   -
105   - * You can also use a Hash, with keys being either thumbnail symbols (I
106   - repeat: _symbols_) or surface boundaries. A surface boundary is a string
107   - starting with either '<' or '>=', followed by a number of pixels. This
108   - lets you specify per-thumbnail or per-general-thumbnail-"size" JPEG
109   - qualities. (which can be useful when you have a _lot_ of thumbnail
110   - options). Surface example: <code>{'<2000' => 90, '>=2000' => 75}</code>.
111   -
112   - Defaults vary depending on the processor (ImageScience: 100%,
113   - Rmagick/MiniMagick/Gd2: 75%, CoreImage: auto-adjust). Note that only
114   - tdd-image_science (available from GitHub) currently supports explicit JPEG
115   - quality; the default image_science currently forces 100%.
116   -
117   -[:path_prefix]
118   - Path to store the uploaded files in. Uses <code>public/#{table_name}</code>
119   - by default for the filesystem, and just <code>#{table_name}</code> for the
120   - S3 and Cloud Files backend. Setting this sets the +:storage+ to
121   - +:file_system+.
122   -
123   -[:partition]
124   - Whether to partiton files in directories like +/0000/0001/image.jpg+.
125   - Default is true. Only applicable to the +:file_system+ backend.
126   -
127   -[:storage]
128   - Specifies the storage system to use. Defaults to +:db_file+. Options are
129   - +:file_system+, +:db_file+, +:s3+, and +:cloud_files+.
130   -
131   -[:cloudfront]
132   - If using S3 for storage, this option allows for serving the files via Amazon
133   - CloudFront. Defaults to false.
134   -
135   -[:processor]
136   - Sets the image processor to use for resizing of the attached image. Options
137   - include ImageScience, Rmagick, MiniMagick, Gd2 and CoreImage. Default is
138   - whatever is installed.
139   -
140   -[:uuid_primary_key]
141   - If your model's primary key is a 128-bit UUID in hexadecimal format, then
142   - set this to true.
143   -
144   -[:association_options]
145   - attachment_fu automatically defines associations with thumbnails with
146   - +has_many+ and +belongs_to+. If there are any additional options that you
147   - want to pass to these methods, then specify them here.
148   -
149   -Examples:
150   -
151   - has_attachment(content_type: 'application/pdf')
152   - has_attachment(
153   - content_type: ['application/pdf', 'application/msword', 'text/plain']
154   - )
155   - has_attachment(content_type: ['application/pdf', :image], resize_to: 'x50')
156   - has_attachment(content_type: :image, resize_to: [50,50])
157   - has_attachment(max_size: 1.kilobyte)
158   - has_attachment(size: 1.megabyte..2.megabytes)
159   - has_attachment(storage: :cloud_files)
160   - has_attachment(storage: :file_system, path_prefix: 'public/files')
161   - has_attachment(
162   - storage: :file_system,
163   - path_prefix: 'public/files',
164   - content_type: :image,
165   - resize_to: [50, 50],
166   - partition: false
167   - )
168   - has_attachment(
169   - storage: :file_system,
170   - path_prefix: 'public/files',
171   - thumbnails: {thumb: [50, 50], geometry: 'x50'}
172   - )
173   - has_attachment(storage: :s3)
174   - has_attachment(store: :s3, cloudfront: true)
175   - has_attachment(thumbnails: {thumb: [50, 50], geometry: 'x50'})
176   -
177   - # Let's say we have a polymorphic belongs_to, e.g. called 'imageable', where
178   - # imageable_type (or whatever the :foreign_type option was set to) can be,
179   - # among other things, 'Product', 'User' or 'Editorial', each of which should
180   - # have extra thumbnails:
181   -
182   - has_attachment(thumbnails: {
183   - editorials: {fullsize: '150x100>'},
184   - geometry: 'x50',
185   - products: {large_thumb: '169x169!', zoomed: '500x500>'},
186   - thumb: [50, 50],
187   - users: {avatar: '64x64!'}
188   - })
189   -
190   - # JPEG qualities…
191   -
192   - has_attachment(jpeg_quality: 75)
193   - has_attachment(jpeg_quality: 80 | ImageScience::JPEG_PROGRESSIVE)
194   - has_attachment(
195   - thumbnails: {thumb: [50, 50], geometry: 'x50'},
196   - jpeg_quality: {'<2000' => 90, '>=2000' => 75}
197   - )
198   - has_attachment(
199   - thumbnails: {thumb: [50, 50], geometry: 'x50'},
200   - jpeg_quality: {nil => 75, thumb: 90, geometry: 90}
201   - )
202   -
203   -== validates_as_attachment
204   -
205   -This method prevents files outside of the valid range (+:min_size+ to
206   -+:max_size+, or the +:size+ range) from being saved. It does not however, halt
207   -the upload of such files. They will be uploaded into memory regardless of size
208   -before validation.
209   -
210   -To perform this validation, simply add +validates_as_attachment+ to your model.
211   -
212   -= attachment_fu migrations
213   -
214   -Fields for attachment_fu metadata tables…
215   -
216   -In general:
217   -
218   - size, :integer # file size in bytes
219   - content_type, :string # mime type, ex: application/mp3
220   - filename, :string # sanitized filename
221   -
222   -That reference images:
223   -
224   - height, :integer # in pixels
225   - width, :integer # in pixels
226   -
227   -That reference images that will be thumbnailed:
228   -
229   - parent_id, :integer # id of parent image (on the same table, a
230   - # self-referencing foreign-key). Only populated if
231   - # the current object is a thumbnail.
232   - thumbnail, :string # The type of thumbnail this attachment record
233   - # describes. Only populated if the current object is
234   - # a thumbnail. Example:
235   - #
236   - # (In Model 'Avatar')
237   - # has_attachment(
238   - # :content_type => :image,
239   - # :storage => :file_system,
240   - # :max_size => 500.kilobytes,
241   - # :resize_to => '320x200>',
242   - # :thumbnails => {
243   - # :small => '10x10>',
244   - # :thumb => '100x100>'
245   - # }
246   - # )
247   - #
248   - # (Elsewhere)
249   - # @user.avatar.thumbnails.first.thumbnail # => 'small'
250   - #
251   - db_file_id, :integer # ID of the file in the database (foreign key) that
252   - # reference files stored in the database (:db_file).
253   -
254   -Field for attachment_fu +db_files+ table:
255   -
256   - data, :binary # binary file data, for use in database file storage
257   -
258   -= attachment_fu views
259   -
260   -There are two main views tasks that will be directly affected by attachment_fu:
261   -upload forms and displaying uploaded images.
262   -
263   -There are two parts of the upload form that differ from typical usage.
264   -
265   -1. Include <code>multipart: true</code> in the html options of the +form_for+
266   - tag. Example:
267   -
268   - <%=
269   - form_for(
270   - :attachment_metadata,
271   - url: {action: "create"},
272   - html: {multipart: true}
273   - ) do |form|
274   - %>
275   -
276   -2. Use the +file_field+ helper with +:uploaded_data+ as the field name. Example:
277   -
278   - <%= form.file_field(:uploaded_data) %>
279   -
280   -Displaying uploaded images is made easy by the +public_filename+ method of the
281   -ActiveRecord attachment objects using file system, s3, and Cloud Files storage.
282   -
283   -== public_filename(thumbnail = nil)
284   -
285   -Returns the public path to the file. If a thumbnail prefix is specified it will
286   -return the public file path to the corresponding thumbnail. Examples:
287   -
288   - attachment_obj.public_filename #=> /attachments/2/file.jpg
289   - attachment_obj.public_filename(:thumb) #=> /attachments/2/file_thumb.jpg
290   - attachment_obj.public_filename(:small) #=> /attachments/2/file_small.jpg
291   -
292   -When serving files from database storage, doing more than simply downloading the
293   -file is beyond the scope of this document.
294   -
295   -= attachment_fu controllers
296   -
297   -There are two considerations to take into account when using attachment_fu in
298   -controllers.
299   -
300   -The first is when the files have no publicly accessible path and need to be
301   -downloaded through an action. Example:
302   -
303   - def readme
304   - send_file(
305   - '/path/to/readme.txt',
306   - type: 'plain/text',
307   - disposition: 'inline'
308   - )
309   - end
310   -
311   -See the possible values for +send_file+ for reference.
312   -
313   -The second is when saving the file when submitted from a form. Example:
314   -
315   -In a view:
316   -
317   - <%= form.file_field(:attachable, :uploaded_data) %>
318   -
319   -In a controller:
320   -
321   - def create
322   - @attachable_file = AttachmentMetadataModel.new(params[:attachable])
323   - if @attachable_file.save
324   - flash[:notice] = 'Attachment was successfully created.'
325   - redirect_to(attachable_url(@attachable_file))
326   - else
327   - redirect_to(action: 'new')
328   - end
329   - end
330   -
331   -= attachment_fu scripting
332   -
333   -You may wish to import a large number of images or attachments. The following
334   -example shows how to upload a file from a script.
335   -
336   - #!/usr/bin/env ./script/runner
337   -
338   - # required to use ActionController::TestUploadedFile
339   - require 'action_controller'
340   - require 'action_controller/test_process.rb'
341   -
342   - path = "./public/images/x.jpg"
343   -
344   - # `mimetype` is a string like "image/jpeg". One way to get the mimetype for
345   - # a given file on a UNIX system: mimetype = `file -ib #{path}`.gsub(/\n/,"")
346   - mimetype = "image/jpeg"
347   -
348   - # This will "upload" the file at path and create the new model.
349   - @attachable = AttachmentMetadataModel.new(
350   - uploaded_data: ActionController::TestUploadedFile.new(path, mimetype)
351   - )
352   - @attachable.save
vendor/plugins/attachment_fu/Rakefile
... ... @@ -1,22 +0,0 @@
1   -require 'rake'
2   -require 'rake/testtask'
3   -require 'rdoc/task'
4   -
5   -desc 'Default: run unit tests.'
6   -task :default => :test
7   -
8   -desc 'Test the attachment_fu plugin.'
9   -Rake::TestTask.new(:test) do |t|
10   - t.libs << 'lib'
11   - t.pattern = 'test/**/*_test.rb'
12   - t.verbose = true
13   -end
14   -
15   -desc 'Generate documentation for the attachment_fu plugin.'
16   -Rake::RDocTask.new(:rdoc) do |rdoc|
17   - rdoc.rdoc_dir = 'rdoc'
18   - rdoc.title = 'ActsAsAttachment'
19   - rdoc.options << '--line-numbers --inline-source'
20   - rdoc.rdoc_files.include('README.rdoc')
21   - rdoc.rdoc_files.include('lib/**/*.rb')
22   -end
vendor/plugins/attachment_fu/amazon_s3.yml.tpl
... ... @@ -1,17 +0,0 @@
1   -development:
2   - bucket_name: appname_development
3   - access_key_id:
4   - secret_access_key:
5   - distribution_domain: XXXX.cloudfront.net
6   -
7   -test:
8   - bucket_name: appname_test
9   - access_key_id:
10   - secret_access_key:
11   - distribution_domain: XXXX.cloudfront.net
12   -
13   -production:
14   - bucket_name: appname
15   - access_key_id:
16   - secret_access_key:
17   - distribution_domain: XXXX.cloudfront.net
vendor/plugins/attachment_fu/attachment_fu.gemspec
... ... @@ -1,23 +0,0 @@
1   -# -*- encoding: utf-8 -*-
2   -
3   -Gem::Specification.new do |s|
4   - s.name = %q{pothoven-attachment_fu}
5   - s.authors = ["Rick Olson", "Steven Pothoven"]
6   - s.summary = %q{attachment_fu as a gem}
7   - s.description = %q{This is a fork of Rick Olson's attachment_fu adding Ruby 1.9 and Rails 3.2 support as well as some other enhancements.}
8   - s.email = %q{steven@pothoven.net}
9   - s.homepage = %q{http://github.com/pothoven/attachment_fu}
10   - s.version = "3.2.10"
11   - s.date = %q{2013-08-22}
12   -
13   - s.files = Dir.glob("{lib,vendor}/**/*") + %w( CHANGELOG LICENSE README.rdoc amazon_s3.yml.tpl rackspace_cloudfiles.yml.tpl )
14   - s.extra_rdoc_files = ["README.rdoc"]
15   - s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
16   - s.require_paths = ["lib"]
17   - s.rubyforge_project = "nowarning"
18   - s.rubygems_version = %q{1.3.5}
19   -
20   - if s.respond_to? :specification_version then
21   - s.specification_version = 2
22   - end
23   -end
vendor/plugins/attachment_fu/config/database.yml
... ... @@ -1,3 +0,0 @@
1   -test:
2   - adapter: sqlite3
3   - database: ":memory:"
vendor/plugins/attachment_fu/config/environment.rb
vendor/plugins/attachment_fu/init.rb
... ... @@ -1,6 +0,0 @@
1   -require 'geometry'
2   -ActiveRecord::Base.send(:extend, Technoweenie::AttachmentFu::ActMethods)
3   -Technoweenie::AttachmentFu.tempfile_path = ATTACHMENT_FU_TEMPFILE_PATH if Object.const_defined?(:ATTACHMENT_FU_TEMPFILE_PATH)
4   -FileUtils.mkdir_p Technoweenie::AttachmentFu.tempfile_path
5   -
6   -$:.unshift(File.dirname(__FILE__) + '/vendor')
vendor/plugins/attachment_fu/install.rb
... ... @@ -1,7 +0,0 @@
1   -require 'fileutils'
2   -
3   -s3_config = File.dirname(__FILE__) + '/../../../config/amazon_s3.yml'
4   -FileUtils.cp File.dirname(__FILE__) + '/amazon_s3.yml.tpl', s3_config unless File.exist?(s3_config)
5   -cloudfiles_config = File.dirname(__FILE__) + '/../../../config/rackspace_cloudfiles.yml'
6   -FileUtils.cp File.dirname(__FILE__) + '/rackspace_cloudfiles.yml.tpl', cloudfiles_config unless File.exist?(cloudfiles_config)
7   -puts IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
vendor/plugins/attachment_fu/lib/geometry.rb
... ... @@ -1,96 +0,0 @@
1   -# This Geometry class was yanked from RMagick. However, it lets ImageMagick handle the actual change_geometry.
2   -# Use #new_dimensions_for to get new dimensions
3   -# Used so I can use spiffy RMagick geometry strings with ImageScience
4   -class Geometry
5   - # @ is removed until support for them is added
6   - FLAGS = ['', '%', '<', '>', '!']#, '@']
7   - RFLAGS = { '%' => :percent,
8   - '!' => :aspect,
9   - '<' => :>,
10   - '>' => :<,
11   - '@' => :area }
12   -
13   - attr_accessor :width, :height, :x, :y, :flag
14   -
15   - def initialize(width=nil, height=nil, x=nil, y=nil, flag=nil)
16   - # Support floating-point width and height arguments so Geometry
17   - # objects can be used to specify Image#density= arguments.
18   - raise ArgumentError, "width must be >= 0: #{width}" if width < 0
19   - raise ArgumentError, "height must be >= 0: #{height}" if height < 0
20   - @width = width.to_f
21   - @height = height.to_f
22   - @x = x.to_i
23   - @y = y.to_i
24   - @flag = flag
25   - end
26   -
27   - # Construct an object from a geometry string
28   - RE = /\A(\d*)(?:x(\d+)?)?([-+]\d+)?([-+]\d+)?([%!<>@]?)\Z/
29   -
30   - def self.from_s(str)
31   - raise(ArgumentError, "no geometry string specified") unless str
32   -
33   - if m = RE.match(str)
34   - new(m[1].to_i, m[2].to_i, m[3].to_i, m[4].to_i, RFLAGS[m[5]])
35   - else
36   - raise ArgumentError, "invalid geometry format"
37   - end
38   - end
39   -
40   - # Convert object to a geometry string
41   - def to_s
42   - str = ''
43   - str << "%g" % @width if @width > 0
44   - str << 'x' if (@width > 0 || @height > 0)
45   - str << "%g" % @height if @height > 0
46   - str << "%+d%+d" % [@x, @y] if (@x != 0 || @y != 0)
47   - str << FLAGS[@flag.to_i]
48   - end
49   -
50   - # attempts to get new dimensions for the current geometry string given these old dimensions.
51   - # This doesn't implement the aspect flag (!) or the area flag (@). PDI
52   - def new_dimensions_for(orig_width, orig_height)
53   - new_width = orig_width
54   - new_height = orig_height
55   -
56   - case @flag
57   - when :percent
58   - scale_x = @width.zero? ? 100 : @width
59   - scale_y = @height.zero? ? @width : @height
60   - new_width = scale_x.to_f * (orig_width.to_f / 100.0)
61   - new_height = scale_y.to_f * (orig_height.to_f / 100.0)
62   - when :aspect
63   - new_width = @width unless @width.nil?
64   - new_height = @height unless @height.nil?
65   - when :<, :>, nil
66   - scale_factor =
67   - if new_width.zero? || new_height.zero?
68   - 1.0
69   - else
70   - if @width.nonzero? && @height.nonzero?
71   - [@width.to_f / new_width.to_f, @height.to_f / new_height.to_f].min
72   - else
73   - @width.nonzero? ? (@width.to_f / new_width.to_f) : (@height.to_f / new_height.to_f)
74   - end
75   - end
76   - new_width = scale_factor * new_width.to_f
77   - new_height = scale_factor * new_height.to_f
78   - new_width = orig_width if @flag && orig_width.send(@flag, new_width)
79   - new_height = orig_height if @flag && orig_height.send(@flag, new_height)
80   - end
81   -
82   - [new_width, new_height].collect! { |v| [v.round, 1].max }
83   - end
84   -end
85   -
86   -class Array
87   - # allows you to get new dimensions for the current array of dimensions with a given geometry string
88   - #
89   - # [50, 64] / '40>' # => [40, 51]
90   - def /(geometry)
91   - raise ArgumentError, "Only works with a [width, height] pair" if size != 2
92   - raise ArgumentError, "Must pass a valid geometry string or object" unless geometry.is_a?(String) || geometry.is_a?(Geometry)
93   - geometry = Geometry.from_s(geometry) if geometry.is_a?(String)
94   - geometry.new_dimensions_for first, last
95   - end
96   -end
vendor/plugins/attachment_fu/lib/pothoven-attachment_fu.rb
... ... @@ -1,12 +0,0 @@
1   -class Engine < Rails::Engine
2   - # Mimic old vendored plugin behavior, attachment_fu/lib is autoloaded.
3   - config.autoload_paths << File.expand_path("..", __FILE__)
4   -
5   - initializer "attachment_fu" do
6   - require 'geometry'
7   -
8   - ActiveRecord::Base.send(:extend, Technoweenie::AttachmentFu::ActMethods)
9   - Technoweenie::AttachmentFu.tempfile_path = ATTACHMENT_FU_TEMPFILE_PATH if Object.const_defined?(:ATTACHMENT_FU_TEMPFILE_PATH)
10   - FileUtils.mkdir_p Technoweenie::AttachmentFu.tempfile_path
11   - end
12   -end
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb
... ... @@ -1,588 +0,0 @@
1   -module Technoweenie # :nodoc:
2   - module AttachmentFu # :nodoc:
3   - @@default_processors = %w(ImageScience Rmagick MiniMagick Gd2 CoreImage)
4   - @@tempfile_path = File.join(Rails.root, 'tmp', 'attachment_fu')
5   - @@content_types = [
6   - 'image/jpeg',
7   - 'image/pjpeg',
8   - 'image/jpg',
9   - 'image/gif',
10   - 'image/png',
11   - 'image/x-png',
12   - 'image/jpg',
13   - 'image/x-ms-bmp',
14   - 'image/bmp',
15   - 'image/x-bmp',
16   - 'image/x-bitmap',
17   - 'image/x-xbitmap',
18   - 'image/x-win-bitmap',
19   - 'image/x-windows-bmp',
20   - 'image/ms-bmp',
21   - 'application/bmp',
22   - 'application/x-bmp',
23   - 'application/x-win-bitmap',
24   - 'application/preview',
25   - 'image/jp_',
26   - 'application/jpg',
27   - 'application/x-jpg',
28   - 'image/pipeg',
29   - 'image/vnd.swiftview-jpeg',
30   - 'image/x-xbitmap',
31   - 'application/png',
32   - 'application/x-png',
33   - 'image/gi_',
34   - 'image/x-citrix-pjpeg'
35   - ]
36   - mattr_reader :content_types, :tempfile_path, :default_processors
37   - mattr_writer :tempfile_path
38   -
39   - class ThumbnailError < StandardError; end
40   - class AttachmentError < StandardError; end
41   -
42   - module ActMethods
43   - # Options:
44   - # * <tt>:content_type</tt> - Allowed content types. Allows all by default. Use :image to allow all standard image types.
45   - # * <tt>:min_size</tt> - Minimum size allowed. 1 byte is the default.
46   - # * <tt>:max_size</tt> - Maximum size allowed. 1.megabyte is the default.
47   - # * <tt>:size</tt> - Range of sizes allowed. (1..1.megabyte) is the default. This overrides the :min_size and :max_size options.
48   - # * <tt>:resize_to</tt> - Used by RMagick to resize images. Pass either an array of width/height, or a geometry string. Prefix geometry string with 'c' to crop image, ex. 'c100x100'
49   - # * <tt>:sharpen_on_resize</tt> - When using RMagick, setting to true will sharpen images after resizing.
50   - # * <tt>:jpeg_quality</tt> - Used to provide explicit JPEG quality for thumbnail/resize saves. Can have multiple formats:
51   - # * Integer from 0 (basically crap) to 100 (basically lossless, fat files).
52   - # * When relying on ImageScience, you can also use one of its +JPEG_xxx+ constants for predefined ratios/settings.
53   - # * You can also use a Hash, with keys being either thumbnail symbols (I repeat: _symbols_) or surface boundaries.
54   - # A surface boundary is a string starting with either '<' or '>=', followed by a number of pixels. This lets you
55   - # specify per-thumbnail or per-general-thumbnail-"size" JPEG qualities. (which can be useful when you have a
56   - # _lot_ of thumbnail options). Surface example: +{ '<2000' => 90, '>=2000' => 75 }+.
57   - # Defaults vary depending on the processor (ImageScience: 100%, Rmagick/MiniMagick/Gd2: 75%,
58   - # CoreImage: auto-adjust). Note that only tdd-image_science (available from GitHub) currently supports explicit JPEG quality;
59   - # the default image_science currently forces 100%.
60   - # * <tt>:thumbnails</tt> - Specifies a set of thumbnails to generate. This accepts a hash of filename suffixes and
61   - # RMagick resizing options. If you have a polymorphic parent relationship, you can provide parent-type-specific
62   - # thumbnail settings by using a pair with the type string as key and a Hash of thumbnail definitions as value.
63   - # AttachmentFu automatically detects your first polymorphic +belongs_to+ relationship.
64   - # * <tt>:thumbnail_class</tt> - Set what class to use for thumbnails. This attachment class is used by default.
65   - # * <tt>:path_prefix</tt> - path to store the uploaded files. Uses public/#{table_name} by default for the filesystem, and just #{table_name}
66   - # for the S3 backend. Setting this sets the :storage to :file_system.
67   -
68   - # * <tt>:storage</tt> - Use :file_system to specify the attachment data is stored with the file system. Defaults to :db_system.
69   - # * <tt>:cloundfront</tt> - Set to true if you are using S3 storage and want to serve the files through CloudFront. You will need to
70   - # set a distribution domain in the amazon_s3.yml config file. Defaults to false
71   - # * <tt>:bucket_key</tt> - Use this to specify a different bucket key other than :bucket_name in the amazon_s3.yml file. This allows you to use
72   - # different buckets for different models. An example setting would be :image_bucket and the you would need to define the name of the corresponding
73   - # bucket in the amazon_s3.yml file.
74   -
75   - # * <tt>:keep_profile</tt> By default image EXIF data will be stripped to minimize image size. For small thumbnails this proivides important savings. Picture quality is not affected. Set to false if you want to keep the image profile as is. ImageScience will allways keep EXIF data.
76   - #
77   - # Examples:
78   - # has_attachment :max_size => 1.kilobyte
79   - # has_attachment :size => 1.megabyte..2.megabytes
80   - # has_attachment :content_type => 'application/pdf'
81   - # has_attachment :content_type => ['application/pdf', 'application/msword', 'text/plain']
82   - # has_attachment :content_type => :image, :resize_to => [50,50]
83   - # has_attachment :content_type => ['application/pdf', :image], :resize_to => 'x50'
84   - # has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
85   - # has_attachment :storage => :file_system, :path_prefix => 'public/files'
86   - # has_attachment :storage => :file_system, :path_prefix => 'public/files',
87   - # :content_type => :image, :resize_to => [50,50]
88   - # has_attachment :storage => :file_system, :path_prefix => 'public/files',
89   - # :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
90   - # has_attachment :storage => :s3
91   - def has_attachment(options = {})
92   - # this allows you to redefine the acts' options for each subclass, however
93   - options[:min_size] ||= 1
94   - options[:max_size] ||= 1.megabyte
95   - options[:size] ||= (options[:min_size]..options[:max_size])
96   - options[:thumbnails] ||= {}
97   - options[:thumbnail_class] ||= self
98   - options[:s3_access] ||= :public_read
99   - options[:cloudfront] ||= false
100   - options[:content_type] = [options[:content_type]].flatten.collect! { |t| t == :image ? ::Technoweenie::AttachmentFu.content_types : t }.flatten unless options[:content_type].nil?
101   - options[:cache_control] ||= "max-age=315360000" # 10 years
102   -
103   - unless options[:thumbnails].is_a?(Hash)
104   - raise ArgumentError, ":thumbnails option should be a hash: e.g. :thumbnails => { :foo => '50x50' }"
105   - end
106   -
107   - extend ClassMethods unless (class << self; included_modules; end).include?(ClassMethods)
108   - include InstanceMethods unless included_modules.include?(InstanceMethods)
109   -
110   - parent_options = attachment_options || {}
111   - # doing these shenanigans so that #attachment_options is available to processors and backends
112   - self.attachment_options = options
113   -
114   - attr_accessor :thumbnail_resize_options
115   -
116   - attachment_options[:storage] ||= (attachment_options[:file_system_path] || attachment_options[:path_prefix]) ? :file_system : :db_file
117   - attachment_options[:storage] ||= parent_options[:storage]
118   - attachment_options[:path_prefix] ||= attachment_options[:file_system_path]
119   - if attachment_options[:path_prefix].nil?
120   - attachment_options[:path_prefix] = case attachment_options[:storage]
121   - when :s3 then table_name
122   - when :cloud_files then table_name
123   - else File.join("public", table_name)
124   - end
125   - end
126   - attachment_options[:path_prefix] = attachment_options[:path_prefix][1..-1] if options[:path_prefix].first == '/'
127   -
128   - association_options = { :foreign_key => 'parent_id' }
129   - if attachment_options[:association_options]
130   - association_options.merge!(attachment_options[:association_options])
131   - end
132   - with_options(association_options) do |m|
133   - m.has_many :thumbnails, :class_name => "::#{attachment_options[:thumbnail_class]}"
134   - m.belongs_to :parent, :class_name => "::#{base_class}" unless options[:thumbnails].empty?
135   - end
136   -
137   - storage_mod = ::Technoweenie::AttachmentFu::Backends.const_get("#{options[:storage].to_s.classify}Backend")
138   - include storage_mod unless included_modules.include?(storage_mod)
139   -
140   - case attachment_options[:processor]
141   - when :none, nil
142   - processors = ::Technoweenie::AttachmentFu.default_processors.dup
143   - begin
144   - if processors.any?
145   - attachment_options[:processor] = processors.first
146   - processor_mod = ::Technoweenie::AttachmentFu::Processors.const_get("#{attachment_options[:processor].to_s.classify}Processor")
147   - include processor_mod unless included_modules.include?(processor_mod)
148   - end
149   - rescue Object, Exception
150   - raise unless load_related_exception?($!)
151   -
152   - processors.shift
153   - retry
154   - end
155   - else
156   - begin
157   - processor_mod = ::Technoweenie::AttachmentFu::Processors.const_get("#{attachment_options[:processor].to_s.classify}Processor")
158   - include processor_mod unless included_modules.include?(processor_mod)
159   - rescue Object, Exception
160   - raise unless load_related_exception?($!)
161   -
162   - puts "Problems loading #{options[:processor]}Processor: #{$!}"
163   - end
164   - end unless parent_options[:processor] # Don't let child override processor
165   - end
166   -
167   - def load_related_exception?(e) #:nodoc: implementation specific
168   - case
169   - when e.kind_of?(LoadError), e.kind_of?(MissingSourceFile), $!.class.name == "CompilationError"
170   - # We can't rescue CompilationError directly, as it is part of the RubyInline library.
171   - # We must instead rescue RuntimeError, and check the class' name.
172   - true
173   - else
174   - false
175   - end
176   - end
177   - private :load_related_exception?
178   - end
179   -
180   - module ClassMethods
181   - delegate :content_types, :to => ::Technoweenie::AttachmentFu
182   -
183   - # Performs common validations for attachment models.
184   - def validates_as_attachment
185   - validates_presence_of :size, :content_type, :filename
186   - validate :attachment_attributes_valid?
187   - end
188   -
189   - # Returns true or false if the given content type is recognized as an image.
190   - def image?(content_type)
191   - content_types.include?(content_type)
192   - end
193   -
194   - def self.extended(base)
195   - base.class_attribute :attachment_options
196   - base.before_destroy :destroy_thumbnails
197   - base.before_validation :set_size_from_temp_path
198   - base.after_destroy :destroy_file
199   - base.after_validation :process_attachment
200   - base.after_save :after_process_attachment
201   - #if defined?(::ActiveSupport::Callbacks)
202   - # base.define_callbacks :after_resize, :after_attachment_saved, :before_thumbnail_saved
203   - #end
204   - end
205   -
206   - unless defined?(::ActiveSupport::Callbacks)
207   - # Callback after an image has been resized.
208   - #
209   - # class Foo < ActiveRecord::Base
210   - # acts_as_attachment
211   - # after_resize do |record, img|
212   - # record.aspect_ratio = img.columns.to_f / img.rows.to_f
213   - # end
214   - # end
215   - def after_resize(&block)
216   - write_inheritable_array(:after_resize, [block])
217   - end
218   -
219   - # Callback after an attachment has been saved either to the file system or the DB.
220   - # Only called if the file has been changed, not necessarily if the record is updated.
221   - #
222   - # class Foo < ActiveRecord::Base
223   - # acts_as_attachment
224   - # after_attachment_saved do |record|
225   - # ...
226   - # end
227   - # end
228   - def after_attachment_saved(&block)
229   - write_inheritable_array(:after_attachment_saved, [block])
230   - end
231   -
232   - # Callback before a thumbnail is saved. Use this to pass any necessary extra attributes that may be required.
233   - #
234   - # class Foo < ActiveRecord::Base
235   - # acts_as_attachment
236   - # before_thumbnail_saved do |thumbnail|
237   - # record = thumbnail.parent
238   - # ...
239   - # end
240   - # end
241   - def before_thumbnail_saved(&block)
242   - write_inheritable_array(:before_thumbnail_saved, [block])
243   - end
244   - end
245   -
246   - # Get the thumbnail class, which is the current attachment class by default.
247   - # Configure this with the :thumbnail_class option.
248   - def thumbnail_class
249   - attachment_options[:thumbnail_class] = attachment_options[:thumbnail_class].constantize unless attachment_options[:thumbnail_class].is_a?(Class)
250   - attachment_options[:thumbnail_class]
251   - end
252   -
253   - # Copies the given file path to a new tempfile, returning the closed tempfile.
254   - def copy_to_temp_file(file, temp_base_name)
255   - Tempfile.new(temp_base_name, ::Technoweenie::AttachmentFu.tempfile_path).tap do |tmp|
256   - tmp.close
257   - FileUtils.cp file, tmp.path
258   - end
259   - end
260   -
261   - # Writes the given data to a new tempfile, returning the closed tempfile.
262   - def write_to_temp_file(data, temp_base_name)
263   - Tempfile.new(temp_base_name, ::Technoweenie::AttachmentFu.tempfile_path).tap do |tmp|
264   - tmp.binmode
265   - tmp.write data
266   - tmp.close
267   - end
268   - end
269   -
270   - def polymorphic_relation_type_column
271   - return @@_polymorphic_relation_type_column if defined?(@@_polymorphic_relation_type_column)
272   - # Checked against ActiveRecord 1.15.6 through Edge @ 2009-08-05.
273   - ref = reflections.values.detect { |r| r.macro == :belongs_to && r.options[:polymorphic] }
274   - @@_polymorphic_relation_type_column = ref && ref.options[:foreign_type]
275   - end
276   - end
277   -
278   - module InstanceMethods
279   - def self.included(base)
280   - base.define_callbacks *[:after_resize, :after_attachment_saved, :before_thumbnail_saved] if base.respond_to?(:define_callbacks)
281   - end
282   -
283   - # Checks whether the attachment's content type is an image content type
284   - def image?
285   - self.class.image?(content_type)
286   - end
287   -
288   - # Returns true/false if an attachment is thumbnailable. A thumbnailable attachment has an image content type and the parent_id attribute.
289   - def thumbnailable?
290   - image? && respond_to?(:parent_id) && parent_id.nil?
291   - end
292   -
293   - # Returns the class used to create new thumbnails for this attachment.
294   - def thumbnail_class
295   - self.class.thumbnail_class
296   - end
297   -
298   - # Gets the thumbnail name for a filename. 'foo.jpg' becomes 'foo_thumbnail.jpg'
299   - def thumbnail_name_for(thumbnail = nil)
300   - if thumbnail.blank?
301   - if filename.nil?
302   - return ''
303   - else
304   - return filename
305   - end
306   - end
307   -
308   - ext = nil
309   - basename = filename.gsub /\.\w+$/ do |s|
310   - ext = s; ''
311   - end
312   - # ImageScience doesn't create gif thumbnails, only pngs
313   - ext.sub!(/gif$/i, 'png') if attachment_options[:processor] == "ImageScience"
314   - "#{basename}_#{thumbnail}#{ext}"
315   - end
316   -
317   - # Creates or updates the thumbnail for the current attachment.
318   - def create_or_update_thumbnail(temp_file, file_name_suffix, *size)
319   - thumbnailable? || raise(ThumbnailError.new("Can't create a thumbnail if the content type is not an image or there is no parent_id column"))
320   - find_or_initialize_thumbnail(file_name_suffix).tap do |thumb|
321   - thumb.temp_paths.unshift temp_file
322   - thumb.send(:assign_attributes, {
323   - :content_type => content_type,
324   - :filename => thumbnail_name_for(file_name_suffix),
325   - :thumbnail_resize_options => size
326   - }, :without_protection => true)
327   - callback_with_args :before_thumbnail_saved, thumb
328   - thumb.save!
329   - end
330   - end
331   -
332   - # Sets the content type.
333   - def content_type=(new_type)
334   - write_attribute :content_type, new_type.to_s.strip
335   - end
336   -
337   - # Sanitizes a filename.
338   - def filename=(new_name)
339   - write_attribute :filename, sanitize_filename(new_name)
340   - end
341   -
342   - # Returns the width/height in a suitable format for the image_tag helper: (100x100)
343   - def image_size
344   - [width.to_s, height.to_s] * 'x'
345   - end
346   -
347   - # Returns true if the attachment data will be written to the storage system on the next save
348   - def save_attachment?
349   - File.file?(temp_path.class == String ? temp_path : temp_path.to_filename)
350   - end
351   -
352   - # nil placeholder in case this field is used in a form.
353   - def uploaded_data() nil; end
354   -
355   - # This method handles the uploaded file object. If you set the field name to uploaded_data, you don't need
356   - # any special code in your controller.
357   - #
358   - # <% form_for :attachment, :html => { :multipart => true } do |f| -%>
359   - # <p><%= f.file_field :uploaded_data %></p>
360   - # <p><%= submit_tag :Save %>
361   - # <% end -%>
362   - #
363   - # @attachment = Attachment.create! params[:attachment]
364   - #
365   - # TODO: Allow it to work with Merb tempfiles too.
366   - def uploaded_data=(file_data)
367   - if file_data.respond_to?(:content_type)
368   - return nil if file_data.size == 0
369   - self.content_type = file_data.content_type
370   - self.filename = file_data.original_filename if respond_to?(:filename)
371   - else
372   - return nil if file_data.blank? || file_data['size'] == 0
373   - self.content_type = file_data['content_type']
374   - self.filename = file_data['filename']
375   - file_data = file_data['tempfile']
376   - end
377   - if file_data.is_a?(StringIO)
378   - file_data.rewind
379   - set_temp_data file_data.read
380   - else
381   - file_data.respond_to?(:tempfile) ? self.temp_paths.unshift( file_data.tempfile.path ) : self.temp_paths.unshift( file_data.path )
382   - end
383   - end
384   -
385   - # Gets the latest temp path from the collection of temp paths. While working with an attachment,
386   - # multiple Tempfile objects may be created for various processing purposes (resizing, for example).
387   - # An array of all the tempfile objects is stored so that the Tempfile instance is held on to until
388   - # it's not needed anymore. The collection is cleared after saving the attachment.
389   - def temp_path
390   - p = temp_paths.first
391   - p.respond_to?(:path) ? p.path : p.to_s
392   - end
393   -
394   - # Gets an array of the currently used temp paths. Defaults to a copy of #full_filename.
395   - def temp_paths
396   - @temp_paths ||= (new_record? || !respond_to?(:full_filename) || !File.exist?(full_filename) ?
397   - [] : [copy_to_temp_file(full_filename)])
398   - end
399   -
400   - # Gets the data from the latest temp file. This will read the file into memory.
401   - def temp_data
402   - save_attachment? ? File.read(temp_path) : nil
403   - end
404   -
405   - # Writes the given data to a Tempfile and adds it to the collection of temp files.
406   - def set_temp_data(data)
407   - temp_paths.unshift write_to_temp_file data unless data.nil?
408   - end
409   -
410   - # Copies the given file to a randomly named Tempfile.
411   - def copy_to_temp_file(file)
412   - self.class.copy_to_temp_file file, random_tempfile_filename
413   - end
414   -
415   - # Writes the given file to a randomly named Tempfile.
416   - def write_to_temp_file(data)
417   - self.class.write_to_temp_file data, random_tempfile_filename
418   - end
419   -
420   - # Stub for creating a temp file from the attachment data. This should be defined in the backend module.
421   - def create_temp_file() end
422   -
423   - # Allows you to work with a processed representation (RMagick, ImageScience, etc) of the attachment in a block.
424   - #
425   - # @attachment.with_image do |img|
426   - # self.data = img.thumbnail(100, 100).to_blob
427   - # end
428   - #
429   - def with_image(&block)
430   - self.class.with_image(temp_path, &block)
431   - end
432   -
433   - protected
434   - # Generates a unique filename for a Tempfile.
435   - def random_tempfile_filename
436   - base_filename = filename ? filename.gsub(/\.\w+$/, '') : 'attachment'
437   - ext = filename.slice(/\.\w+$/)
438   - ["#{rand Time.now.to_i}#{base_filename}", ext || '']
439   - end
440   -
441   - def sanitize_filename(filename)
442   - return unless filename
443   - filename.strip.tap do |name|
444   - # NOTE: File.basename doesn't work right with Windows paths on Unix
445   - # get only the filename, not the whole path
446   - name.gsub! /^.*(\\|\/)/, ''
447   -
448   - # Finally, replace all non alphanumeric, underscore or periods with underscore
449   - name.gsub! /[^A-Za-z0-9\.\-]/, '_'
450   - end
451   - end
452   -
453   - # before_validation callback.
454   - def set_size_from_temp_path
455   - self.size = File.size(temp_path) if save_attachment?
456   - end
457   -
458   - # validates the size and content_type attributes according to the current model's options
459   - def attachment_attributes_valid?
460   - [:size, :content_type].each do |attr_name|
461   - enum = attachment_options[attr_name]
462   - if Object.const_defined?(:I18n) # Rails >= 2.2
463   - errors.add attr_name, I18n.translate("activerecord.errors.messages.inclusion", attr_name => enum) unless enum.nil? || enum.include?(send(attr_name))
464   - else
465   - errors.add attr_name, ActiveRecord::Errors.default_error_messages[:inclusion] unless enum.nil? || enum.include?(send(attr_name))
466   - end
467   - end
468   - end
469   -
470   - # Initializes a new thumbnail with the given suffix.
471   - def find_or_initialize_thumbnail(file_name_suffix)
472   - respond_to?(:parent_id) ?
473   - thumbnail_class.find_or_initialize_by_thumbnail_and_parent_id(file_name_suffix.to_s, id) :
474   - thumbnail_class.find_or_initialize_by_thumbnail(file_name_suffix.to_s)
475   - end
476   -
477   - # Stub for a #process_attachment method in a processor
478   - def process_attachment
479   - @saved_attachment = save_attachment?
480   - end
481   -
482   - # Cleans up after processing. Thumbnails are created, the attachment is stored to the backend, and the temp_paths are cleared.
483   - def after_process_attachment
484   - if @saved_attachment
485   - if respond_to?(:process_attachment_with_processing, true) && thumbnailable? && !attachment_options[:thumbnails].blank? && parent_id.nil?
486   - temp_file = temp_path || create_temp_file
487   - attachment_options[:thumbnails].each { |suffix, size|
488   - if size.is_a?(Symbol)
489   - parent_type = polymorphic_parent_type
490   - next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s) && respond_to?(size)
491   - size = send(size)
492   - end
493   - if size.is_a?(Hash)
494   - parent_type = polymorphic_parent_type
495   - next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s)
496   - size.each { |ppt_suffix, ppt_size|
497   - create_or_update_thumbnail(temp_file, ppt_suffix, *ppt_size)
498   - }
499   - else
500   - create_or_update_thumbnail(temp_file, suffix, *size)
501   - end
502   - }
503   - end
504   - save_to_storage
505   - @temp_paths.clear
506   - @saved_attachment = nil
507   - #callback :after_attachment_saved
508   - callback_with_args :after_attachment_saved, nil
509   - end
510   - end
511   -
512   - # Resizes the given processed img object with either the attachment resize options or the thumbnail resize options.
513   - def resize_image_or_thumbnail!(img)
514   - if (!respond_to?(:parent_id) || parent_id.nil?) && attachment_options[:resize_to] # parent image
515   - resize_image(img, attachment_options[:resize_to])
516   - elsif thumbnail_resize_options # thumbnail
517   - resize_image(img, thumbnail_resize_options)
518   - end
519   - end
520   -
521   - if defined?(Rails) && Rails::VERSION::MAJOR >= 3
522   - def callback_with_args(method, arg = self)
523   - if respond_to?(method)
524   - send(method, arg)
525   - end
526   - end
527   - # Yanked from ActiveRecord::Callbacks, modified so I can pass args to the callbacks besides self.
528   - # Only accept blocks, however
529   - elsif ActiveSupport.const_defined?(:Callbacks)
530   - # Rails 2.1 and beyond!
531   - def callback_with_args(method, arg = self)
532   - notify(method)
533   -
534   - result = run_callbacks(method, { :object => arg }) { |result, object| result == false }
535   -
536   - if result != false && respond_to_without_attributes?(method)
537   - result = send(method)
538   - end
539   -
540   - result
541   - end
542   -
543   - def run_callbacks(kind, options = {}, &block)
544   - options.reverse_merge!( :object => self )
545   - self.class.send("#{kind}_callback_chain").run(options[:object], options, &block)
546   - end
547   - else
548   - # Rails 2.0
549   - def callback_with_args(method, arg = self)
550   - notify(method)
551   -
552   - result = nil
553   - callbacks_for(method).each do |callback|
554   - result = callback.call(self, arg)
555   - return false if result == false
556   - end
557   - result
558   - end
559   - end
560   -
561   - # Removes the thumbnails for the attachment, if it has any
562   - def destroy_thumbnails
563   - self.thumbnails.each { |thumbnail| thumbnail.destroy } if thumbnailable?
564   - end
565   -
566   - def polymorphic_parent_type
567   - rel_name = self.class.polymorphic_relation_type_column
568   - rel_name && send(rel_name)
569   - end
570   -
571   - def get_jpeg_quality(require_0_to_100 = true)
572   - quality = attachment_options[:jpeg_quality]
573   - if quality.is_a?(Hash)
574   - sbl_quality = thumbnail && quality[thumbnail.to_sym]
575   - sbl_quality = nil if sbl_quality && require_0_to_100 && !sbl_quality.to_i.between?(0, 100)
576   - surface = (width || 1) * (height || 1)
577   - size_quality = quality.detect { |k, v|
578   - next unless k.is_a?(String) && k =~ /^(<|>=)(\d+)$/
579   - op, threshold = $1, $2.to_i
580   - surface.send(op, threshold)
581   - }
582   - quality = sbl_quality || size_quality && size_quality[1]
583   - end
584   - return quality && (!require_0_to_100 || quality.to_i.between?(0, 100)) ? quality : nil
585   - end
586   - end
587   - end
588   -end
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/cloud_file_backend.rb
... ... @@ -1,211 +0,0 @@
1   -module Technoweenie # :nodoc:
2   - module AttachmentFu # :nodoc:
3   - module Backends
4   - # = CloudFiles Storage Backend
5   - #
6   - # Enables use of {Rackspace Cloud Files}[http://www.mosso.com/cloudfiles.jsp] as a storage mechanism
7   - #
8   - # Based heavily on the Amazon S3 backend.
9   - #
10   - # == Requirements
11   - #
12   - # Requires the {Cloud Files Gem}[http://www.mosso.com/cloudfiles.jsp] by Rackspace
13   - #
14   - # == Configuration
15   - #
16   - # Configuration is done via <tt>Rails.root.to_s/config/rackspace_cloudfiles.yml</tt> and is loaded according to the <tt>#{Rails.env}</tt>.
17   - # The minimum connection options that you must specify are a container name, your Mosso login name and your Mosso API key.
18   - # You can sign up for Cloud Files and get access keys by visiting https://www.mosso.com/buy.htm
19   - #
20   - # Example configuration (Rails.root.to_s/config/rackspace_cloudfiles.yml)
21   - #
22   - # development:
23   - # container_name: appname_development
24   - # username: <your key>
25   - # api_key: <your key>
26   - #
27   - # test:
28   - # container_name: appname_test
29   - # username: <your key>
30   - # api_key: <your key>
31   - #
32   - # production:
33   - # container_name: appname
34   - # username: <your key>
35   - # apik_key: <your key>
36   - #
37   - # You can change the location of the config path by passing a full path to the :cloudfiles_config_path option.
38   - #
39   - # has_attachment :storage => :cloud_files, :cloudfiles_config_path => (Rails.root.to_s + '/config/mosso.yml')
40   - #
41   - # === Required configuration parameters
42   - #
43   - # * <tt>:username</tt> - The username for your Rackspace Cloud (Mosso) account. Provided by Rackspace.
44   - # * <tt>:secret_access_key</tt> - The api key for your Rackspace Cloud account. Provided by Rackspace.
45   - # * <tt>:container_name</tt> - The name of a container in your Cloud Files account.
46   - #
47   - # If any of these required arguments is missing, a AuthenticationException will be raised from CloudFiles::Connection.
48   - #
49   - # == Usage
50   - #
51   - # To specify Cloud Files as the storage mechanism for a model, set the acts_as_attachment <tt>:storage</tt> option to <tt>:cloud_files/tt>.
52   - #
53   - # class Photo < ActiveRecord::Base
54   - # has_attachment :storage => :cloud_files
55   - # end
56   - #
57   - # === Customizing the path
58   - #
59   - # By default, files are prefixed using a pseudo hierarchy in the form of <tt>:table_name/:id</tt>, which results
60   - # in Cloud Files object names (and urls) that look like: http://:server/:container_name/:table_name/:id/:filename with :table_name
61   - # representing the customizable portion of the path. You can customize this prefix using the <tt>:path_prefix</tt>
62   - # option:
63   - #
64   - # class Photo < ActiveRecord::Base
65   - # has_attachment :storage => :cloud_files, :path_prefix => 'my/custom/path'
66   - # end
67   - #
68   - # Which would result in public URLs like <tt>http(s)://:server/:container_name/my/custom/path/:id/:filename.</tt>
69   - #
70   - # === Permissions
71   - #
72   - # File permisisons are determined by the permissions of the container. At present, the options are public (and distributed
73   - # by the Limelight CDN), and private (only available to your login)
74   - #
75   - # === Other options
76   - #
77   - # Of course, all the usual configuration options apply, such as content_type and thumbnails:
78   - #
79   - # class Photo < ActiveRecord::Base
80   - # has_attachment :storage => :cloud_files, :content_type => ['application/pdf', :image], :resize_to => 'x50'
81   - # has_attachment :storage => :cloud_files, :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
82   - # end
83   - #
84   - # === Accessing Cloud Files URLs
85   - #
86   - # You can get an object's public URL using the cloudfiles_url accessor. For example, assuming that for your postcard app
87   - # you had a container name like 'postcard_world_development', and an attachment model called Photo:
88   - #
89   - # @postcard.cloudfiles_url # => http://cdn.cloudfiles.mosso.com/c45182/uploaded_files/20/london.jpg
90   - #
91   - # The resulting url is in the form: http://:server/:container_name/:table_name/:id/:file.
92   - # The optional thumbnail argument will output the thumbnail's filename (if any).
93   - #
94   - # Additionally, you can get an object's base path relative to the container root using
95   - # <tt>base_path</tt>:
96   - #
97   - # @photo.file_base_path # => uploaded_files/20
98   - #
99   - # And the full path (including the filename) using <tt>full_filename</tt>:
100   - #
101   - # @photo.full_filename # => uploaded_files/20/london.jpg
102   - #
103   - # Niether <tt>base_path</tt> or <tt>full_filename</tt> include the container name as part of the path.
104   - # You can retrieve the container name using the <tt>container_name</tt> method.
105   - module CloudFileBackend
106   - class RequiredLibraryNotFoundError < StandardError; end
107   - class ConfigFileNotFoundError < StandardError; end
108   -
109   - def self.included(base) #:nodoc:
110   - mattr_reader :container_name, :cloudfiles_config
111   -
112   - begin
113   - require 'cloudfiles'
114   - rescue LoadError
115   - raise RequiredLibraryNotFoundError.new('CloudFiles could not be loaded')
116   - end
117   -
118   - begin
119   - @@cloudfiles_config_path = base.attachment_options[:cloudfiles_config_path] || (Rails.root.to_s + '/config/rackspace_cloudfiles.yml')
120   - @@cloudfiles_config = @@cloudfiles_config = YAML.load(ERB.new(File.read(@@cloudfiles_config_path)).result)[Rails.env].symbolize_keys
121   - rescue
122   - #raise ConfigFileNotFoundError.new('File %s not found' % @@cloudfiles_config_path)
123   - end
124   -
125   - @@container_name = @@cloudfiles_config[:container_name]
126   - @@cf = CloudFiles::Connection.new(@@cloudfiles_config[:username], @@cloudfiles_config[:api_key])
127   - @@container = @@cf.container(@@container_name)
128   -
129   - base.before_update :rename_file
130   - end
131   -
132   - # Overwrites the base filename writer in order to store the old filename
133   - def filename=(value)
134   - @old_filename = filename unless filename.nil? || @old_filename
135   - write_attribute :filename, sanitize_filename(value)
136   - end
137   -
138   - # The attachment ID used in the full path of a file
139   - def attachment_path_id
140   - ((respond_to?(:parent_id) && parent_id) || id).to_s
141   - end
142   -
143   - # The pseudo hierarchy containing the file relative to the container name
144   - # Example: <tt>:table_name/:id</tt>
145   - def base_path
146   - File.join(attachment_options[:path_prefix], attachment_path_id)
147   - end
148   -
149   - # The full path to the file relative to the container name
150   - # Example: <tt>:table_name/:id/:filename</tt>
151   - def full_filename(thumbnail = nil)
152   - File.join(base_path, thumbnail_name_for(thumbnail))
153   - end
154   -
155   - # All public objects are accessible via a GET request to the Cloud Files servers. You can generate a
156   - # url for an object using the cloudfiles_url method.
157   - #
158   - # @photo.cloudfiles_url
159   - #
160   - # The resulting url is in the CDN URL for the object
161   - #
162   - # The optional thumbnail argument will output the thumbnail's filename (if any).
163   - #
164   - # If you are trying to get the URL for a nonpublic container, nil will be returned.
165   - def cloudfiles_url(thumbnail = nil)
166   - if @@container.public?
167   - File.join(@@container.cdn_url, full_filename(thumbnail))
168   - else
169   - nil
170   - end
171   - end
172   - alias :public_filename :cloudfiles_url
173   -
174   - def create_temp_file
175   - write_to_temp_file current_data
176   - end
177   -
178   - def current_data
179   - @@container.get_object(full_filename).data
180   - end
181   -
182   - protected
183   - # Called in the after_destroy callback
184   - def destroy_file
185   - @@container.delete_object(full_filename)
186   - end
187   -
188   - def rename_file
189   - # Cloud Files doesn't rename right now, so we'll just nuke.
190   - return unless @old_filename && @old_filename != filename
191   -
192   - old_full_filename = File.join(base_path, @old_filename)
193   - @@container.delete_object(old_full_filename)
194   -
195   - @old_filename = nil
196   - true
197   - end
198   -
199   - def save_to_storage
200   - if save_attachment?
201   - @object = @@container.create_object(full_filename)
202   - @object.write((temp_path ? File.open(temp_path) : temp_data))
203   - end
204   -
205   - @old_filename = nil
206   - true
207   - end
208   - end
209   - end
210   - end
211   -end
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/db_file_backend.rb
... ... @@ -1,39 +0,0 @@
1   -module Technoweenie # :nodoc:
2   - module AttachmentFu # :nodoc:
3   - module Backends
4   - # Methods for DB backed attachments
5   - module DbFileBackend
6   - def self.included(base) #:nodoc:
7   - Object.const_set(:DbFile, Class.new(ActiveRecord::Base)) unless Object.const_defined?(:DbFile)
8   - base.belongs_to :db_file, :class_name => '::DbFile', :foreign_key => 'db_file_id'
9   - end
10   -
11   - # Creates a temp file with the current db data.
12   - def create_temp_file
13   - write_to_temp_file current_data
14   - end
15   -
16   - # Gets the current data from the database
17   - def current_data
18   - db_file.data
19   - end
20   -
21   - protected
22   - # Destroys the file. Called in the after_destroy callback
23   - def destroy_file
24   - db_file.destroy if db_file
25   - end
26   -
27   - # Saves the data to the DbFile model
28   - def save_to_storage
29   - if save_attachment?
30   - (db_file || build_db_file).data = temp_data
31   - db_file.save!
32   - self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
33   - end
34   - true
35   - end
36   - end
37   - end
38   - end
39   -end
40 0 \ No newline at end of file
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/file_system_backend.rb
... ... @@ -1,126 +0,0 @@
1   -require 'fileutils'
2   -require 'digest/sha2'
3   -
4   -module Technoweenie # :nodoc:
5   - module AttachmentFu # :nodoc:
6   - module Backends
7   - # Methods for file system backed attachments
8   - module FileSystemBackend
9   - def self.included(base) #:nodoc:
10   - base.before_update :rename_file
11   - end
12   -
13   - # Gets the full path to the filename in this format:
14   - #
15   - # # This assumes a model name like MyModel
16   - # # public/#{table_name} is the default filesystem path
17   - # #{Rails.root}/public/my_models/5/blah.jpg
18   - #
19   - # Overwrite this method in your model to customize the filename.
20   - # The optional thumbnail argument will output the thumbnail's filename.
21   - def full_filename(thumbnail = nil)
22   - file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s
23   - File.join(Rails.root, file_system_path, *partitioned_path(thumbnail_name_for(thumbnail)))
24   - end
25   -
26   - # Used as the base path that #public_filename strips off full_filename to create the public path
27   - def base_path
28   - @base_path ||= File.join(Rails.root, 'public')
29   - end
30   -
31   - # The attachment ID used in the full path of a file
32   - def attachment_path_id
33   - ((respond_to?(:parent_id) && parent_id) || id) || 0
34   - end
35   -
36   - # Partitions the given path into an array of path components.
37   - #
38   - # For example, given an <tt>*args</tt> of ["foo", "bar"], it will return
39   - # <tt>["0000", "0001", "foo", "bar"]</tt> (assuming that that id returns 1).
40   - #
41   - # If the id is not an integer, then path partitioning will be performed by
42   - # hashing the string value of the id with SHA-512, and splitting the result
43   - # into 4 components. If the id a 128-bit UUID (as set by :uuid_primary_key => true)
44   - # then it will be split into 2 components.
45   - #
46   - # To turn this off entirely, set :partition => false.
47   - def partitioned_path(*args)
48   - if respond_to?(:attachment_options) && attachment_options[:partition] == false
49   - args
50   - elsif attachment_options[:uuid_primary_key]
51   - # Primary key is a 128-bit UUID in hex format. Split it into 2 components.
52   - path_id = attachment_path_id.to_s
53   - component1 = path_id[0..15] || "-"
54   - component2 = path_id[16..-1] || "-"
55   - [component1, component2] + args
56   - else
57   - path_id = attachment_path_id
58   - if path_id.is_a?(Integer)
59   - # Primary key is an integer. Split it after padding it with 0.
60   - ("%08d" % path_id).scan(/..../) + args
61   - else
62   - # Primary key is a String. Hash it, then split it into 4 components.
63   - hash = Digest::SHA512.hexdigest(path_id.to_s)
64   - [hash[0..31], hash[32..63], hash[64..95], hash[96..127]] + args
65   - end
66   - end
67   - end
68   -
69   - # Gets the public path to the file
70   - # The optional thumbnail argument will output the thumbnail's filename.
71   - def public_filename(thumbnail = nil)
72   - full_filename(thumbnail).gsub %r(^#{Regexp.escape(base_path)}), ''
73   - end
74   -
75   - def filename=(value)
76   - @old_filename = full_filename unless filename.nil? || @old_filename
77   - write_attribute :filename, sanitize_filename(value)
78   - end
79   -
80   - # Creates a temp file from the currently saved file.
81   - def create_temp_file
82   - copy_to_temp_file full_filename
83   - end
84   -
85   - protected
86   - # Destroys the file. Called in the after_destroy callback
87   - def destroy_file
88   - FileUtils.rm full_filename
89   - # remove directory also if it is now empty
90   - Dir.rmdir(File.dirname(full_filename)) if (Dir.entries(File.dirname(full_filename))-['.','..']).empty?
91   - rescue
92   - logger.info "Exception destroying #{full_filename.inspect}: [#{$!.class.name}] #{$1.to_s}"
93   - logger.warn $!.backtrace.collect { |b| " > #{b}" }.join("\n")
94   - end
95   -
96   - # Renames the given file before saving
97   - def rename_file
98   - return unless @old_filename && @old_filename != full_filename
99   - if save_attachment? && File.exists?(@old_filename)
100   - FileUtils.rm @old_filename
101   - elsif File.exists?(@old_filename)
102   - FileUtils.mv @old_filename, full_filename
103   - end
104   - @old_filename = nil
105   - true
106   - end
107   -
108   - # Saves the file to the file system
109   - def save_to_storage
110   - if save_attachment?
111   - # TODO: This overwrites the file if it exists, maybe have an allow_overwrite option?
112   - FileUtils.mkdir_p(File.dirname(full_filename))
113   - FileUtils.cp(temp_path, full_filename)
114   - FileUtils.chmod(attachment_options[:chmod] || 0644, full_filename)
115   - end
116   - @old_filename = nil
117   - true
118   - end
119   -
120   - def current_data
121   - File.file?(full_filename) ? File.read(full_filename) : nil
122   - end
123   - end
124   - end
125   - end
126   -end
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/s3_backend.rb
... ... @@ -1,412 +0,0 @@
1   -module Technoweenie # :nodoc:
2   - module AttachmentFu # :nodoc:
3   - module Backends
4   - # = AWS::S3 Storage Backend
5   - #
6   - # Enables use of {Amazon's Simple Storage Service}[http://aws.amazon.com/s3] as a storage mechanism
7   - #
8   - # == Requirements
9   - #
10   - # Requires the {AWS::S3 Library}[http://amazon.rubyforge.org] for S3 by Marcel Molina Jr. installed either
11   - # as a gem or a as a Rails plugin.
12   - #
13   - # == Configuration
14   - #
15   - # Configuration is done via <tt>#{Rails.root}/config/amazon_s3.yml</tt> and is loaded according to the <tt>#{Rails.env}</tt>.
16   - # The minimum connection options that you must specify are a bucket name, your access key id and your secret access key.
17   - # If you don't already have your access keys, all you need to sign up for the S3 service is an account at Amazon.
18   - # You can sign up for S3 and get access keys by visiting http://aws.amazon.com/s3.
19   - #
20   - # If you wish to use Amazon CloudFront to serve the files, you can also specify a distibution domain for the bucket.
21   - # To read more about CloudFront, visit http://aws.amazon.com/cloudfront
22   - #
23   - # Example configuration (#{Rails.root}/config/amazon_s3.yml)
24   - #
25   - # development:
26   - # bucket_name: appname_development
27   - # access_key_id: <your key>
28   - # secret_access_key: <your key>
29   - # distribution_domain: XXXX.cloudfront.net
30   - #
31   - # test:
32   - # bucket_name: appname_test
33   - # access_key_id: <your key>
34   - # secret_access_key: <your key>
35   - # distribution_domain: XXXX.cloudfront.net
36   - #
37   - # production:
38   - # bucket_name: appname
39   - # access_key_id: <your key>
40   - # secret_access_key: <your key>
41   - # distribution_domain: XXXX.cloudfront.net
42   - #
43   - # You can change the location of the config path by passing a full path to the :s3_config_path option.
44   - #
45   - # has_attachment :storage => :s3, :s3_config_path => (#{Rails.root} + '/config/s3.yml')
46   - #
47   - # === Required configuration parameters
48   - #
49   - # * <tt>:access_key_id</tt> - The access key id for your S3 account. Provided by Amazon.
50   - # * <tt>:secret_access_key</tt> - The secret access key for your S3 account. Provided by Amazon.
51   - # * <tt>:bucket_name</tt> - A unique bucket name (think of the bucket_name as being like a database name).
52   - #
53   - # If any of these required arguments is missing, a MissingAccessKey exception will be raised from AWS::S3.
54   - #
55   - # == About bucket names
56   - #
57   - # Bucket names have to be globaly unique across the S3 system. And you can only have up to 100 of them,
58   - # so it's a good idea to think of a bucket as being like a database, hence the correspondance in this
59   - # implementation to the development, test, and production environments.
60   - #
61   - # The number of objects you can store in a bucket is, for all intents and purposes, unlimited.
62   - #
63   - # === Optional configuration parameters
64   - #
65   - # * <tt>:server</tt> - The server to make requests to. Defaults to <tt>s3.amazonaws.com</tt>.
66   - # * <tt>:port</tt> - The port to the requests should be made on. Defaults to 80 or 443 if <tt>:use_ssl</tt> is set.
67   - # * <tt>:use_ssl</tt> - If set to true, <tt>:port</tt> will be implicitly set to 443, unless specified otherwise. Defaults to false.
68   - # * <tt>:distribution_domain</tt> - The CloudFront distribution domain for the bucket. This can either be the assigned
69   - # distribution domain (ie. XXX.cloudfront.net) or a chosen domain using a CNAME. See CloudFront for more details.
70   - #
71   - # == Usage
72   - #
73   - # To specify S3 as the storage mechanism for a model, set the acts_as_attachment <tt>:storage</tt> option to <tt>:s3</tt>.
74   - #
75   - # class Photo < ActiveRecord::Base
76   - # has_attachment :storage => :s3
77   - # end
78   - #
79   - # === Customizing the path
80   - #
81   - # By default, files are prefixed using a pseudo hierarchy in the form of <tt>:table_name/:id</tt>, which results
82   - # in S3 urls that look like: http(s)://:server/:bucket_name/:table_name/:id/:filename with :table_name
83   - # representing the customizable portion of the path. You can customize this prefix using the <tt>:path_prefix</tt>
84   - # option:
85   - #
86   - # class Photo < ActiveRecord::Base
87   - # has_attachment :storage => :s3, :path_prefix => 'my/custom/path'
88   - # end
89   - #
90   - # Which would result in URLs like <tt>http(s)://:server/:bucket_name/my/custom/path/:id/:filename.</tt>
91   - #
92   - # === Using different bucket names on different models
93   - #
94   - # By default the bucket name that the file will be stored to is the one specified by the
95   - # <tt>:bucket_name</tt> key in the amazon_s3.yml file. You can use the <tt>:bucket_key</tt> option
96   - # to overide this behavior on a per model basis. For instance if you want a bucket that will hold
97   - # only Photos you can do this:
98   - #
99   - # class Photo < ActiveRecord::Base
100   - # has_attachment :storage => :s3, :bucket_key => :photo_bucket_name
101   - # end
102   - #
103   - # And then your amazon_s3.yml file needs to look like this.
104   - #
105   - # development:
106   - # bucket_name: appname_development
107   - # access_key_id: <your key>
108   - # secret_access_key: <your key>
109   - #
110   - # test:
111   - # bucket_name: appname_test
112   - # access_key_id: <your key>
113   - # secret_access_key: <your key>
114   - #
115   - # production:
116   - # bucket_name: appname
117   - # photo_bucket_name: appname_photos
118   - # access_key_id: <your key>
119   - # secret_access_key: <your key>
120   - #
121   - # If the bucket_key you specify is not there in a certain environment then attachment_fu will
122   - # default to the <tt>bucket_name</tt> key. This way you only have to create special buckets
123   - # this can be helpful if you only need special buckets in certain environments.
124   - #
125   - # === Permissions
126   - #
127   - # By default, files are stored on S3 with public access permissions. You can customize this using
128   - # the <tt>:s3_access</tt> option to <tt>has_attachment</tt>. Available values are
129   - # <tt>:private</tt>, <tt>:public_read_write</tt>, and <tt>:authenticated_read</tt>.
130   - #
131   - # === Other options
132   - #
133   - # Of course, all the usual configuration options apply, such as content_type and thumbnails:
134   - #
135   - # class Photo < ActiveRecord::Base
136   - # has_attachment :storage => :s3, :content_type => ['application/pdf', :image], :resize_to => 'x50'
137   - # has_attachment :storage => :s3, :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
138   - # end
139   - #
140   - # === Accessing S3 URLs
141   - #
142   - # You can get an object's URL using the s3_url accessor. For example, assuming that for your postcard app
143   - # you had a bucket name like 'postcard_world_development', and an attachment model called Photo:
144   - #
145   - # @postcard.s3_url # => http(s)://s3.amazonaws.com/postcard_world_development/photos/1/mexico.jpg
146   - #
147   - # The resulting url is in the form: http(s)://:server/:bucket_name/:table_name/:id/:file.
148   - # The optional thumbnail argument will output the thumbnail's filename (if any).
149   - #
150   - # Additionally, you can get an object's base path relative to the bucket root using
151   - # <tt>base_path</tt>:
152   - #
153   - # @photo.file_base_path # => photos/1
154   - #
155   - # And the full path (including the filename) using <tt>full_filename</tt>:
156   - #
157   - # @photo.full_filename # => photos/
158   - #
159   - # Niether <tt>base_path</tt> or <tt>full_filename</tt> include the bucket name as part of the path.
160   - # You can retrieve the bucket name using the <tt>bucket_name</tt> method.
161   - #
162   - # === Accessing CloudFront URLs
163   - #
164   - # You can get an object's CloudFront URL using the cloudfront_url accessor. Using the example from above:
165   - # @postcard.cloudfront_url # => http://XXXX.cloudfront.net/photos/1/mexico.jpg
166   - #
167   - # The resulting url is in the form: http://:distribution_domain/:table_name/:id/:file
168   - #
169   - # If you set :cloudfront to true in your model, the public_filename will be the CloudFront
170   - # URL, not the S3 URL.
171   - module S3Backend
172   - class RequiredLibraryNotFoundError < StandardError; end
173   - class ConfigFileNotFoundError < StandardError; end
174   -
175   - def self.included(base) #:nodoc:
176   - mattr_reader :bucket_name, :s3_config
177   -
178   - begin
179   - require 'aws/s3'
180   - include AWS::S3
181   - rescue LoadError
182   - raise RequiredLibraryNotFoundError.new('AWS::S3 could not be loaded')
183   - end
184   -
185   - begin
186   - @@s3_config_path = base.attachment_options[:s3_config_path] || File.join(Rails.root, 'config', 'amazon_s3.yml')
187   - @@s3_config = @@s3_config = YAML.load(ERB.new(File.read(@@s3_config_path)).result)[Rails.env].symbolize_keys
188   - #rescue
189   - # raise ConfigFileNotFoundError.new('File %s not found' % @@s3_config_path)
190   - end
191   -
192   - bucket_key = base.attachment_options[:bucket_key]
193   -
194   - if bucket_key and s3_config[bucket_key.to_sym]
195   - eval_string = "def bucket_name()\n \"#{s3_config[bucket_key.to_sym]}\"\nend"
196   - else
197   - eval_string = "def bucket_name()\n \"#{s3_config[:bucket_name]}\"\nend"
198   - end
199   - base.class_eval(eval_string, __FILE__, __LINE__)
200   -
201   - Base.establish_connection!(s3_config.slice(:access_key_id, :secret_access_key, :server, :port, :use_ssl, :persistent, :proxy))
202   -
203   - # Bucket.create(@@bucket_name)
204   -
205   - base.before_update :rename_file
206   - end
207   -
208   - def self.protocol
209   - @protocol ||= s3_config[:use_ssl] ? 'https://' : 'http://'
210   - end
211   -
212   - def self.hostname
213   - @hostname ||= s3_config[:server] || AWS::S3::DEFAULT_HOST
214   - end
215   -
216   - def self.port_string
217   - @port_string ||= (s3_config[:port].nil? || s3_config[:port] == (s3_config[:use_ssl] ? 443 : 80)) ? '' : ":#{s3_config[:port]}"
218   - end
219   -
220   - def self.distribution_domain
221   - @distribution_domain = s3_config[:distribution_domain]
222   - end
223   -
224   - module ClassMethods
225   - def s3_protocol
226   - Technoweenie::AttachmentFu::Backends::S3Backend.protocol
227   - end
228   -
229   - def s3_hostname
230   - Technoweenie::AttachmentFu::Backends::S3Backend.hostname
231   - end
232   -
233   - def s3_port_string
234   - Technoweenie::AttachmentFu::Backends::S3Backend.port_string
235   - end
236   -
237   - def cloudfront_distribution_domain
238   - Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
239   - end
240   - end
241   -
242   - # Overwrites the base filename writer in order to store the old filename
243   - def filename=(value)
244   - @old_filename = filename unless filename.nil? || @old_filename
245   - write_attribute :filename, sanitize_filename(value)
246   - end
247   -
248   - # The attachment ID used in the full path of a file
249   - def attachment_path_id
250   - ((respond_to?(:parent_id) && parent_id) || id).to_s
251   - end
252   -
253   - # The pseudo hierarchy containing the file relative to the bucket name
254   - # Example: <tt>:table_name/:id</tt>
255   - def base_path
256   - File.join(attachment_options[:path_prefix], attachment_path_id)
257   - end
258   -
259   - # The full path to the file relative to the bucket name
260   - # Example: <tt>:table_name/:id/:filename</tt>
261   - def full_filename(thumbnail = nil)
262   - File.join(base_path, thumbnail_name_for(thumbnail))
263   - end
264   -
265   - # All public objects are accessible via a GET request to the S3 servers. You can generate a
266   - # url for an object using the s3_url method.
267   - #
268   - # @photo.s3_url
269   - #
270   - # The resulting url is in the form: <tt>http(s)://:server/:bucket_name/:table_name/:id/:file</tt> where
271   - # the <tt>:server</tt> variable defaults to <tt>AWS::S3 URL::DEFAULT_HOST</tt> (s3.amazonaws.com) and can be
272   - # set using the configuration parameters in <tt>#{Rails.root}/config/amazon_s3.yml</tt>.
273   - #
274   - # The optional thumbnail argument will output the thumbnail's filename (if any).
275   - def s3_url(thumbnail = nil)
276   - File.join(s3_protocol + s3_hostname + s3_port_string, bucket_name, full_filename(thumbnail))
277   - end
278   -
279   - # All public objects are accessible via a GET request to CloudFront. You can generate a
280   - # url for an object using the cloudfront_url method.
281   - #
282   - # @photo.cloudfront_url
283   - #
284   - # The resulting url is in the form: <tt>http://:distribution_domain/:table_name/:id/:file</tt> using
285   - # the <tt>:distribution_domain</tt> variable set in the configuration parameters in <tt>#{Rails.root}/config/amazon_s3.yml</tt>.
286   - #
287   - # The optional thumbnail argument will output the thumbnail's filename (if any).
288   - def cloudfront_url(thumbnail = nil)
289   - s3_protocol + cloudfront_distribution_domain + "/" + full_filename(thumbnail)
290   - end
291   -
292   - def public_filename(*args)
293   - if attachment_options[:cloudfront]
294   - cloudfront_url(*args)
295   - else
296   - s3_url(*args)
297   - end
298   - end
299   -
300   - # All private objects are accessible via an authenticated GET request to the S3 servers. You can generate an
301   - # authenticated url for an object like this:
302   - #
303   - # @photo.authenticated_s3_url
304   - #
305   - # By default authenticated urls expire 5 minutes after they were generated.
306   - #
307   - # Expiration options can be specified either with an absolute time using the <tt>:expires</tt> option,
308   - # or with a number of seconds relative to now with the <tt>:expires_in</tt> option:
309   - #
310   - # # Absolute expiration date (October 13th, 2025)
311   - # @photo.authenticated_s3_url(:expires => Time.mktime(2025,10,13).to_i)
312   - #
313   - # # Expiration in five hours from now
314   - # @photo.authenticated_s3_url(:expires_in => 5.hours)
315   - #
316   - # You can specify whether the url should go over SSL with the <tt>:use_ssl</tt> option.
317   - # By default, the ssl settings for the current connection will be used:
318   - #
319   - # @photo.authenticated_s3_url(:use_ssl => true)
320   - #
321   - # Finally, the optional thumbnail argument will output the thumbnail's filename (if any):
322   - #
323   - # @photo.authenticated_s3_url('thumbnail', :expires_in => 5.hours, :use_ssl => true)
324   - def authenticated_s3_url(*args)
325   - options = args.extract_options!
326   - options[:expires_in] = options[:expires_in].to_i if options[:expires_in]
327   - thumbnail = args.shift
328   - S3Object.url_for(full_filename(thumbnail), bucket_name, options)
329   - end
330   -
331   - def create_temp_file
332   - write_to_temp_file current_data
333   - end
334   -
335   - def current_data
336   - if attachment_options[:encrypted_storage] && self.respond_to?(:encryption_key) && self.encryption_key != nil
337   - EncryptedData.decrypt_data(S3Object.value(full_filename, bucket_name), self.encryption_key)
338   - else
339   - S3Object.value full_filename, bucket_name
340   - end
341   - end
342   -
343   - def s3_protocol
344   - Technoweenie::AttachmentFu::Backends::S3Backend.protocol
345   - end
346   -
347   - def s3_hostname
348   - Technoweenie::AttachmentFu::Backends::S3Backend.hostname
349   - end
350   -
351   - def s3_port_string
352   - Technoweenie::AttachmentFu::Backends::S3Backend.port_string
353   - end
354   -
355   - def cloudfront_distribution_domain
356   - Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
357   - end
358   -
359   - protected
360   - # Called in the after_destroy callback
361   - def destroy_file
362   - S3Object.delete full_filename, bucket_name
363   - end
364   -
365   - def rename_file
366   - return unless @old_filename && @old_filename != filename
367   -
368   - old_full_filename = File.join(base_path, @old_filename)
369   -
370   - S3Object.rename(
371   - old_full_filename,
372   - full_filename,
373   - bucket_name,
374   - :access => attachment_options[:s3_access]
375   - )
376   -
377   - @old_filename = nil
378   - true
379   - end
380   -
381   - def save_to_storage
382   - if save_attachment?
383   - if attachment_options[:encrypted_storage]
384   - S3Object.store(
385   - full_filename,
386   - (temp_path ? File.open(temp_path) : temp_data),
387   - bucket_name,
388   - :content_type => content_type,
389   - :cache_control => attachment_options[:cache_control],
390   - :access => attachment_options[:s3_access],
391   - 'x-amz-server-side-encryption' => 'AES256',
392   - 'Content-Disposition' => "attachment; filename=\"#{filename}\""
393   - )
394   - else
395   - S3Object.store(
396   - full_filename,
397   - (temp_path ? File.open(temp_path) : temp_data),
398   - bucket_name,
399   - :content_type => content_type,
400   - :cache_control => attachment_options[:cache_control],
401   - :access => attachment_options[:s3_access]
402   - )
403   - end
404   - end
405   -
406   - @old_filename = nil
407   - true
408   - end
409   - end
410   - end
411   - end
412   -end
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/processors/core_image_processor.rb
... ... @@ -1,66 +0,0 @@
1   -require 'red_artisan/core_image/processor'
2   -
3   -module Technoweenie # :nodoc:
4   - module AttachmentFu # :nodoc:
5   - module Processors
6   - module CoreImageProcessor
7   - def self.included(base)
8   - base.send :extend, ClassMethods
9   - base.alias_method_chain :process_attachment, :processing
10   - end
11   -
12   - module ClassMethods
13   - def with_image(file, &block)
14   - block.call OSX::CIImage.from(file)
15   - end
16   - end
17   -
18   - protected
19   - def process_attachment_with_processing
20   - return unless process_attachment_without_processing
21   - with_image do |img|
22   - self.width = img.extent.size.width if respond_to?(:width)
23   - self.height = img.extent.size.height if respond_to?(:height)
24   - resize_image_or_thumbnail! img
25   - callback_with_args :after_resize, img
26   - end if image?
27   - end
28   -
29   - # Performs the actual resizing operation for a thumbnail
30   - def resize_image(img, size)
31   - processor = ::RedArtisan::CoreImage::Processor.new(img)
32   - size = size.first if size.is_a?(Array) && size.length == 1
33   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
34   - if size.is_a?(Fixnum)
35   - processor.fit(size)
36   - else
37   - processor.resize(size[0], size[1])
38   - end
39   - else
40   - new_size = [img.extent.size.width, img.extent.size.height] / size.to_s
41   - processor.resize(new_size[0], new_size[1])
42   - end
43   -
44   - processor.render do |result|
45   - self.width = result.extent.size.width if respond_to?(:width)
46   - self.height = result.extent.size.height if respond_to?(:height)
47   - out_file = random_tempfile_filename
48   - temp_paths.unshift Tempfile.new(out_file, Technoweenie::AttachmentFu.tempfile_path).path
49   - properties = nil
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
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   - #
58   - self.size = File.size(self.temp_path)
59   - end
60   - end
61   - end
62   - end
63   - end
64   -end
65   -
66   -
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/processors/gd2_processor.rb
... ... @@ -1,59 +0,0 @@
1   -require 'rubygems'
2   -require 'gd2'
3   -module Technoweenie # :nodoc:
4   - module AttachmentFu # :nodoc:
5   - module Processors
6   - module Gd2Processor
7   - def self.included(base)
8   - base.send :extend, ClassMethods
9   - base.alias_method_chain :process_attachment, :processing
10   - end
11   -
12   - module ClassMethods
13   - # Yields a block containing a GD2 Image for the given binary data.
14   - def with_image(file, &block)
15   - im = GD2::Image.import(file)
16   - block.call(im)
17   - end
18   - end
19   -
20   - protected
21   - def process_attachment_with_processing
22   - return unless process_attachment_without_processing && image?
23   - with_image do |img|
24   - resize_image_or_thumbnail! img
25   - self.width = img.width
26   - self.height = img.height
27   - callback_with_args :after_resize, img
28   - end
29   - end
30   -
31   - # Performs the actual resizing operation for a thumbnail
32   - def resize_image(img, size)
33   - size = size.first if size.is_a?(Array) && size.length == 1
34   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
35   - if size.is_a?(Fixnum)
36   - # Borrowed from image science's #thumbnail method and adapted
37   - # for this.
38   - scale = size.to_f / (img.width > img.height ? img.width.to_f : img.height.to_f)
39   - img.resize!((img.width * scale).round(1), (img.height * scale).round(1), false)
40   - else
41   - img.resize!(size.first, size.last, false)
42   - end
43   - else
44   - w, h = [img.width, img.height] / size.to_s
45   - img.resize!(w, h, false)
46   - end
47   - self.width = img.width if respond_to?(:width)
48   - self.height = img.height if respond_to?(:height)
49   - out_file = random_tempfile_filename
50   - temp_paths.unshift out_file
51   - jpeg = out_file =~ /\.jpe?g\z/i
52   - quality = jpeg && get_jpeg_quality
53   - self.size = img.export(self.temp_path, quality ? { :quality => quality } : {})
54   - end
55   -
56   - end
57   - end
58   - end
59   -end
60 0 \ No newline at end of file
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/processors/image_science_processor.rb
... ... @@ -1,80 +0,0 @@
1   -require 'image_science'
2   -module Technoweenie # :nodoc:
3   - module AttachmentFu # :nodoc:
4   - module Processors
5   - module ImageScienceProcessor
6   - def self.included(base)
7   - base.send :extend, ClassMethods
8   - base.alias_method_chain :process_attachment, :processing
9   - end
10   -
11   - module ClassMethods
12   - # Yields a block containing an Image Science image for the given binary data.
13   - def with_image(file, &block)
14   - ::ImageScience.with_image file, &block
15   - end
16   - end
17   -
18   - protected
19   - def process_attachment_with_processing
20   - return unless process_attachment_without_processing && image?
21   - with_image do |img|
22   - self.width = img.width if respond_to?(:width)
23   - self.height = img.height if respond_to?(:height)
24   - resize_image_or_thumbnail! img
25   - end
26   - end
27   -
28   - # Performs the actual resizing operation for a thumbnail
29   - def resize_image(img, size)
30   - # create a dummy temp file to write to
31   - # ImageScience doesn't handle all gifs properly, so it converts them to
32   - # pngs for thumbnails. It has something to do with trying to save gifs
33   - # with a larger palette than 256 colors, which is all the gif format
34   - # supports.
35   - filename.sub! /gif$/i, 'png'
36   - content_type.sub!(/gif$/, 'png')
37   - temp_paths.unshift write_to_temp_file(filename)
38   - grab_dimensions = lambda do |img|
39   - self.width = img.width if respond_to?(:width)
40   - self.height = img.height if respond_to?(:height)
41   -
42   - # We don't check for quality being a 0-100 value as we also allow FreeImage JPEG_xxx constants.
43   - quality = content_type[/jpe?g/i] && get_jpeg_quality(false)
44   - # Traditional ImageScience has a 1-arg save method, tdd-image_science has 1 mandatory + 1 optional
45   - if quality && img.method(:save).arity == -2
46   - img.save self.temp_path, quality
47   - else
48   - img.save self.temp_path
49   - end
50   - self.size = File.size(self.temp_path)
51   - callback_with_args :after_resize, img
52   - end
53   -
54   - size = size.first if size.is_a?(Array) && size.length == 1
55   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
56   - if size.is_a?(Fixnum)
57   - img.thumbnail(size, &grab_dimensions)
58   - else
59   - img.resize(size[0], size[1], &grab_dimensions)
60   - end
61   - else
62   - new_size = [img.width, img.height] / size.to_s
63   - if size.ends_with?('!')
64   - aspect = new_size[0].to_f / new_size[1].to_f
65   - ih, iw = img.height, img.width
66   - w, h = (ih * aspect), (iw / aspect)
67   - w = [iw, w].min.to_i
68   - h = [ih, h].min.to_i
69   - img.with_crop((iw-w)/2, (ih-h)/2, (iw+w)/2, (ih+h)/2) { |crop|
70   - crop.resize(new_size[0], new_size[1], &grab_dimensions)
71   - }
72   - else
73   - img.resize(new_size[0], new_size[1], &grab_dimensions)
74   - end
75   - end
76   - end
77   - end
78   - end
79   - end
80   -end
81 0 \ No newline at end of file
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/processors/mini_magick_processor.rb
... ... @@ -1,142 +0,0 @@
1   -require 'mini_magick'
2   -module Technoweenie # :nodoc:
3   - module AttachmentFu # :nodoc:
4   - module Processors
5   - module MiniMagickProcessor
6   - def self.included(base)
7   - base.send :extend, ClassMethods
8   - base.alias_method_chain :process_attachment, :processing
9   - end
10   -
11   - module ClassMethods
12   - # Yields a block containing an MiniMagick Image for the given binary data.
13   - def with_image(file, &block)
14   - begin
15   - binary_data = file.is_a?(MiniMagick::Image) ? file : MiniMagick::Image.open(file) unless !Object.const_defined?(:MiniMagick)
16   - rescue
17   - # Log the failure to load the image.
18   - logger.debug("Exception working with image: #{$!}")
19   - binary_data = nil
20   - end
21   - block.call binary_data if block && binary_data
22   - ensure
23   - !binary_data.nil?
24   - end
25   - end
26   -
27   - protected
28   - def process_attachment_with_processing
29   - return unless process_attachment_without_processing
30   - with_image do |img|
31   - resize_image_or_thumbnail! img
32   - self.width = img[:width] if respond_to?(:width)
33   - self.height = img[:height] if respond_to?(:height)
34   - callback_with_args :after_resize, img
35   - end if image?
36   - end
37   -
38   - # Performs the actual resizing operation for a thumbnail
39   - def resize_image(img, size)
40   - size = size.first if size.is_a?(Array) && size.length == 1
41   - format = img[:format]
42   - img.combine_options do |commands|
43   - commands.strip unless attachment_options[:keep_profile]
44   -
45   - # GIF is not handled correctly, so we move to PNG, as in other processors…
46   - if format == 'GIF'
47   - img.format('PNG')
48   - end
49   -
50   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
51   - if size.is_a?(Fixnum)
52   - size = [size, size]
53   - commands.resize(size.join('x'))
54   - else
55   - commands.resize(size.join('x') + '!')
56   - end
57   - # extend to thumbnail size
58   - elsif size.is_a?(String) and size =~ /e$/
59   - size = size.gsub(/e/, '')
60   - commands.resize(size.to_s + '>')
61   - commands.background('#ffffff')
62   - commands.gravity('center')
63   - commands.extent(size)
64   - # crop thumbnail, the smart way
65   - elsif size.is_a?(String) and size =~ /c$/
66   - size = size.gsub(/c/, '')
67   -
68   - # calculate sizes and aspect ratio
69   - thumb_width, thumb_height = size.split("x")
70   - thumb_width = thumb_width.to_f
71   - thumb_height = thumb_height.to_f
72   -
73   - thumb_aspect = thumb_width.to_f / thumb_height.to_f
74   - image_width, image_height = img[:width].to_f, img[:height].to_f
75   - image_aspect = image_width / image_height
76   -
77   - # only crop if image is not smaller in both dimensions
78   - unless image_width < thumb_width and image_height < thumb_height
79   - command = calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
80   -
81   - # crop image
82   - commands.extract(command)
83   - end
84   -
85   - # don not resize if image is not as height or width then thumbnail
86   - if image_width < thumb_width or image_height < thumb_height
87   - commands.background('#ffffff')
88   - commands.gravity('center')
89   - commands.extent(size)
90   - # resize image
91   - else
92   - commands.resize("#{size.to_s}")
93   - end
94   - # crop end
95   - else
96   - commands.resize(size.to_s)
97   - end
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
107   - temp_paths.unshift img
108   - self.size = File.size(self.temp_path)
109   - end
110   -
111   - def calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
112   - # only crop if image is not smaller in both dimensions
113   -
114   - # special cases, image smaller in one dimension then thumbsize
115   - if image_width < thumb_width
116   - offset = (image_height / 2) - (thumb_height / 2)
117   - command = "#{image_width}x#{thumb_height}+0+#{offset}"
118   - elsif image_height < thumb_height
119   - offset = (image_width / 2) - (thumb_width / 2)
120   - command = "#{thumb_width}x#{image_height}+#{offset}+0"
121   -
122   - # normal thumbnail generation
123   - # calculate height and offset y, width is fixed
124   - elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
125   - height = image_width / thumb_aspect
126   - offset = (image_height / 2) - (height / 2)
127   - command = "#{image_width}x#{height}+0+#{offset}"
128   - # calculate width and offset x, height is fixed
129   - else
130   - width = image_height * thumb_aspect
131   - offset = (image_width / 2) - (width / 2)
132   - command = "#{width}x#{image_height}+#{offset}+0"
133   - end
134   - # crop image
135   - command
136   - end
137   -
138   -
139   - end
140   - end
141   - end
142   -end
143 0 \ No newline at end of file
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/processors/rmagick_processor.rb
... ... @@ -1,66 +0,0 @@
1   -require 'RMagick'
2   -module Technoweenie # :nodoc:
3   - module AttachmentFu # :nodoc:
4   - module Processors
5   - module RmagickProcessor
6   - def self.included(base)
7   - base.send :extend, ClassMethods
8   - base.alias_method_chain :process_attachment, :processing
9   - end
10   -
11   - module ClassMethods
12   - # Yields a block containing an RMagick Image for the given binary data.
13   - def with_image(file, &block)
14   - begin
15   - binary_data = file.is_a?(Magick::Image) ? file : Magick::Image.read(file).first unless !Object.const_defined?(:Magick)
16   - binary_data && binary_data.auto_orient!
17   - rescue
18   - # Log the failure to load the image. This should match ::Magick::ImageMagickError
19   - # but that would cause acts_as_attachment to require rmagick.
20   - logger.debug("Exception working with image: #{$!}")
21   - binary_data = nil
22   - end
23   - block.call binary_data if block && binary_data
24   - ensure
25   - !binary_data.nil?
26   - end
27   - end
28   -
29   - protected
30   - def process_attachment_with_processing
31   - return unless process_attachment_without_processing
32   - with_image do |img|
33   - resize_image_or_thumbnail! img
34   - self.width = img.columns if respond_to?(:width)
35   - self.height = img.rows if respond_to?(:height)
36   - callback_with_args :after_resize, img
37   - end if image?
38   - end
39   -
40   - # Performs the actual resizing operation for a thumbnail
41   - def resize_image(img, size)
42   - size = size.first if size.is_a?(Array) && size.length == 1 && !size.first.is_a?(Fixnum)
43   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
44   - size = [size, size] if size.is_a?(Fixnum)
45   - img.thumbnail!(*size)
46   - elsif size.is_a?(String) && size =~ /^c.*$/ # Image cropping - example geometry string: c75x75
47   - dimensions = size[1..size.size].split("x")
48   - img.crop_resized!(dimensions[0].to_i, dimensions[1].to_i)
49   - else
50   - img.change_geometry(size.to_s) { |cols, rows, image|
51   - image.resize!(cols<1 ? 1 : cols, rows<1 ? 1 : rows)
52   - }
53   - end
54   - self.width = img.columns if respond_to?(:width)
55   - self.height = img.rows if respond_to?(:height)
56   - img = img.sharpen if attachment_options[:sharpen_on_resize] && img.changed?
57   - img.strip! unless attachment_options[:keep_profile]
58   - quality = img.format.to_s[/JPEG/] && get_jpeg_quality
59   - out_file = write_to_temp_file(img.to_blob { self.quality = quality if quality })
60   - temp_paths.unshift out_file
61   - self.size = File.size(self.temp_path)
62   - end
63   - end
64   - end
65   - end
66   -end
vendor/plugins/attachment_fu/rackspace_cloudfiles.yml.tpl
... ... @@ -1,14 +0,0 @@
1   -development:
2   - container_name: appname_development
3   - username:
4   - api_key:
5   -
6   -test:
7   - container_name: appname_test
8   - username:
9   - api_key:
10   -
11   -production:
12   - container_name: appname_production
13   - username:
14   - api_key:
vendor/plugins/attachment_fu/test/backends/db_file_test.rb
... ... @@ -1,16 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class DbFileTest < Test::Unit::TestCase
4   - include BaseAttachmentTests
5   - attachment_model Attachment
6   -
7   - def test_should_call_after_attachment_saved(klass = Attachment)
8   - attachment_model.saves = 0
9   - assert_created do
10   - upload_file :filename => '/files/rails.png'
11   - end
12   - assert_equal 1, attachment_model.saves
13   - end
14   -
15   - test_against_subclass :test_should_call_after_attachment_saved, Attachment
16   -end
17 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/backends/file_system_test.rb
... ... @@ -1,143 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -require 'digest/sha2'
3   -
4   -class FileSystemTest < Test::Unit::TestCase
5   - include BaseAttachmentTests
6   - attachment_model FileAttachment
7   -
8   - def test_filesystem_size_for_file_attachment(klass = FileAttachment)
9   - attachment_model klass
10   - assert_created 1 do
11   - attachment = upload_file :filename => '/files/rails.png'
12   - assert_equal attachment.size, File.open(attachment.full_filename).stat.size
13   - end
14   - end
15   -
16   - test_against_subclass :test_filesystem_size_for_file_attachment, FileAttachment
17   -
18   - def test_should_not_overwrite_file_attachment(klass = FileAttachment)
19   - attachment_model klass
20   - assert_created 2 do
21   - real = upload_file :filename => '/files/rails.png'
22   - assert_valid real
23   - assert !real.new_record?, real.errors.full_messages.join("\n")
24   - assert !real.size.zero?
25   -
26   - fake = upload_file :filename => '/files/fake/rails.png'
27   - assert_valid fake
28   - assert !fake.size.zero?
29   -
30   - assert_not_equal File.open(real.full_filename).stat.size, File.open(fake.full_filename).stat.size
31   - end
32   - end
33   -
34   - test_against_subclass :test_should_not_overwrite_file_attachment, FileAttachment
35   -
36   - def test_should_store_file_attachment_in_filesystem(klass = FileAttachment)
37   - attachment_model klass
38   - attachment = nil
39   - assert_created do
40   - attachment = upload_file :filename => '/files/rails.png'
41   - assert_valid attachment
42   - assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
43   - end
44   - attachment
45   - end
46   -
47   - test_against_subclass :test_should_store_file_attachment_in_filesystem, FileAttachment
48   -
49   - def test_should_delete_old_file_when_updating(klass = FileAttachment)
50   - attachment_model klass
51   - attachment = upload_file :filename => '/files/rails.png'
52   - old_filename = attachment.full_filename
53   - assert_not_created do
54   - use_temp_file 'files/rails.png' do |file|
55   - attachment.filename = 'rails2.png'
56   - attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
57   - attachment.save!
58   - assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
59   - assert !File.exists?(old_filename), "#{old_filename} still exists"
60   - end
61   - end
62   - end
63   -
64   - test_against_subclass :test_should_delete_old_file_when_updating, FileAttachment
65   -
66   - def test_should_delete_old_file_when_renaming(klass = FileAttachment)
67   - attachment_model klass
68   - attachment = upload_file :filename => '/files/rails.png'
69   - old_filename = attachment.full_filename
70   - assert_not_created do
71   - attachment.filename = 'rails2.png'
72   - attachment.save
73   - assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
74   - assert !File.exists?(old_filename), "#{old_filename} still exists"
75   - assert !attachment.reload.size.zero?
76   - assert_equal 'rails2.png', attachment.filename
77   - end
78   - end
79   -
80   - test_against_subclass :test_should_delete_old_file_when_renaming, FileAttachment
81   -
82   - def test_path_partitioning_works_on_integer_id(klass = FileAttachment)
83   - attachment_model klass
84   -
85   - # Create a random attachment object, doesn't matter what.
86   - attachment = upload_file :filename => '/files/rails.png'
87   - old_id = attachment.id
88   - attachment.id = 1
89   -
90   - begin
91   - assert_equal ["0000", "0001", "bar.txt"], attachment.send(:partitioned_path, "bar.txt")
92   - ensure
93   - attachment.id = old_id
94   - end
95   - end
96   -
97   - test_against_subclass :test_path_partitioning_works_on_integer_id, FileAttachment
98   -
99   - def test_path_partitioning_with_string_id_works_by_generating_hash(klass = FileAttachmentWithStringId)
100   - attachment_model klass
101   -
102   - # Create a random attachment object, doesn't matter what.
103   - attachment = upload_file :filename => '/files/rails.png'
104   - old_id = attachment.id
105   - attachment.id = "hello world some long string"
106   - hash = Digest::SHA512.hexdigest("hello world some long string")
107   -
108   - begin
109   - assert_equal [
110   - hash[0..31],
111   - hash[32..63],
112   - hash[64..95],
113   - hash[96..127],
114   - "bar.txt"
115   - ], attachment.send(:partitioned_path, "bar.txt")
116   - ensure
117   - attachment.id = old_id
118   - end
119   - end
120   -
121   - test_against_subclass :test_path_partitioning_with_string_id_works_by_generating_hash, FileAttachmentWithStringId
122   -
123   - def test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid(klass = FileAttachmentWithUuid)
124   - attachment_model klass
125   -
126   - # Create a random attachment object, doesn't matter what.
127   - attachment = upload_file :filename => '/files/rails.png'
128   - old_id = attachment.id
129   - attachment.id = "0c0743b698483569dc65909a8cdb3bf9"
130   -
131   - begin
132   - assert_equal [
133   - "0c0743b698483569",
134   - "dc65909a8cdb3bf9",
135   - "bar.txt"
136   - ], attachment.send(:partitioned_path, "bar.txt")
137   - ensure
138   - attachment.id = old_id
139   - end
140   - end
141   -
142   - test_against_subclass :test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid, FileAttachmentWithUuid
143   -end
vendor/plugins/attachment_fu/test/backends/remote/cloudfiles_test.rb
... ... @@ -1,102 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
2   -require 'net/http'
3   -
4   -class CloudfilesTest < Test::Unit::TestCase
5   - def self.test_CloudFiles?
6   - true unless ENV["TEST_CLOUDFILES"] == "false"
7   - end
8   -
9   - if test_CloudFiles? && File.exist?(File.join(File.dirname(__FILE__), '../../rackspace_cloudfiles.yml'))
10   - include BaseAttachmentTests
11   - attachment_model CloudFilesAttachment
12   -
13   - def test_should_create_correct_container_name(klass = CloudFilesAttachment)
14   - attachment_model klass
15   - attachment = upload_file :filename => '/files/rails.png'
16   - assert_equal attachment.cloudfiles_config[:container_name], attachment.container_name
17   - end
18   -
19   - test_against_subclass :test_should_create_correct_container_name, CloudFilesAttachment
20   -
21   - def test_should_create_default_path_prefix(klass = CloudFilesAttachment)
22   - attachment_model klass
23   - attachment = upload_file :filename => '/files/rails.png'
24   - assert_equal File.join(attachment_model.table_name, attachment.attachment_path_id), attachment.base_path
25   - end
26   -
27   - test_against_subclass :test_should_create_default_path_prefix, CloudFilesAttachment
28   -
29   - def test_should_create_custom_path_prefix(klass = CloudFilesWithPathPrefixAttachment)
30   - attachment_model klass
31   - attachment = upload_file :filename => '/files/rails.png'
32   - assert_equal File.join('some/custom/path/prefix', attachment.attachment_path_id), attachment.base_path
33   - end
34   -
35   - test_against_subclass :test_should_create_custom_path_prefix, CloudFilesWithPathPrefixAttachment
36   -
37   -
38   - def test_should_create_valid_url(klass = CloudFilesAttachment)
39   - attachment_model klass
40   - attachment = upload_file :filename => '/files/rails.png'
41   - assert_match(%r!http://cdn.cloudfiles.mosso.com/(.*?)/cloud_files_attachments/1/rails.png!, attachment.cloudfiles_url)
42   - end
43   -
44   - test_against_subclass :test_should_create_valid_url, CloudFilesAttachment
45   -
46   - def test_should_save_attachment(klass = CloudFilesAttachment)
47   - attachment_model klass
48   - assert_created do
49   - attachment = upload_file :filename => '/files/rails.png'
50   - assert_valid attachment
51   - assert attachment.image?
52   - assert !attachment.size.zero?
53   - assert_kind_of Net::HTTPOK, http_response_for(attachment.cloudfiles_url)
54   - end
55   - end
56   -
57   - test_against_subclass :test_should_save_attachment, CloudFilesAttachment
58   -
59   - def test_should_delete_attachment_from_cloud_files_when_attachment_record_destroyed(klass = CloudFilesAttachment)
60   - attachment_model klass
61   - attachment = upload_file :filename => '/files/rails.png'
62   -
63   - urls = [attachment.cloudfiles_url] + attachment.thumbnails.collect(&:cloudfiles_url)
64   -
65   - urls.each {|url| assert_kind_of Net::HTTPOK, http_response_for(url) }
66   - attachment.destroy
67   - urls.each do |url|
68   - begin
69   - http_response_for(url)
70   - rescue Net::HTTPForbidden, Net::HTTPNotFound
71   - nil
72   - end
73   - end
74   - end
75   -
76   - test_against_subclass :test_should_delete_attachment_from_cloud_files_when_attachment_record_destroyed, CloudFilesAttachment
77   -
78   -
79   -
80   - protected
81   - def http_response_for(url)
82   - url = URI.parse(url)
83   - Net::HTTP.start(url.host, url.port) {|http| http.request_head(url.path) }
84   - end
85   -
86   - def s3_protocol
87   - Technoweenie::AttachmentFu::Backends::S3Backend.protocol
88   - end
89   -
90   - def s3_hostname
91   - Technoweenie::AttachmentFu::Backends::S3Backend.hostname
92   - end
93   -
94   - def s3_port_string
95   - Technoweenie::AttachmentFu::Backends::S3Backend.port_string
96   - end
97   - else
98   - def test_flunk_s3
99   - puts "s3 config file not loaded, tests not running"
100   - end
101   - end
102   -end
103 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/backends/remote/s3_test.rb
... ... @@ -1,119 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
2   -require 'net/http'
3   -
4   -class S3Test < Test::Unit::TestCase
5   - def self.test_S3?
6   - true unless ENV["TEST_S3"] == "false"
7   - end
8   -
9   - if test_S3? && File.exist?(File.join(File.dirname(__FILE__), '../../amazon_s3.yml'))
10   - include BaseAttachmentTests
11   - attachment_model S3Attachment
12   -
13   - def test_should_create_correct_bucket_name(klass = S3Attachment)
14   - attachment_model klass
15   - attachment = upload_file :filename => '/files/rails.png'
16   - assert_equal attachment.s3_config[:bucket_name], attachment.bucket_name
17   - end
18   -
19   - test_against_subclass :test_should_create_correct_bucket_name, S3Attachment
20   -
21   - def test_should_create_default_path_prefix(klass = S3Attachment)
22   - attachment_model klass
23   - attachment = upload_file :filename => '/files/rails.png'
24   - assert_equal File.join(attachment_model.table_name, attachment.attachment_path_id), attachment.base_path
25   - end
26   -
27   - test_against_subclass :test_should_create_default_path_prefix, S3Attachment
28   -
29   - def test_should_create_custom_path_prefix(klass = S3WithPathPrefixAttachment)
30   - attachment_model klass
31   - attachment = upload_file :filename => '/files/rails.png'
32   - assert_equal File.join('some/custom/path/prefix', attachment.attachment_path_id), attachment.base_path
33   - end
34   -
35   - test_against_subclass :test_should_create_custom_path_prefix, S3WithPathPrefixAttachment
36   -
37   - def test_should_create_valid_url(klass = S3Attachment)
38   - attachment_model klass
39   - attachment = upload_file :filename => '/files/rails.png'
40   - assert_equal "#{s3_protocol}#{s3_hostname}#{s3_port_string}/#{attachment.bucket_name}/#{attachment.full_filename}", attachment.s3_url
41   - end
42   -
43   - test_against_subclass :test_should_create_valid_url, S3Attachment
44   -
45   - def test_should_create_authenticated_url(klass = S3Attachment)
46   - attachment_model klass
47   - attachment = upload_file :filename => '/files/rails.png'
48   - assert_match /^http.+AWSAccessKeyId.+Expires.+Signature.+/, attachment.authenticated_s3_url(:use_ssl => true)
49   - end
50   -
51   - test_against_subclass :test_should_create_authenticated_url, S3Attachment
52   -
53   - def test_should_create_authenticated_url_for_thumbnail(klass = S3Attachment)
54   - attachment_model klass
55   - attachment = upload_file :filename => '/files/rails.png'
56   - ['large', :large].each do |thumbnail|
57   - assert_match(
58   - /^http.+rails_large\.png.+AWSAccessKeyId.+Expires.+Signature/,
59   - attachment.authenticated_s3_url(thumbnail),
60   - "authenticated_s3_url failed with #{thumbnail.class} parameter"
61   - )
62   - end
63   - end
64   -
65   - def test_should_save_attachment(klass = S3Attachment)
66   - attachment_model klass
67   - assert_created do
68   - attachment = upload_file :filename => '/files/rails.png'
69   - assert_valid attachment
70   - assert attachment.image?
71   - assert !attachment.size.zero?
72   - assert_kind_of Net::HTTPOK, http_response_for(attachment.s3_url)
73   - end
74   - end
75   -
76   - test_against_subclass :test_should_save_attachment, S3Attachment
77   -
78   - def test_should_delete_attachment_from_s3_when_attachment_record_destroyed(klass = S3Attachment)
79   - attachment_model klass
80   - attachment = upload_file :filename => '/files/rails.png'
81   -
82   - urls = [attachment.s3_url] + attachment.thumbnails.collect(&:s3_url)
83   -
84   - urls.each {|url| assert_kind_of Net::HTTPOK, http_response_for(url) }
85   - attachment.destroy
86   - urls.each do |url|
87   - begin
88   - http_response_for(url)
89   - rescue Net::HTTPForbidden, Net::HTTPNotFound
90   - nil
91   - end
92   - end
93   - end
94   -
95   - test_against_subclass :test_should_delete_attachment_from_s3_when_attachment_record_destroyed, S3Attachment
96   -
97   - protected
98   - def http_response_for(url)
99   - url = URI.parse(url)
100   - Net::HTTP.start(url.host, url.port) {|http| http.request_head(url.path) }
101   - end
102   -
103   - def s3_protocol
104   - Technoweenie::AttachmentFu::Backends::S3Backend.protocol
105   - end
106   -
107   - def s3_hostname
108   - Technoweenie::AttachmentFu::Backends::S3Backend.hostname
109   - end
110   -
111   - def s3_port_string
112   - Technoweenie::AttachmentFu::Backends::S3Backend.port_string
113   - end
114   - else
115   - def test_flunk_s3
116   - puts "s3 config file not loaded, tests not running"
117   - end
118   - end
119   -end
120 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/base_attachment_tests.rb
... ... @@ -1,77 +0,0 @@
1   -module BaseAttachmentTests
2   - def test_should_create_file_from_uploaded_file
3   - assert_created do
4   - attachment = upload_file :filename => '/files/foo.txt', :content_type => 'text/plain'
5   - assert_valid attachment
6   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
7   - assert !attachment.image?
8   - assert !attachment.size.zero?
9   - #assert_equal 3, attachment.size
10   - assert_nil attachment.width
11   - assert_nil attachment.height
12   - end
13   - end
14   -
15   - def test_should_create_file_from_merb_temp_file
16   - assert_created do
17   - attachment = upload_merb_file :filename => '/files/foo.txt', :content_type => 'text/plain'
18   - assert_valid attachment
19   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
20   - assert !attachment.image?
21   - assert !attachment.size.zero?
22   - #assert_equal 3, attachment.size
23   - assert_nil attachment.width
24   - assert_nil attachment.height
25   - end
26   - end
27   -
28   - def test_reassign_attribute_data
29   - assert_created 1 do
30   - attachment = upload_file :filename => '/files/rails.png'
31   - assert_valid attachment
32   - assert attachment.size > 0, "no data was set"
33   -
34   - attachment.set_temp_data 'wtf'
35   - assert attachment.save_attachment?
36   - attachment.save!
37   -
38   - assert_equal 'wtf', attachment_model.find(attachment.id).send(:current_data)
39   - end
40   - end
41   -
42   - def test_no_reassign_attribute_data_on_nil
43   - assert_created 1 do
44   - attachment = upload_file :filename => '/files/rails.png'
45   - assert_valid attachment
46   - assert attachment.size > 0, "no data was set"
47   -
48   - attachment.set_temp_data nil
49   - assert !attachment.save_attachment?
50   - end
51   - end
52   -
53   - def test_should_overwrite_old_contents_when_updating
54   - attachment = upload_file :filename => '/files/rails.png'
55   - assert_not_created do # no new db_file records
56   - use_temp_file 'files/rails.png' do |file|
57   - attachment.filename = 'rails2.png'
58   - attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
59   - attachment.save!
60   - end
61   - end
62   - end
63   -
64   - def test_should_save_without_updating_file
65   - attachment = upload_file :filename => '/files/foo.txt'
66   - assert_valid attachment
67   - assert !attachment.save_attachment?
68   - assert_nothing_raised { attachment.save! }
69   - end
70   -
71   - def test_should_handle_nil_file_upload
72   - attachment = attachment_model.create :uploaded_data => ''
73   - assert_raise ActiveRecord::RecordInvalid do
74   - attachment.save!
75   - end
76   - end
77   -end
78 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/basic_test.rb
... ... @@ -1,121 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
3   -
4   -class BasicTest < Test::Unit::TestCase
5   - def test_should_set_default_min_size
6   - assert_equal 1, Attachment.attachment_options[:min_size]
7   - end
8   -
9   - def test_should_set_default_max_size
10   - assert_equal 1.megabyte, Attachment.attachment_options[:max_size]
11   - end
12   -
13   - def test_should_set_default_size
14   - assert_equal (1..1.megabyte), Attachment.attachment_options[:size]
15   - end
16   -
17   - def test_should_set_default_thumbnails_option
18   - assert_equal Hash.new, Attachment.attachment_options[:thumbnails]
19   - end
20   -
21   - def test_should_set_default_thumbnail_class
22   - assert_equal Attachment, Attachment.attachment_options[:thumbnail_class]
23   - end
24   -
25   - def test_should_normalize_content_types_to_array
26   - assert_equal %w(pdf), PdfAttachment.attachment_options[:content_type]
27   - assert_equal %w(pdf doc txt), DocAttachment.attachment_options[:content_type]
28   - assert_equal Technoweenie::AttachmentFu.content_types, ImageAttachment.attachment_options[:content_type]
29   - assert_equal ['pdf'] + Technoweenie::AttachmentFu.content_types, ImageOrPdfAttachment.attachment_options[:content_type]
30   - end
31   -
32   - def test_should_sanitize_content_type
33   - @attachment = Attachment.new :content_type => ' foo '
34   - assert_equal 'foo', @attachment.content_type
35   - end
36   -
37   - def test_should_sanitize_filenames
38   - @attachment = Attachment.new :filename => 'blah/foo.bar'
39   - assert_equal 'foo.bar', @attachment.filename
40   -
41   - @attachment.filename = 'blah\\foo.bar'
42   - assert_equal 'foo.bar', @attachment.filename
43   -
44   - @attachment.filename = 'f o!O-.bar'
45   - assert_equal 'f_o_O-.bar', @attachment.filename
46   -
47   -# @attachment.filename = 'sheeps_says_bææ'
48   -# assert_equal 'sheeps_says_b__', @attachment.filename
49   -
50   - @attachment.filename = nil
51   - assert_nil @attachment.filename
52   - end
53   -
54   - def test_should_convert_thumbnail_name
55   - @attachment = FileAttachment.new :filename => 'foo.bar'
56   - assert_equal 'foo.bar', @attachment.thumbnail_name_for(nil)
57   - assert_equal 'foo.bar', @attachment.thumbnail_name_for('')
58   - assert_equal 'foo_blah.bar', @attachment.thumbnail_name_for(:blah)
59   - assert_equal 'foo_blah.blah.bar', @attachment.thumbnail_name_for('blah.blah')
60   -
61   - @attachment.filename = 'foo.bar.baz'
62   - assert_equal 'foo.bar_blah.baz', @attachment.thumbnail_name_for(:blah)
63   - end
64   -
65   - def test_should_require_valid_thumbnails_option
66   - klass = Class.new(ActiveRecord::Base)
67   - assert_raise ArgumentError do
68   - klass.has_attachment :thumbnails => []
69   - end
70   - end
71   -
72   - class ::ImageWithPolymorphicThumbsAttachment
73   - cattr_accessor :thumbnail_creations
74   -
75   - def create_or_update_thumbnail(path, thumb, *size)
76   - @@thumbnail_creations[thumb] = size.size == 1 ? size.first : size
77   - end
78   -
79   - def self.reset_creations
80   - @@thumbnail_creations = {}
81   - end
82   - end
83   -
84   - def test_should_handle_polymorphic_thumbnails_option
85   - assert_polymorphic_thumb_creation nil,
86   - :thumb => [50, 50], :geometry => 'x50'
87   - assert_polymorphic_thumb_creation 'Product',
88   - :thumb => [50, 50], :geometry => 'x50', :large_thumb => '169x169!', :zoomed => '500x500>'
89   - assert_polymorphic_thumb_creation 'Editorial',
90   - :thumb => [50, 50], :geometry => 'x50', :fullsize => '150x100>'
91   - assert_polymorphic_thumb_creation 'User',
92   - :thumb => [50, 50], :geometry => 'x50', :avatar => '64x64!'
93   - end
94   -
95   - def test_should_compute_per_thumbnail_jpeg_quality
96   - assert_jpeg_quality :thumb, 90
97   - assert_jpeg_quality :avatar, 85
98   - assert_jpeg_quality :large, 75
99   - assert_jpeg_quality :large, 0x200 | 75, false
100   - assert_jpeg_quality nil, 75
101   - end
102   -
103   -private
104   - def assert_jpeg_quality(thumbnail, quality, require_0_to_100 = true)
105   - klass = ImageWithPerThumbJpegAttachment
106   - w, h = if thumbnail
107   - klass.attachment_options[:thumbnails][thumbnail].scan(/\d+/)
108   - else
109   - klass.attachment_options[:resize_to].scan(/\d+/)
110   - end
111   - attachment = klass.new(:thumbnail => thumbnail, :width => w, :height => h)
112   - assert_equal quality, attachment.send(:get_jpeg_quality, require_0_to_100)
113   - end
114   -
115   - def assert_polymorphic_thumb_creation(parent, defs)
116   - attachment_model ImageWithPolymorphicThumbsAttachment
117   - attachment_model.reset_creations
118   - attachment = upload_file :filename => '/files/rails.png', :imageable_type => parent.to_s.classify, :imageable_id => nil
119   - assert_equal defs, attachment_model.thumbnail_creations
120   - end
121   -end
vendor/plugins/attachment_fu/test/database.yml
... ... @@ -1,18 +0,0 @@
1   -sqlite:
2   - :adapter: sqlite
3   - :database: attachment_fu_plugin.sqlite.db
4   -sqlite3:
5   - :adapter: sqlite3
6   - :database: attachment_fu_plugin.sqlite3.db
7   -postgresql:
8   - :adapter: postgresql
9   - :username: postgres
10   - :password: postgres
11   - :database: attachment_fu_plugin_test
12   - :min_messages: ERROR
13   -mysql:
14   - :adapter: mysql
15   - :host: localhost
16   - :username: rails
17   - :password:
18   - :database: attachment_fu_plugin_test
19 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/extra_attachment_test.rb
... ... @@ -1,67 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2   -
3   -class OrphanAttachmentTest < Test::Unit::TestCase
4   - include BaseAttachmentTests
5   - attachment_model OrphanAttachment
6   -
7   - def test_should_create_image_from_uploaded_file
8   - assert_created do
9   - attachment = upload_file :filename => '/files/rails.png'
10   - assert_valid attachment
11   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
12   - assert attachment.image?
13   - assert !attachment.size.zero?
14   - end
15   - end
16   -
17   - def test_should_create_file_from_uploaded_file
18   - assert_created do
19   - attachment = upload_file :filename => '/files/foo.txt'
20   - assert_valid attachment
21   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
22   - assert attachment.image?
23   - assert !attachment.size.zero?
24   - end
25   - end
26   -
27   - def test_should_create_file_from_merb_temp_file
28   - assert_created do
29   - attachment = upload_merb_file :filename => '/files/foo.txt'
30   - assert_valid attachment
31   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
32   - assert attachment.image?
33   - assert !attachment.size.zero?
34   - end
35   - end
36   -
37   - def test_should_create_image_from_uploaded_file_with_custom_content_type
38   - assert_created do
39   - attachment = upload_file :content_type => 'foo/bar', :filename => '/files/rails.png'
40   - assert_valid attachment
41   - assert !attachment.image?
42   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
43   - assert !attachment.size.zero?
44   - #assert_equal 1784, attachment.size
45   - end
46   - end
47   -
48   - def test_should_create_thumbnail
49   - attachment = upload_file :filename => '/files/rails.png'
50   -
51   - assert_raise Technoweenie::AttachmentFu::ThumbnailError do
52   - attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', 50, 50)
53   - end
54   - end
55   -
56   - def test_should_create_thumbnail_with_geometry_string
57   - attachment = upload_file :filename => '/files/rails.png'
58   -
59   - assert_raise Technoweenie::AttachmentFu::ThumbnailError do
60   - attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', 'x50')
61   - end
62   - end
63   -end
64   -
65   -class MinimalAttachmentTest < OrphanAttachmentTest
66   - attachment_model MinimalAttachment
67   -end
68 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/fixtures/attachment.rb
... ... @@ -1,297 +0,0 @@
1   -class Attachment < ActiveRecord::Base
2   - @@saves = 0
3   - cattr_accessor :saves
4   - has_attachment :processor => :rmagick
5   - validates_as_attachment
6   - after_save do |record|
7   - self.saves += 1
8   - end
9   -end
10   -
11   -class LowerQualityAttachment < Attachment
12   - self.table_name = 'attachments'
13   - has_attachment :resize_to => [55,55], :jpeg_quality => 50
14   -end
15   -
16   -class SmallAttachment < Attachment
17   - has_attachment :max_size => 1.kilobyte
18   -end
19   -
20   -class BigAttachment < Attachment
21   - has_attachment :size => 1.megabyte..2.megabytes
22   -end
23   -
24   -class PdfAttachment < Attachment
25   - has_attachment :content_type => 'pdf'
26   -end
27   -
28   -class DocAttachment < Attachment
29   - has_attachment :content_type => %w(pdf doc txt)
30   -end
31   -
32   -class ImageAttachment < Attachment
33   - has_attachment :content_type => :image, :resize_to => [50,50]
34   -end
35   -
36   -class ImageOrPdfAttachment < Attachment
37   - has_attachment :content_type => ['pdf', :image], :resize_to => 'x50'
38   -end
39   -
40   -class ImageWithThumbsAttachment < Attachment
41   - has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }, :resize_to => [55,55]
42   - # after_resize do |record, img|
43   - # record.aspect_ratio = img.columns.to_f / img.rows.to_f
44   - # end
45   -end
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   -
64   -class FileAttachment < ActiveRecord::Base
65   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
66   - validates_as_attachment
67   -end
68   -
69   -class FileAttachmentWithStringId < ActiveRecord::Base
70   - self.table_name = 'file_attachments_with_string_id'
71   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
72   - validates_as_attachment
73   -
74   - before_validation :auto_generate_id
75   - before_save :auto_generate_id
76   - @@last_id = 0
77   -
78   - private
79   - def auto_generate_id
80   - @@last_id += 1
81   - self.id = "id_#{@@last_id}"
82   - end
83   -end
84   -
85   -class FileAttachmentWithUuid < ActiveRecord::Base
86   - self.table_name = 'file_attachments_with_string_id'
87   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick, :uuid_primary_key => true
88   - validates_as_attachment
89   -
90   - before_validation :auto_generate_id
91   - before_save :auto_generate_id
92   - @@last_id = 0
93   -
94   - private
95   - def auto_generate_id
96   - @@last_id += 1
97   - self.id = "%0127dx" % @@last_id
98   - end
99   -end
100   -
101   -class ImageFileAttachment < FileAttachment
102   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
103   - :content_type => :image, :resize_to => [50,50]
104   -end
105   -
106   -class ImageWithThumbsFileAttachment < FileAttachment
107   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
108   - :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }, :resize_to => [55,55]
109   - # after_resize do |record, img|
110   - # record.aspect_ratio = img.columns.to_f / img.rows.to_f
111   - # end
112   -end
113   -
114   -class ImageWithThumbsClassFileAttachment < FileAttachment
115   - # use file_system_path to test backwards compatibility
116   - has_attachment :file_system_path => 'vendor/plugins/attachment_fu/test/files',
117   - :thumbnails => { :thumb => [50, 50] }, :resize_to => [55,55],
118   - :thumbnail_class => 'ImageThumbnail'
119   -end
120   -
121   -class ImageThumbnail < FileAttachment
122   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files/thumbnails'
123   -end
124   -
125   -# no parent
126   -class OrphanAttachment < ActiveRecord::Base
127   - has_attachment :processor => :rmagick
128   - validates_as_attachment
129   -end
130   -
131   -# no filename, no size, no content_type
132   -class MinimalAttachment < ActiveRecord::Base
133   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
134   - validates_as_attachment
135   -
136   - def filename
137   - "#{id}.file"
138   - end
139   -end
140   -
141   -begin
142   - class ImageScienceAttachment < ActiveRecord::Base
143   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
144   - :processor => :image_science, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
145   - end
146   -
147   - class ImageScienceLowerQualityAttachment < ActiveRecord::Base
148   - self.table_name = 'image_science_attachments'
149   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
150   - :processor => :image_science, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
151   - :jpeg_quality => 75
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
161   -rescue MissingSourceFile
162   - puts $!.message
163   - puts "no ImageScience"
164   -end
165   -
166   -begin
167   - class CoreImageAttachment < ActiveRecord::Base
168   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
169   - :processor => :core_image, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
170   - end
171   -
172   - class LowerQualityCoreImageAttachment < CoreImageAttachment
173   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
174   - :processor => :core_image, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
175   - :jpeg_quality => 50
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
185   -rescue MissingSourceFile
186   - puts $!.message
187   - puts "no CoreImage"
188   -end
189   -
190   -begin
191   - class MiniMagickAttachment < ActiveRecord::Base
192   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
193   - :processor => :mini_magick, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
194   - end
195   -
196   - class ImageThumbnailCrop < MiniMagickAttachment
197   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
198   - :thumbnails => { :square => "50x50c", :vertical => "30x60c", :horizontal => "60x30c"}
199   -
200   - # TODO this is a bad duplication, this method is in the MiniMagick Processor
201   - def self.calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
202   - # only crop if image is not smaller in both dimensions
203   -
204   - # special cases, image smaller in one dimension then thumbsize
205   - if image_width < thumb_width
206   - offset = (image_height / 2) - (thumb_height / 2)
207   - command = "#{image_width}x#{thumb_height}+0+#{offset}"
208   - elsif image_height < thumb_height
209   - offset = (image_width / 2) - (thumb_width / 2)
210   - command = "#{thumb_width}x#{image_height}+#{offset}+0"
211   -
212   - # normal thumbnail generation
213   - # calculate height and offset y, width is fixed
214   - elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
215   - height = image_width / thumb_aspect
216   - offset = (image_height / 2) - (height / 2)
217   - command = "#{image_width}x#{height}+0+#{offset}"
218   - # calculate width and offset x, height is fixed
219   - else
220   - width = image_height * thumb_aspect
221   - offset = (image_width / 2) - (width / 2)
222   - command = "#{width}x#{image_height}+#{offset}+0"
223   - end
224   - # crop image
225   - command
226   - end
227   - end
228   -
229   - class LowerQualityMiniMagickAttachment < ActiveRecord::Base
230   - self.table_name = 'mini_magick_attachments'
231   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
232   - :processor => :mini_magick, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
233   - :jpeg_quality => 50
234   - end
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   -
244   -rescue MissingSourceFile
245   - puts $!.message
246   - puts "no Mini Magick"
247   -end
248   -
249   -begin
250   - class GD2Attachment < ActiveRecord::Base
251   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
252   - :processor => :gd2, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
253   - end
254   -
255   - class LowerQualityGD2Attachment < GD2Attachment
256   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
257   - :processor => :gd2, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
258   - :jpeg_quality => 50
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
268   -rescue MissingSourceFile
269   - puts $!.message
270   - puts "no GD2"
271   -end
272   -
273   -
274   -begin
275   - class S3Attachment < ActiveRecord::Base
276   - has_attachment :storage => :s3, :processor => :rmagick, :s3_config_path => File.join(File.dirname(__FILE__), '../amazon_s3.yml')
277   - validates_as_attachment
278   - end
279   -
280   - class CloudFilesAttachment < ActiveRecord::Base
281   - has_attachment :storage => :cloud_files, :processor => :rmagick, :cloudfiles_config_path => File.join(File.dirname(__FILE__), '../rackspace_cloudfiles.yml')
282   - validates_as_attachment
283   - end
284   -
285   - class S3WithPathPrefixAttachment < S3Attachment
286   - has_attachment :storage => :s3, :path_prefix => 'some/custom/path/prefix', :processor => :rmagick
287   - validates_as_attachment
288   - end
289   -
290   - class CloudFilesWithPathPrefixAttachment < CloudFilesAttachment
291   - has_attachment :storage => :cloud_files, :path_prefix => 'some/custom/path/prefix', :processor => :rmagick
292   - validates_as_attachment
293   - end
294   -
295   -rescue
296   - puts "S3 error: #{$!}"
297   -end
vendor/plugins/attachment_fu/test/fixtures/files/fake/rails.png

4.12 KB

vendor/plugins/attachment_fu/test/fixtures/files/foo.txt
... ... @@ -1 +0,0 @@
1   -foo
2 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/fixtures/files/rails.jpg

2.43 KB

vendor/plugins/attachment_fu/test/fixtures/files/rails.png

1.75 KB

vendor/plugins/attachment_fu/test/geometry_test.rb
... ... @@ -1,114 +0,0 @@
1   -require 'test/unit'
2   -require File.expand_path(File.join(File.dirname(__FILE__), '../lib/geometry')) unless Object.const_defined?(:Geometry)
3   -
4   -class GeometryTest < Test::Unit::TestCase
5   - def test_should_resize
6   - assert_geometry 50, 64,
7   - "50x50" => [39, 50],
8   - "60x60" => [47, 60],
9   - "100x100" => [78, 100]
10   - end
11   -
12   - def test_should_resize_no_width
13   - assert_geometry 50, 64,
14   - "x50" => [39, 50],
15   - "x60" => [47, 60],
16   - "x100" => [78, 100]
17   - end
18   -
19   - def test_should_resize_no_height
20   - assert_geometry 50, 64,
21   - "50" => [50, 64],
22   - "60" => [60, 77],
23   - "100" => [100, 128]
24   - end
25   -
26   - def test_should_resize_no_height_with_x
27   - assert_geometry 50, 64,
28   - "50x" => [50, 64],
29   - "60x" => [60, 77],
30   - "100x" => [100, 128]
31   - end
32   -
33   - def test_should_resize_with_percent
34   - assert_geometry 50, 64,
35   - "50x50%" => [25, 32],
36   - "60x60%" => [30, 38],
37   - "120x112%" => [60, 72]
38   - end
39   -
40   - def test_should_resize_with_percent_and_no_width
41   - assert_geometry 50, 64,
42   - "x50%" => [50, 32],
43   - "x60%" => [50, 38],
44   - "x112%" => [50, 72]
45   - end
46   -
47   - def test_should_resize_with_percent_and_no_height
48   - assert_geometry 50, 64,
49   - "50%" => [25, 32],
50   - "60%" => [30, 38],
51   - "120%" => [60, 77]
52   - end
53   -
54   - def test_should_resize_with_less
55   - assert_geometry 50, 64,
56   - "50x50<" => [50, 64],
57   - "60x60<" => [50, 64],
58   - "100x100<" => [78, 100],
59   - "100x112<" => [88, 112],
60   - "40x70<" => [50, 64]
61   - end
62   -
63   - def test_should_resize_with_less_and_no_width
64   - assert_geometry 50, 64,
65   - "x50<" => [50, 64],
66   - "x60<" => [50, 64],
67   - "x100<" => [78, 100]
68   - end
69   -
70   - def test_should_resize_with_less_and_no_height
71   - assert_geometry 50, 64,
72   - "50<" => [50, 64],
73   - "60<" => [60, 77],
74   - "100<" => [100, 128]
75   - end
76   -
77   - def test_should_resize_with_greater
78   - assert_geometry 50, 64,
79   - "50x50>" => [39, 50],
80   - "60x60>" => [47, 60],
81   - "100x100>" => [50, 64],
82   - "100x112>" => [50, 64],
83   - "40x70>" => [40, 51]
84   - end
85   -
86   - def test_should_resize_with_greater_and_no_width
87   - assert_geometry 50, 64,
88   - "x40>" => [31, 40],
89   - "x60>" => [47, 60],
90   - "x100>" => [50, 64]
91   - end
92   -
93   - def test_should_resize_with_greater_and_no_height
94   - assert_geometry 50, 64,
95   - "40>" => [40, 51],
96   - "60>" => [50, 64],
97   - "100>" => [50, 64]
98   - end
99   -
100   - def test_should_resize_with_aspect
101   - assert_geometry 50, 64,
102   - "35x35!" => [35, 35],
103   - "70x70!" => [70, 70]
104   - end
105   -
106   - protected
107   - def assert_geometry(width, height, values)
108   - values.each do |geo, result|
109   - # run twice to verify the Geometry string isn't modified after a run
110   - geo = Geometry.from_s(geo)
111   - 2.times { assert_equal result, [width, height] / geo }
112   - end
113   - end
114   -end
115 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/processors/core_image_test.rb
... ... @@ -1,58 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class CoreImageTest < Test::Unit::TestCase
4   - attachment_model CoreImageAttachment
5   -
6   - if Object.const_defined?(:OSX)
7   - def test_should_resize_image
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert attachment.image?
11   - # test core image thumbnail
12   - assert_equal 42, attachment.width
13   - assert_equal 55, attachment.height
14   -
15   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
16   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
17   - aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
18   -
19   - # test exact resize dimensions
20   - assert_equal 50, thumb.width
21   - assert_equal 51, thumb.height
22   -
23   - # test geometry strings
24   - assert_equal 31, geo.width
25   - assert_equal 41, geo.height
26   - assert_equal 25, aspect.width
27   - assert_equal 25, aspect.height
28   -
29   - # This makes sure that we didn't overwrite the original file
30   - # and will end up with a thumbnail instead of the original
31   - assert_equal 42, attachment.width
32   - assert_equal 55, attachment.height
33   -
34   - end
35   -
36   - def test_should_handle_jpeg_quality
37   - attachment_model CoreImageAttachment
38   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
39   - full_size = attachment.size
40   - attachment_model LowerQualityCoreImageAttachment
41   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
42   - lq_size = attachment.size
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
52   - end
53   - else
54   - def test_flunk
55   - puts "CoreImage not loaded, tests not running"
56   - end
57   - end
58   -end
59 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/processors/gd2_test.rb
... ... @@ -1,51 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class GD2Test < Test::Unit::TestCase
4   - attachment_model GD2Attachment
5   -
6   - if Object.const_defined?(:GD2)
7   - def test_should_resize_image
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert attachment.image?
11   - # test gd2 thumbnail
12   - assert_equal 43, attachment.width
13   - assert_equal 55, attachment.height
14   -
15   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
16   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
17   - aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
18   -
19   - # test exact resize dimensions
20   - assert_equal 50, thumb.width
21   - assert_equal 51, thumb.height
22   -
23   - # test geometry strings
24   - assert_equal 31, geo.width
25   - assert_equal 40, geo.height
26   - assert_equal 25, aspect.width
27   - assert_equal 25, aspect.height
28   - end
29   -
30   - def test_should_handle_jpeg_quality
31   - attachment_model GD2Attachment
32   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
33   - full_size = attachment.size
34   - attachment_model LowerQualityGD2Attachment
35   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
36   - lq_size = attachment.size
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
45   - end
46   - else
47   - def test_flunk
48   - puts "GD2 not loaded, tests not running"
49   - end
50   - end
51   -end
52 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/processors/image_science_test.rb
... ... @@ -1,54 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class ImageScienceTest < Test::Unit::TestCase
4   - attachment_model ImageScienceAttachment
5   -
6   - if Object.const_defined?(:ImageScience)
7   - def test_should_resize_image
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert attachment.image?
11   - # test image science thumbnail
12   - assert_equal 42, attachment.width
13   - assert_equal 55, attachment.height
14   -
15   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
16   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
17   - aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
18   -
19   - # test exact resize dimensions
20   - assert_equal 50, thumb.width
21   - assert_equal 51, thumb.height
22   -
23   - # test geometry strings
24   - assert_equal 31, geo.width
25   - assert_equal 41, geo.height
26   - assert_equal 25, aspect.width
27   - assert_equal 25, aspect.height
28   - end
29   -
30   - def test_should_handle_jpeg_quality
31   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
32   - full_size = attachment.size
33   - attachment_model ImageScienceLowerQualityAttachment
34   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
35   - lq_size = attachment.size
36   - if ImageScience.instance_method(:save).arity == -2 # tdd-image_science: JPEG quality processing
37   - assert lq_size <= full_size * 0.75, 'Lower-quality JPEG filesize should be congruently smaller'
38   - else
39   - assert_equal full_size, lq_size, 'Unsupported lower-quality JPEG should yield exact same file size'
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
48   - end
49   - else
50   - def test_flunk
51   - puts "ImageScience not loaded, tests not running"
52   - end
53   - end
54   -end
55 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/processors/mini_magick_test.rb
... ... @@ -1,122 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class MiniMagickTest < Test::Unit::TestCase
4   - attachment_model MiniMagickAttachment
5   -
6   - if Object.const_defined?(:MiniMagick)
7   - def test_should_resize_image
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert attachment.image?
11   - # test MiniMagick thumbnail
12   - assert_equal 43, attachment.width
13   - assert_equal 55, attachment.height
14   -
15   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
16   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
17   - aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
18   -
19   - # test exact resize dimensions
20   - assert_equal 50, thumb.width
21   - assert_equal 51, thumb.height
22   -
23   - # test geometry strings
24   - assert_equal 31, geo.width
25   - assert_equal 40, geo.height
26   - assert_equal 25, aspect.width
27   - assert_equal 25, aspect.height
28   - end
29   -
30   - def test_should_crop_image(klass = ImageThumbnailCrop)
31   - attachment_model klass
32   - attachment = upload_file :filename => '/files/rails.png'
33   - assert_valid attachment
34   - assert attachment.image?
35   - # has_attachment :thumbnails => { :square => "50x50c", :vertical => "30x60c", :horizontal => "60x30c"}
36   -
37   - square = attachment.thumbnails.detect { |t| t.filename =~ /_square/ }
38   - vertical = attachment.thumbnails.detect { |t| t.filename =~ /_vertical/ }
39   - horizontal = attachment.thumbnails.detect { |t| t.filename =~ /_horizontal/ }
40   -
41   - # test excat resize
42   - assert_equal 50, square.width
43   - assert_equal 50, square.height
44   -
45   - assert_equal 30, vertical.width
46   - assert_equal 60, vertical.height
47   -
48   - assert_equal 60, horizontal.width
49   - assert_equal 30, horizontal.height
50   - end
51   -
52   - # tests the first step in resize, crop the image in original size to right format
53   - def test_should_crop_image_right(klass = ImageThumbnailCrop)
54   - @@testcases.collect do |testcase|
55   - image_width, image_height, thumb_width, thumb_height = testcase[:data]
56   - image_aspect, thumb_aspect = image_width/image_height, thumb_width/thumb_height
57   - crop_comand = klass.calculate_offset(image_width, image_height, image_aspect, thumb_width, thumb_height,thumb_aspect)
58   - # pattern matching on crop command
59   - if testcase.has_key?(:height)
60   - assert crop_comand.match(/^#{image_width}x#{testcase[:height]}\+0\+#{testcase[:yoffset]}$/)
61   - else
62   - assert crop_comand.match(/^#{testcase[:width]}x#{image_height}\+#{testcase[:xoffset]}\+0$/)
63   - end
64   - end
65   - end
66   -
67   - def test_should_handle_jpeg_quality
68   - attachment_model MiniMagickAttachment
69   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
70   - full_size = attachment.size
71   - attachment_model LowerQualityMiniMagickAttachment
72   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
73   - lq_size = attachment.size
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
82   - end
83   - else
84   - def test_flunk
85   - puts "MiniMagick not loaded, tests not running"
86   - end
87   - end
88   -
89   - @@testcases = [
90   - # image_aspect <= 1 && thumb_aspect >= 1
91   - {:data => [10.0,40.0,2.0,1.0], :height => 5.0, :yoffset => 17.5}, # 1b
92   - {:data => [10.0,40.0,1.0,1.0], :height => 10.0, :yoffset => 15.0}, # 1b
93   -
94   - # image_aspect < 1 && thumb_aspect < 1
95   - {:data => [10.0,40.0,1.0,2.0], :height => 20.0, :yoffset => 10.0}, # 1a
96   - {:data => [2.0,3.0,1.0,2.0], :width => 1.5, :xoffset => 0.25}, # 1a
97   -
98   - # image_aspect = thumb_aspect
99   - {:data => [10.0,10.0,1.0,1.0], :height => 10.0, :yoffset => 0.0}, # QUADRAT 1c
100   -
101   - # image_aspect >= 1 && thumb_aspect > 1 && image_aspect < thumb_aspect
102   - {:data => [6.0,3.0,4.0,1.0], :height => 1.5, :yoffset => 0.75}, # 2b
103   - {:data => [6.0,6.0,4.0,1.0], :height => 1.5, :yoffset => 2.25}, # 2b
104   -
105   - # image_aspect > 1 && thumb_aspect > 1 && image_aspect > thumb_aspect
106   - {:data => [9.0,3.0,2.0,1.0], :width => 6.0, :xoffset => 1.5}, # 2a
107   -
108   - # image_aspect > 1 && thumb_aspect < 1 && image_aspect < thumb_aspect
109   - {:data => [10.0,5.0,0.1,2.0], :width => 0.25, :xoffset => 4.875}, # 4
110   - {:data => [10.0,5.0,1.0,2.0], :width => 2.5, :xoffset => 3.75}, # 4
111   -
112   - # image_aspect > 1 && thumb_aspect > 1 && image_aspect > thumb_aspect
113   - {:data => [9.0,3.0,2.0,1.0], :width => 6.0, :xoffset => 1.5}, # 3a
114   - # image_aspect > 1 && thumb_aspect > 1 && image_aspect < thumb_aspect
115   - {:data => [9.0,3.0,5.0,1.0], :height => 1.8, :yoffset => 0.6} # 3a
116   - ]
117   -
118   -
119   -
120   -
121   -
122   -end
vendor/plugins/attachment_fu/test/processors/rmagick_test.rb
... ... @@ -1,272 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -class RmagickTest < Test::Unit::TestCase
3   - attachment_model Attachment
4   -
5   - if Object.const_defined?(:Magick)
6   - def test_should_create_image_from_uploaded_file
7   - assert_created do
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
11   - assert attachment.image?
12   - assert !attachment.size.zero?
13   - #assert_equal 1784, attachment.size
14   - assert_equal 50, attachment.width
15   - assert_equal 64, attachment.height
16   - assert_equal '50x64', attachment.image_size
17   - end
18   - end
19   -
20   - def test_should_create_image_from_uploaded_file_with_custom_content_type
21   - assert_created do
22   - attachment = upload_file :content_type => 'foo/bar', :filename => '/files/rails.png'
23   - assert_valid attachment
24   - assert !attachment.image?
25   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
26   - assert !attachment.size.zero?
27   - #assert_equal 1784, attachment.size
28   - assert_nil attachment.width
29   - assert_nil attachment.height
30   - assert_equal [], attachment.thumbnails
31   - end
32   - end
33   -
34   - def test_should_create_thumbnail
35   - attachment = upload_file :filename => '/files/rails.png'
36   -
37   - assert_created do
38   - basename, ext = attachment.filename.split '.'
39   - thumbnail = attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', 50, 50)
40   - assert_valid thumbnail
41   - assert !thumbnail.size.zero?
42   - #assert_in_delta 4673, thumbnail.size, 2
43   - assert_equal 50, thumbnail.width
44   - assert_equal 50, thumbnail.height
45   - assert_equal [thumbnail.id], attachment.thumbnails.collect(&:id)
46   - assert_equal attachment.id, thumbnail.parent_id if thumbnail.respond_to?(:parent_id)
47   - assert_equal "#{basename}_thumb.#{ext}", thumbnail.filename
48   - end
49   - end
50   -
51   - def test_should_create_thumbnail_with_geometry_strings
52   - attachment = upload_file :filename => '/files/rails.png'
53   -
54   - assert_created do
55   - basename, ext = attachment.filename.split '.'
56   - { 'x50' => [39, 50], '25x25!' => [25, 25] }.each do |geo, (w, h)|
57   - thumbnail = attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', geo)
58   - assert_valid thumbnail
59   - assert !thumbnail.size.zero?
60   - assert_equal w, thumbnail.width
61   - assert_equal h, thumbnail.height
62   - assert_equal [thumbnail], attachment.thumbnails
63   - assert_equal attachment.id, thumbnail.parent_id if thumbnail.respond_to?(:parent_id)
64   - assert_equal "#{basename}_thumb.#{ext}", thumbnail.filename
65   - end
66   - end
67   - end
68   -
69   - def test_should_resize_image(klass = ImageAttachment)
70   - attachment_model klass
71   - assert_equal [50, 50], attachment_model.attachment_options[:resize_to]
72   - attachment = upload_file :filename => '/files/rails.png'
73   - assert_valid attachment
74   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
75   - assert attachment.image?
76   - assert !attachment.size.zero?
77   - #assert_in_delta 4673, attachment.size, 2
78   - assert_equal 50, attachment.width
79   - assert_equal 50, attachment.height
80   - end
81   -
82   - test_against_subclass :test_should_resize_image, ImageAttachment
83   -
84   - def test_should_resize_image_with_geometry(klass = ImageOrPdfAttachment)
85   - attachment_model klass
86   - assert_equal 'x50', attachment_model.attachment_options[:resize_to]
87   - attachment = upload_file :filename => '/files/rails.png'
88   - assert_valid attachment
89   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
90   - assert attachment.image?
91   - assert !attachment.size.zero?
92   - #assert_equal 3915, attachment.size
93   - assert_equal 39, attachment.width
94   - assert_equal 50, attachment.height
95   - end
96   -
97   - test_against_subclass :test_should_resize_image_with_geometry, ImageOrPdfAttachment
98   -
99   - def test_should_give_correct_thumbnail_filenames(klass = ImageWithThumbsFileAttachment)
100   - attachment_model klass
101   - assert_created 3 do
102   - attachment = upload_file :filename => '/files/rails.png'
103   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
104   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
105   -
106   - [attachment, thumb, geo].each { |record| assert_valid record }
107   -
108   - assert_match /rails\.png$/, attachment.full_filename
109   - assert_match /rails_geometry\.png$/, attachment.full_filename(:geometry)
110   - assert_match /rails_thumb\.png$/, attachment.full_filename(:thumb)
111   - end
112   - end
113   -
114   - test_against_subclass :test_should_give_correct_thumbnail_filenames, ImageWithThumbsFileAttachment
115   -
116   - def test_should_automatically_create_thumbnails(klass = ImageWithThumbsAttachment)
117   - attachment_model klass
118   - assert_created 3 do
119   - attachment = upload_file :filename => '/files/rails.png'
120   - assert_valid attachment
121   - assert !attachment.size.zero?
122   - #assert_equal 1784, attachment.size
123   - assert_equal 55, attachment.width
124   - assert_equal 55, attachment.height
125   - assert_equal 2, attachment.thumbnails.length
126   - # assert_equal 1.0, attachment.aspect_ratio
127   -
128   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
129   - assert !thumb.new_record?, thumb.errors.full_messages.join("\n")
130   - assert !thumb.size.zero?
131   - #assert_in_delta 4673, thumb.size, 2
132   - assert_equal 50, thumb.width
133   - assert_equal 50, thumb.height
134   - # assert_equal 1.0, thumb.aspect_ratio
135   -
136   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
137   - assert !geo.new_record?, geo.errors.full_messages.join("\n")
138   - assert !geo.size.zero?
139   - #assert_equal 3915, geo.size
140   - assert_equal 50, geo.width
141   - assert_equal 50, geo.height
142   - # assert_equal 1.0, geo.aspect_ratio
143   - end
144   - end
145   -
146   - test_against_subclass :test_should_automatically_create_thumbnails, ImageWithThumbsAttachment
147   -
148   - # same as above method, but test it on a file model
149   - test_against_class :test_should_automatically_create_thumbnails, ImageWithThumbsFileAttachment
150   - test_against_subclass :test_should_automatically_create_thumbnails_on_class, ImageWithThumbsFileAttachment
151   -
152   - def test_should_use_thumbnail_subclass(klass = ImageWithThumbsClassFileAttachment)
153   - attachment_model klass
154   - attachment = nil
155   - assert_difference ImageThumbnail, :count do
156   - attachment = upload_file :filename => '/files/rails.png'
157   - assert_valid attachment
158   - end
159   - assert_kind_of ImageThumbnail, attachment.thumbnails.first
160   - if attachment.thumbnails.first.respond_to?(:parent)
161   - assert_equal attachment.id, attachment.thumbnails.first.parent.id
162   - assert_kind_of FileAttachment, attachment.thumbnails.first.parent
163   - end
164   - assert_equal 'rails_thumb.png', attachment.thumbnails.first.filename
165   - assert_equal attachment.thumbnails.first.full_filename, attachment.full_filename(attachment.thumbnails.first.thumbnail),
166   - "#full_filename does not use thumbnail class' path."
167   - assert_equal attachment.destroy, attachment
168   - end
169   -
170   - test_against_subclass :test_should_use_thumbnail_subclass, ImageWithThumbsClassFileAttachment
171   -
172   - def test_should_remove_old_thumbnail_files_when_updating(klass = ImageWithThumbsFileAttachment)
173   - attachment_model klass
174   - attachment = nil
175   - assert_created 3 do
176   - attachment = upload_file :filename => '/files/rails.png'
177   - end
178   -
179   - old_filenames = [attachment.full_filename] + attachment.thumbnails.collect(&:full_filename)
180   -
181   - assert_not_created do
182   - use_temp_file "files/rails.png" do |file|
183   - attachment.filename = 'rails2.png'
184   - attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
185   - attachment.save
186   - new_filenames = [attachment.reload.full_filename] + attachment.thumbnails.collect { |t| t.reload.full_filename }
187   - new_filenames.each { |f| assert File.exists?(f), "#{f} does not exist" }
188   - old_filenames.each { |f| assert !File.exists?(f), "#{f} still exists" }
189   - end
190   - end
191   - end
192   -
193   - test_against_subclass :test_should_remove_old_thumbnail_files_when_updating, ImageWithThumbsFileAttachment
194   -
195   - def test_should_delete_file_when_in_file_system_when_attachment_record_destroyed(klass = ImageWithThumbsFileAttachment)
196   - attachment_model klass
197   - attachment = upload_file :filename => '/files/rails.png'
198   - filenames = [attachment.full_filename] + attachment.thumbnails.collect(&:full_filename)
199   - filenames.each { |f| assert File.exists?(f), "#{f} never existed to delete on destroy" }
200   - attachment.destroy
201   - filenames.each { |f| assert !File.exists?(f), "#{f} still exists" }
202   - end
203   -
204   - test_against_subclass :test_should_delete_file_when_in_file_system_when_attachment_record_destroyed, ImageWithThumbsFileAttachment
205   -
206   - def test_should_have_full_filename_method(klass = FileAttachment)
207   - attachment_model klass
208   - attachment = upload_file :filename => '/files/rails.png'
209   - assert_respond_to attachment, :full_filename
210   - end
211   -
212   - test_against_subclass :test_should_have_full_filename_method, FileAttachment
213   -
214   - def test_should_overwrite_old_thumbnail_records_when_updating(klass = ImageWithThumbsAttachment)
215   - attachment_model klass
216   - attachment = nil
217   - assert_created 3 do
218   - attachment = upload_file :filename => '/files/rails.png'
219   - end
220   - assert_not_created do # no new db_file records
221   - use_temp_file "files/rails.png" do |file|
222   - attachment.filename = 'rails2.png'
223   - # The above test (#test_should_have_full_filename_method) to pass before be can set the temp_path below --
224   - # #temp_path calls #full_filename, which is not getting mixed into the attachment. Maybe we don't need to
225   - # set temp_path at all?
226   - #
227   - # attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
228   - attachment.save!
229   - end
230   - end
231   - end
232   -
233   - test_against_subclass :test_should_overwrite_old_thumbnail_records_when_updating, ImageWithThumbsAttachment
234   -
235   - def test_should_overwrite_old_thumbnail_records_when_renaming(klass = ImageWithThumbsAttachment)
236   - attachment_model klass
237   - attachment = nil
238   - assert_created 3 do
239   - attachment = upload_file :class => klass, :filename => '/files/rails.png'
240   - end
241   - assert_not_created do # no new db_file records
242   - attachment.filename = 'rails2.png'
243   - attachment.save
244   - assert !attachment.reload.size.zero?
245   - assert_equal 'rails2.png', attachment.filename
246   - end
247   - end
248   -
249   - test_against_subclass :test_should_overwrite_old_thumbnail_records_when_renaming, ImageWithThumbsAttachment
250   -
251   - def test_should_handle_jpeg_quality
252   - attachment_model ImageWithThumbsAttachment
253   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
254   - full_size = attachment.size
255   - attachment_model LowerQualityAttachment
256   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
257   - lq_size = attachment.size
258   - assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
259   -
260   - attachment_model ImageWithPerThumbJpegAttachment
261   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
262   - assert_file_jpeg_quality attachment, :thumb, 90
263   - assert_file_jpeg_quality attachment, :avatar, 85
264   - assert_file_jpeg_quality attachment, :large, 75
265   - assert_file_jpeg_quality attachment, nil, 75
266   - end
267   - else
268   - def test_flunk
269   - puts "RMagick not installed, no tests running"
270   - end
271   - end
272   -end
vendor/plugins/attachment_fu/test/schema.rb
... ... @@ -1,136 +0,0 @@
1   -ActiveRecord::Schema.define(:version => 0) do
2   - create_table :attachments, :force => true do |t|
3   - t.column :db_file_id, :integer
4   - t.column :parent_id, :integer
5   - t.column :imageable_id, :integer
6   - t.column :imageable_type, :string, :limit => 255
7   - t.column :thumbnail, :string
8   - t.column :filename, :string, :limit => 255
9   - t.column :content_type, :string, :limit => 255
10   - t.column :size, :integer
11   - t.column :width, :integer
12   - t.column :height, :integer
13   - t.column :aspect_ratio, :float
14   - end
15   -
16   - create_table :file_attachments, :force => true do |t|
17   - t.column :parent_id, :integer
18   - t.column :thumbnail, :string
19   - t.column :filename, :string, :limit => 255
20   - t.column :content_type, :string, :limit => 255
21   - t.column :size, :integer
22   - t.column :width, :integer
23   - t.column :height, :integer
24   - t.column :type, :string
25   - t.column :aspect_ratio, :float
26   - end
27   -
28   - create_table :file_attachments_with_string_id, :id => false, :force => true do |t|
29   - t.column :id, :string
30   - t.column :parent_id, :string
31   - t.column :thumbnail, :string
32   - t.column :filename, :string, :limit => 255
33   - t.column :content_type, :string, :limit => 255
34   - t.column :size, :integer
35   - t.column :width, :integer
36   - t.column :height, :integer
37   - t.column :type, :string
38   - t.column :aspect_ratio, :float
39   - end
40   -
41   - create_table :gd2_attachments, :force => true do |t|
42   - t.column :parent_id, :integer
43   - t.column :thumbnail, :string
44   - t.column :filename, :string, :limit => 255
45   - t.column :content_type, :string, :limit => 255
46   - t.column :size, :integer
47   - t.column :width, :integer
48   - t.column :height, :integer
49   - t.column :type, :string
50   - end
51   -
52   - create_table :image_science_attachments, :force => true do |t|
53   - t.column :parent_id, :integer
54   - t.column :thumbnail, :string
55   - t.column :filename, :string, :limit => 255
56   - t.column :content_type, :string, :limit => 255
57   - t.column :size, :integer
58   - t.column :width, :integer
59   - t.column :height, :integer
60   - t.column :type, :string
61   - end
62   -
63   - create_table :core_image_attachments, :force => true do |t|
64   - t.column :parent_id, :integer
65   - t.column :thumbnail, :string
66   - t.column :filename, :string, :limit => 255
67   - t.column :content_type, :string, :limit => 255
68   - t.column :size, :integer
69   - t.column :width, :integer
70   - t.column :height, :integer
71   - t.column :type, :string
72   - end
73   -
74   - create_table :mini_magick_attachments, :force => true do |t|
75   - t.column :parent_id, :integer
76   - t.column :thumbnail, :string
77   - t.column :filename, :string, :limit => 255
78   - t.column :content_type, :string, :limit => 255
79   - t.column :size, :integer
80   - t.column :width, :integer
81   - t.column :height, :integer
82   - t.column :type, :string
83   - end
84   -
85   - create_table :mini_magick_attachments, :force => true do |t|
86   - t.column :parent_id, :integer
87   - t.column :thumbnail, :string
88   - t.column :filename, :string, :limit => 255
89   - t.column :content_type, :string, :limit => 255
90   - t.column :size, :integer
91   - t.column :width, :integer
92   - t.column :height, :integer
93   - t.column :type, :string
94   - end
95   -
96   - create_table :orphan_attachments, :force => true do |t|
97   - t.column :db_file_id, :integer
98   - t.column :filename, :string, :limit => 255
99   - t.column :content_type, :string, :limit => 255
100   - t.column :size, :integer
101   - end
102   -
103   - create_table :minimal_attachments, :force => true do |t|
104   - t.column :size, :integer
105   - t.column :content_type, :string, :limit => 255
106   - end
107   -
108   - create_table :db_files, :force => true do |t|
109   - t.column :data, :binary
110   - end
111   -
112   - create_table :s3_attachments, :force => true do |t|
113   - t.column :parent_id, :integer
114   - t.column :thumbnail, :string
115   - t.column :filename, :string, :limit => 255
116   - t.column :content_type, :string, :limit => 255
117   - t.column :size, :integer
118   - t.column :width, :integer
119   - t.column :height, :integer
120   - t.column :type, :string
121   - t.column :aspect_ratio, :float
122   - end
123   -
124   - create_table :cloud_files_attachments, :force => true do |t|
125   - t.column :parent_id, :integer
126   - t.column :thumbnail, :string
127   - t.column :filename, :string, :limit => 255
128   - t.column :content_type, :string, :limit => 255
129   - t.column :size, :integer
130   - t.column :width, :integer
131   - t.column :height, :integer
132   - t.column :type, :string
133   - t.column :aspect_ratio, :float
134   - end
135   -
136   -end
vendor/plugins/attachment_fu/test/test_helper.rb
... ... @@ -1,169 +0,0 @@
1   -$LOAD_PATH.unshift(File.dirname(__FILE__))
2   -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3   -
4   -ENV['RAILS_ENV'] = 'test'
5   -
6   -require 'rails/all'
7   -require 'test/unit'
8   -require 'pothoven-attachment_fu'
9   -include ActionDispatch::TestProcess
10   -
11   -# Define the application and configuration
12   -module RbConfig
13   - class Application < ::Rails::Application
14   - # configuration here if needed
15   - config.active_support.deprecation = :stderr
16   - end
17   -end
18   -
19   -# Initialize the application
20   -RbConfig::Application.initialize!
21   -
22   -# Setup database
23   -load(File.dirname(__FILE__) + "/schema.rb")
24   -
25   -FIXTURE_PATH = File.dirname(__FILE__) + "/fixtures"
26   -$LOAD_PATH.unshift(FIXTURE_PATH)
27   -
28   -class Test::Unit::TestCase #:nodoc:
29   - # include ActionDispatch::TestProcess
30   - def create_fixtures(*table_names)
31   - if block_given?
32   - Fixtures.create_fixtures(FIXTURE_PATH, table_names) { yield }
33   - else
34   - Fixtures.create_fixtures(FIXTURE_PATH, table_names)
35   - end
36   - end
37   -
38   - def setup
39   - Attachment.saves = 0
40   - DbFile.transaction { [Attachment, FileAttachment, OrphanAttachment, MinimalAttachment, DbFile].each { |klass| klass.delete_all } }
41   - attachment_model self.class.attachment_model
42   - end
43   -
44   - def teardown
45   - FileUtils.rm_rf File.join(File.dirname(__FILE__), 'files')
46   - # Files generated by random_tempfile_filename
47   - FileUtils.rm_rf Dir['[0-9]*.{png,jpg}']
48   - end
49   -
50   - #self.use_transactional_fixtures = true
51   - #self.use_instantiated_fixtures = false
52   -
53   - def self.attachment_model(klass = nil)
54   - @attachment_model = klass if klass
55   - @attachment_model
56   - end
57   -
58   - def self.test_against_class(test_method, klass, subclass = false)
59   - define_method("#{test_method}_on_#{:sub if subclass}class") do
60   - klass = Class.new(klass) if subclass
61   - attachment_model klass
62   - send test_method, klass
63   - end
64   - end
65   -
66   - def self.test_against_subclass(test_method, klass)
67   - test_against_class test_method, klass, true
68   - end
69   -
70   - protected
71   - def upload_file(options = {})
72   - use_temp_file options[:filename] do |file|
73   -puts options
74   - opts = { :uploaded_data => fixture_file_upload(file, options[:content_type] || 'image/png') }
75   - opts.update(options.reject { |k, v| ![:imageable_type, :imageable_id].include?(k) })
76   - att = attachment_model.create opts
77   - att.reload unless att.new_record?
78   - return att
79   - end
80   - end
81   -
82   - def upload_merb_file(options = {})
83   - use_temp_file options[:filename] do |file|
84   - att = attachment_model.create :uploaded_data => {"size" => file.size, "content_type" => options[:content_type] || 'image/png', "filename" => file, 'tempfile' => fixture_file_upload(file, options[:content_type] || 'image/png')}
85   - att.reload unless att.new_record?
86   - return att
87   - end
88   - end
89   -
90   - def use_temp_file(fixture_filename)
91   - temp_path = File.join('/tmp', File.basename(fixture_filename))
92   - temp_dir = File.join(FIXTURE_PATH, 'tmp')
93   - use_file = File.join(FIXTURE_PATH, temp_path)
94   - FileUtils.mkdir_p temp_dir
95   - FileUtils.cp File.join(FIXTURE_PATH, fixture_filename), use_file
96   - yield use_file
97   - ensure
98   - FileUtils.rm_rf temp_dir
99   - end
100   -
101   - def assert_created(num = 1)
102   - assert_difference attachment_model.base_class, :count, num do
103   - if attachment_model.included_modules.include? DbFile
104   - assert_difference DbFile, :count, num do
105   - yield
106   - end
107   - else
108   - yield
109   - end
110   - end
111   - end
112   -
113   - def assert_valid(record)
114   - assert record.valid?, record.errors.full_messages.join("\n")
115   - end
116   -
117   - def assert_file_jpeg_quality(model, thumbnail, expected)
118   - filename = if model.respond_to?(:full_filename)
119   - model.full_filename(thumbnail)
120   - else
121   - thumb = thumbnail ? model.thumbnails.find(:first, :conditions => { :thumbnail => thumbnail.to_s }, :include => :db_file) : model
122   - unless thumb && thumb.db_file && thumb.db_file.data && thumb.db_file.data.size > 0
123   - STDERR.puts "Cannot find DB file data for thumbnail #{thumbnail.inspect} -> Aborting JPEG quality check."
124   - return
125   - end
126   - result = Tempfile.new('dbfile_dump').path
127   - File.open(result, 'wb') { |f| f.write(thumb.db_file.data) }
128   - result
129   - end
130   - quality = %x(identify -format '%Q' "#{filename}" 2> /dev/null)
131   - if $?.success?
132   - assert_equal expected, quality.to_i, "Produced JPEG quality (thumbnail: #{thumbnail.inspect}) is incorrect."
133   - else
134   - STDERR.puts "ImageMagick's identify not found / not in PATH: can't quickly check produced image quality."
135   - end
136   - end
137   -
138   - def assert_not_created
139   - assert_created(0) { yield }
140   - end
141   -
142   - def should_reject_by_size_with(klass)
143   - attachment_model klass
144   - assert_not_created do
145   - attachment = upload_file :filename => '/files/rails.png'
146   - assert attachment.new_record?
147   - assert attachment.errors.on(:size)
148   - assert_nil attachment.db_file if attachment.respond_to?(:db_file)
149   - end
150   - end
151   -
152   - def assert_difference(object, method = nil, difference = 1)
153   - initial_value = object.send(method)
154   - yield
155   - assert_equal initial_value + difference, object.send(method)
156   - end
157   -
158   - def assert_no_difference(object, method, &block)
159   - assert_difference object, method, 0, &block
160   - end
161   -
162   - def attachment_model(klass = nil)
163   - @attachment_model = klass if klass
164   - @attachment_model
165   - end
166   -end
167   -
168   -require File.join(File.dirname(__FILE__), 'fixtures/attachment')
169   -require File.join(File.dirname(__FILE__), 'base_attachment_tests')
vendor/plugins/attachment_fu/test/validation_test.rb
... ... @@ -1,55 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2   -
3   -class ValidationTest < Test::Unit::TestCase
4   - def test_should_invalidate_big_files
5   - @attachment = SmallAttachment.new
6   - assert !@attachment.valid?
7   - assert @attachment.errors[:size]
8   -
9   - @attachment.size = 2000
10   - assert !@attachment.valid?
11   - assert @attachment.errors[:size], @attachment.errors.full_messages.to_sentence
12   -
13   - @attachment.size = 1000
14   - assert !@attachment.valid?
15   - assert @attachment.errors[:size].empty?
16   - end
17   -
18   - def test_should_invalidate_small_files
19   - @attachment = BigAttachment.new
20   - assert !@attachment.valid?
21   - assert @attachment.errors[:size]
22   -
23   - @attachment.size = 2000
24   - assert !@attachment.valid?
25   - assert @attachment.errors[:size], @attachment.errors.full_messages.to_sentence
26   -
27   - @attachment.size = 1.megabyte
28   - assert !@attachment.valid?
29   - assert @attachment.errors[:size].empty?
30   - end
31   -
32   - def test_should_validate_content_type
33   - @attachment = PdfAttachment.new
34   - assert !@attachment.valid?
35   - assert @attachment.errors[:content_type]
36   -
37   - @attachment.content_type = 'foo'
38   - assert !@attachment.valid?
39   - assert @attachment.errors[:content_type]
40   -
41   - @attachment.content_type = 'pdf'
42   - assert !@attachment.valid?
43   - assert @attachment.errors[:content_type].empty?
44   - end
45   -
46   - def test_should_require_filename
47   - @attachment = Attachment.new
48   - assert !@attachment.valid?
49   - assert @attachment.errors[:filename]
50   -
51   - @attachment.filename = 'foo'
52   - assert !@attachment.valid?
53   - assert @attachment.errors[:filename].empty?
54   - end
55   -end
56 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/color.rb
... ... @@ -1,27 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Color
5   -
6   - def greyscale(color = nil, intensity = 1.00)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - color = OSX::CIColor.colorWithString("1.0 1.0 1.0 1.0") unless color
10   -
11   - @original.color_monochrome :inputColor => color, :inputIntensity => intensity do |greyscale|
12   - @target = greyscale
13   - end
14   - end
15   -
16   - def sepia(intensity = 1.00)
17   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
18   -
19   - @original.sepia_tone :inputIntensity => intensity do |sepia|
20   - @target = sepia
21   - end
22   - end
23   -
24   - end
25   - end
26   - end
27   -end
28 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/effects.rb
... ... @@ -1,31 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Effects
5   -
6   - def spotlight(position, points_at, brightness, concentration, color)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - @original.spot_light :inputLightPosition => vector3(*position), :inputLightPointsAt => vector3(*points_at),
10   - :inputBrightness => brightness, :inputConcentration => concentration, :inputColor => color do |spot|
11   - @target = spot
12   - end
13   - end
14   -
15   - def edges(intensity = 1.00)
16   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
17   -
18   - @original.edges :inputIntensity => intensity do |edged|
19   - @target = edged
20   - end
21   - end
22   -
23   - private
24   -
25   - def vector3(x, y, w)
26   - OSX::CIVector.vectorWithX_Y_Z(x, y, w)
27   - end
28   - end
29   - end
30   - end
31   -end
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/perspective.rb
... ... @@ -1,25 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Perspective
5   -
6   - def perspective(top_left, top_right, bottom_left, bottom_right)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - @original.perspective_transform :inputTopLeft => top_left, :inputTopRight => top_right, :inputBottomLeft => bottom_left, :inputBottomRight => bottom_right do |transformed|
10   - @target = transformed
11   - end
12   - end
13   -
14   - def perspective_tiled(top_left, top_right, bottom_left, bottom_right)
15   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
16   -
17   - @original.perspective_tile :inputTopLeft => top_left, :inputTopRight => top_right, :inputBottomLeft => bottom_left, :inputBottomRight => bottom_right do |tiled|
18   - @target = tiled
19   - end
20   - end
21   -
22   - end
23   - end
24   - end
25   -end
26 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/quality.rb
... ... @@ -1,25 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Quality
5   -
6   - def reduce_noise(level = 0.02, sharpness = 0.4)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - @original.noise_reduction :inputNoiseLevel => level, :inputSharpness => sharpness do |noise_reduced|
10   - @target = noise_reduced
11   - end
12   - end
13   -
14   - def adjust_exposure(input_ev = 0.5)
15   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
16   -
17   - @original.exposure_adjust :inputEV => input_ev do |adjusted|
18   - @target = adjusted
19   - end
20   - end
21   -
22   - end
23   - end
24   - end
25   -end
26 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/scale.rb
... ... @@ -1,47 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Scale
5   -
6   - def resize(width, height)
7   - create_core_image_context(width, height)
8   -
9   - scale_x, scale_y = scale(width, height)
10   -
11   - @original.affine_clamp :inputTransform => OSX::NSAffineTransform.transform do |clamped|
12   - clamped.lanczos_scale_transform :inputScale => scale_x > scale_y ? scale_x : scale_y, :inputAspectRatio => scale_x / scale_y do |scaled|
13   - scaled.crop :inputRectangle => vector(0, 0, width, height) do |cropped|
14   - @target = cropped
15   - end
16   - end
17   - end
18   - end
19   -
20   - def thumbnail(width, height)
21   - create_core_image_context(width, height)
22   -
23   - transform = OSX::NSAffineTransform.transform
24   - transform.scaleXBy_yBy *scale(width, height)
25   -
26   - @original.affine_transform :inputTransform => transform do |scaled|
27   - @target = scaled
28   - end
29   - end
30   -
31   - def fit(size)
32   - original_size = @original.extent.size
33   - scale = size.to_f / (original_size.width > original_size.height ? original_size.width : original_size.height)
34   - resize (original_size.width * scale).to_i, (original_size.height * scale).to_i
35   - end
36   -
37   - private
38   -
39   - def scale(width, height)
40   - original_size = @original.extent.size
41   - return width.to_f / original_size.width.to_f, height.to_f / original_size.height.to_f
42   - end
43   -
44   - end
45   - end
46   - end
47   -end
48 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/watermark.rb
... ... @@ -1,32 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Watermark
5   -
6   - def watermark(watermark_image, tile = false, strength = 0.1)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - if watermark_image.respond_to? :to_str
10   - watermark_image = OSX::CIImage.from(watermark_image.to_str)
11   - end
12   -
13   - if tile
14   - tile_transform = OSX::NSAffineTransform.transform
15   - tile_transform.scaleXBy_yBy 1.0, 1.0
16   -
17   - watermark_image.affine_tile :inputTransform => tile_transform do |tiled|
18   - tiled.crop :inputRectangle => vector(0, 0, @original.extent.size.width, @original.extent.size.height) do |tiled_watermark|
19   - watermark_image = tiled_watermark
20   - end
21   - end
22   - end
23   -
24   - @original.dissolve_transition :inputTargetImage => watermark_image, :inputTime => strength do |watermarked|
25   - @target = watermarked
26   - end
27   - end
28   -
29   - end
30   - end
31   - end
32   -end
33 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/processor.rb
... ... @@ -1,123 +0,0 @@
1   -require 'rubygems'
2   -require 'osx/cocoa'
3   -require 'active_support'
4   -
5   -require 'red_artisan/core_image/filters/scale'
6   -require 'red_artisan/core_image/filters/color'
7   -require 'red_artisan/core_image/filters/watermark'
8   -require 'red_artisan/core_image/filters/quality'
9   -require 'red_artisan/core_image/filters/perspective'
10   -require 'red_artisan/core_image/filters/effects'
11   -
12   -# Generic image processor for scaling images based on CoreImage via RubyCocoa.
13   -#
14   -# Example usage:
15   -#
16   -# p = Processor.new OSX::CIImage.from(path_to_image)
17   -# p.resize(640, 480)
18   -# p.render do |result|
19   -# result.save('resized.jpg', OSX::NSJPEGFileType)
20   -# end
21   -#
22   -# This will resize the image to the given dimensions exactly, if you'd like to ensure that aspect ratio is preserved:
23   -#
24   -# p = Processor.new OSX::CIImage.from(path_to_image)
25   -# p.fit(640)
26   -# p.render do |result|
27   -# result.save('resized.jpg', OSX::NSJPEGFileType)
28   -# end
29   -#
30   -# fit(size) will attempt its best to resize the image so that the longest width/height (depending on image orientation) will match
31   -# the given size. The second axis will be calculated automatically based on the aspect ratio.
32   -#
33   -# Scaling is performed by first clamping the image so that its external bounds become infinite, this helps when scaling so that any
34   -# rounding discrepencies in dimensions don't affect the resultant image. We then perform a Lanczos transform on the image which scales
35   -# it to the target size. We then crop the image to the traget dimensions.
36   -#
37   -# If you are generating smaller images such as thumbnails where high quality rendering isn't as important, an additional method is
38   -# available:
39   -#
40   -# p = Processor.new OSX::CIImage.from(path_to_image)
41   -# p.thumbnail(100, 100)
42   -# p.render do |result|
43   -# result.save('resized.jpg', OSX::NSJPEGFileType)
44   -# end
45   -#
46   -# This will perform a straight affine transform and scale the X and Y boundaries to the requested size. Generally, this will be faster
47   -# than a lanczos scale transform, but with a scaling quality trade.
48   -#
49   -# More than welcome to intregrate any patches, improvements - feel free to mail me with ideas.
50   -#
51   -# Thanks to
52   -# * Satoshi Nakagawa for working out that OCObjWrapper needs inclusion when aliasing method_missing on existing OSX::* classes.
53   -# * Vasantha Crabb for general help and inspiration with Cocoa
54   -# * Ben Schwarz for example image data and collaboration during performance testing
55   -#
56   -# Copyright (c) Marcus Crafter <crafterm@redartisan.com> released under the MIT license
57   -#
58   -module RedArtisan
59   - module CoreImage
60   - class Processor
61   -
62   - def initialize(original)
63   - if original.respond_to? :to_str
64   - @original = OSX::CIImage.from(original.to_str)
65   - else
66   - @original = original
67   - end
68   - end
69   -
70   - def render(&block)
71   - raise "unprocessed image: #{@original}" unless @target
72   - block.call @target
73   - end
74   -
75   - include Filters::Scale, Filters::Color, Filters::Watermark, Filters::Quality, Filters::Perspective, Filters::Effects
76   -
77   - private
78   -
79   - def create_core_image_context(width, height)
80   - output = OSX::NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel(nil, width, height, 8, 4, true, false, OSX::NSDeviceRGBColorSpace, 0, 0)
81   - context = OSX::NSGraphicsContext.graphicsContextWithBitmapImageRep(output)
82   - OSX::NSGraphicsContext.setCurrentContext(context)
83   - @ci_context = context.CIContext
84   - end
85   -
86   - def vector(x, y, w, h)
87   - OSX::CIVector.vectorWithX_Y_Z_W(x, y, w, h)
88   - end
89   - end
90   - end
91   -end
92   -
93   -module OSX
94   - class CIImage
95   - include OCObjWrapper
96   -
97   - def method_missing_with_filter_processing(sym, *args, &block)
98   - f = OSX::CIFilter.filterWithName("CI#{sym.to_s.camelize}")
99   - return method_missing_without_filter_processing(sym, *args, &block) unless f
100   -
101   - f.setDefaults if f.respond_to? :setDefaults
102   - f.setValue_forKey(self, 'inputImage')
103   - options = args.last.is_a?(Hash) ? args.last : {}
104   - options.each { |k, v| f.setValue_forKey(v, k.to_s) }
105   -
106   - block.call f.valueForKey('outputImage')
107   - end
108   -
109   - alias_method_chain :method_missing, :filter_processing
110   -
111   - def save(target, format = OSX::NSJPEGFileType, properties = nil)
112   - bitmapRep = OSX::NSBitmapImageRep.alloc.initWithCIImage(self)
113   - blob = bitmapRep.representationUsingType_properties(format, properties)
114   - blob.writeToFile_atomically(target, false)
115   - end
116   -
117   - def self.from(filepath)
118   - raise Errno::ENOENT, "No such file or directory - #{filepath}" unless File.exists?(filepath)
119   - OSX::CIImage.imageWithContentsOfURL(OSX::NSURL.fileURLWithPath(filepath))
120   - end
121   - end
122   -end
123   -
vendor/plugins/pothoven-attachment_fu/CHANGELOG 0 → 100644
... ... @@ -0,0 +1,84 @@
  1 +* Aug 22, 2013 *
  2 +* Added cache-control header option and Ruby 1.9 fix for S3 from tricycle
  3 +
  4 +* Aug 21, 2013 *
  5 +* Added S3 :encrypted_storage option support from cschulte22
  6 +
  7 +* Jul 5, 2013
  8 +* Pull in changes from lchimonji10 to reformat README to RDoc format
  9 +
  10 +* Apr 10, 2013 *
  11 +* Ruby 2 compatibility fix
  12 +* Removed some lingering occurrences of RAILS_ROOT and RAILS_ENV
  13 +* clean up of gemspec file
  14 +* no longer package unnecessary files like the test files
  15 +
  16 +* Mar 12, 2013 *
  17 +* Pull in changes from https://github.com/aalong/attachment_fu to use Ruby 1.9.2 Tempfile naming strategy to fix conflicts with Sprockets (see https://github.com/aalong/attachment_fu/commit/938ec3b8597fbf82b1de8c98de12c4688463450a)
  18 +
  19 +* Feb 19, 2013 *
  20 +* Pull in changes from https://github.com/itkin/attachment_fu fork to fix mini magick
  21 +
  22 +* Nov 15, 2012 *
  23 +* Removed 'crop:' option as already included when prefixing geometry with a 'c'. Add note to docs.
  24 +* Added option to sharpen resized images ':sharpen_on_resize'
  25 +
  26 +* Oct 26, 2012 *
  27 +* Merged with https://github.com/tdd/attachment_fu fork to include GEM support for use in Rails 3.2, and bumped version to 3.2.x to indicate Rails 3.2 support.
  28 +
  29 +* Oct 25, 2012 *
  30 +* Fix to support Ruby 1.9.3
  31 +* Image cropping support (append 'crop:' to desired file size when resizing)
  32 +
  33 +* Mar 15, 2010 *
  34 +* Added a symbol syntax for parent-type-based size spec: calls the corresponding method on the current asset instance to
  35 + get a Hash of required thumbnails. Lets us dynamically specify what would otherwise be hard-coded, which is useful
  36 + when the set of thumbnails for a given parent type varies depending on the usage context.
  37 +
  38 +* Aug 6, 2009 *
  39 +* JPEG quality control finalized across processors (although CoreImage applies it in a rather fuzzy-logic way), with tests.
  40 +
  41 +* Aug 4, 2009 *
  42 +* Supports the :aspect/'!' geometry flag in all processors
  43 + (thanks to http://www.deepcalm.com/writing/cropped-thumbnails-in-attachment_fu-using-imagescience)
  44 +* JPEG quality control on thumbnailing/resizing (still buggy on Rmagick/MiniMagick though).
  45 +* Moves from GIF to PNG regardless of the source file extension's case (used to require lowercase)
  46 +* Auto-orients image (if EXIF suggests it) prior to processing with RMagickProcessor
  47 +* Fixes non-image upload tests (both regular files and Merb files)
  48 +* Fixes obsolete failures on RMagick tests (aspect_ratio tested but not initialized anymore due to new callback architecture
  49 +
  50 +* Apr 17 2008 *
  51 +* amazon_s3.yml is now passed through ERB before being passed to AWS::S3 [François Beausoleil]
  52 +
  53 +* Mar 22 2008 *
  54 +* Some tweaks to support Rails 2.0 and Rails 2.1 due to ActiveSupport::Callback changes.
  55 + Thanks to http://blog.methodmissing.com/2008/1/19/edge-callback-refactorings-attachment_fu/
  56 +
  57 +* Feb. 26, 2008 *
  58 +* remove breakpoint from test_helper, makes test suite crazy (at least Rails 2+) [Rob Sanheim]
  59 +* make S3 test really optional [Rob Sanheim]
  60 +
  61 +* Nov 27, 2007 *
  62 +* Handle properly ImageScience thumbnails resized from a gif file [Matt Aimonetti]
  63 +* Save thumbnails file size properly when using ImageScience [Matt Aimonetti]
  64 +* fixed s3 config file loading with latest versions of Rails [Matt Aimonetti]
  65 +
  66 +* April 2, 2007 *
  67 +
  68 +* don't copy the #full_filename to the default #temp_paths array if it doesn't exist
  69 +* add default ID partitioning for attachments
  70 +* add #binmode call to Tempfile (note: ruby should be doing this!) [Eric Beland]
  71 +* Check for current type of :thumbnails option.
  72 +* allow customization of the S3 configuration file path with the :s3_config_path option.
  73 +* Don't try to remove thumbnails if there aren't any. Closes #3 [ben stiglitz]
  74 +
  75 +* BC * (before changelog)
  76 +
  77 +* add default #temp_paths entry [mattly]
  78 +* add MiniMagick support to attachment_fu [Isacc]
  79 +* update #destroy_file to clear out any empty directories too [carlivar]
  80 +* fix references to S3Backend module [Hunter Hillegas]
  81 +* make #current_data public with db_file and s3 backends [ebryn]
  82 +* oops, actually svn add the files for s3 backend. [Jeffrey Hardy]
  83 +* experimental s3 support, egad, no tests.... [Jeffrey Hardy]
  84 +* doh, fix a few bad references to ActsAsAttachment [sixty4bit]
... ...
vendor/plugins/pothoven-attachment_fu/Gemfile 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +source 'http://rubygems.org'
  2 +
  3 +
  4 +group :test, :development do
  5 + gem 'rails', '~> 3.2'
  6 + gem 'sqlite3'
  7 + gem 'pothoven-attachment_fu', :path => '.'
  8 + gem 'rmagick'
  9 + gem 'core_image'
  10 + gem 'mini_magick'
  11 + gem 'aws-s3', :require => 'aws/s3'
  12 + gem 'test-unit'
  13 +end
... ...
vendor/plugins/pothoven-attachment_fu/Gemfile.lock 0 → 100644
... ... @@ -0,0 +1,109 @@
  1 +PATH
  2 + remote: .
  3 + specs:
  4 + pothoven-attachment_fu (3.2.10)
  5 +
  6 +GEM
  7 + remote: http://rubygems.org/
  8 + specs:
  9 + actionmailer (3.2.14)
  10 + actionpack (= 3.2.14)
  11 + mail (~> 2.5.4)
  12 + actionpack (3.2.14)
  13 + activemodel (= 3.2.14)
  14 + activesupport (= 3.2.14)
  15 + builder (~> 3.0.0)
  16 + erubis (~> 2.7.0)
  17 + journey (~> 1.0.4)
  18 + rack (~> 1.4.5)
  19 + rack-cache (~> 1.2)
  20 + rack-test (~> 0.6.1)
  21 + sprockets (~> 2.2.1)
  22 + activemodel (3.2.14)
  23 + activesupport (= 3.2.14)
  24 + builder (~> 3.0.0)
  25 + activerecord (3.2.14)
  26 + activemodel (= 3.2.14)
  27 + activesupport (= 3.2.14)
  28 + arel (~> 3.0.2)
  29 + tzinfo (~> 0.3.29)
  30 + activeresource (3.2.14)
  31 + activemodel (= 3.2.14)
  32 + activesupport (= 3.2.14)
  33 + activesupport (3.2.14)
  34 + i18n (~> 0.6, >= 0.6.4)
  35 + multi_json (~> 1.0)
  36 + arel (3.0.2)
  37 + aws-s3 (0.6.3)
  38 + builder
  39 + mime-types
  40 + xml-simple
  41 + builder (3.0.4)
  42 + core_image (0.0.3.5)
  43 + erubis (2.7.0)
  44 + hike (1.2.3)
  45 + i18n (0.6.5)
  46 + journey (1.0.4)
  47 + json (1.8.0)
  48 + mail (2.5.4)
  49 + mime-types (~> 1.16)
  50 + treetop (~> 1.4.8)
  51 + mime-types (1.24)
  52 + mini_magick (3.6.0)
  53 + subexec (~> 0.2.1)
  54 + multi_json (1.7.9)
  55 + polyglot (0.3.3)
  56 + rack (1.4.5)
  57 + rack-cache (1.2)
  58 + rack (>= 0.4)
  59 + rack-ssl (1.3.3)
  60 + rack
  61 + rack-test (0.6.2)
  62 + rack (>= 1.0)
  63 + rails (3.2.14)
  64 + actionmailer (= 3.2.14)
  65 + actionpack (= 3.2.14)
  66 + activerecord (= 3.2.14)
  67 + activeresource (= 3.2.14)
  68 + activesupport (= 3.2.14)
  69 + bundler (~> 1.0)
  70 + railties (= 3.2.14)
  71 + railties (3.2.14)
  72 + actionpack (= 3.2.14)
  73 + activesupport (= 3.2.14)
  74 + rack-ssl (~> 1.3.2)
  75 + rake (>= 0.8.7)
  76 + rdoc (~> 3.4)
  77 + thor (>= 0.14.6, < 2.0)
  78 + rake (10.1.0)
  79 + rdoc (3.12.2)
  80 + json (~> 1.4)
  81 + rmagick (2.13.2)
  82 + sprockets (2.2.2)
  83 + hike (~> 1.2)
  84 + multi_json (~> 1.0)
  85 + rack (~> 1.0)
  86 + tilt (~> 1.1, != 1.3.0)
  87 + sqlite3 (1.3.8)
  88 + subexec (0.2.3)
  89 + test-unit (2.5.5)
  90 + thor (0.18.1)
  91 + tilt (1.4.1)
  92 + treetop (1.4.15)
  93 + polyglot
  94 + polyglot (>= 0.3.1)
  95 + tzinfo (0.3.37)
  96 + xml-simple (1.1.2)
  97 +
  98 +PLATFORMS
  99 + ruby
  100 +
  101 +DEPENDENCIES
  102 + aws-s3
  103 + core_image
  104 + mini_magick
  105 + pothoven-attachment_fu!
  106 + rails (~> 3.2)
  107 + rmagick
  108 + sqlite3
  109 + test-unit
... ...
vendor/plugins/pothoven-attachment_fu/LICENSE 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +Copyright (c) 2009 rick olson
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining
  4 +a copy of this software and associated documentation files (the
  5 +"Software"), to deal in the Software without restriction, including
  6 +without limitation the rights to use, copy, modify, merge, publish,
  7 +distribute, sublicense, and/or sell copies of the Software, and to
  8 +permit persons to whom the Software is furnished to do so, subject to
  9 +the following conditions:
  10 +
  11 +The above copyright notice and this permission notice shall be
  12 +included in all copies or substantial portions of the Software.
  13 +
  14 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  18 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  19 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  20 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
... ...
vendor/plugins/pothoven-attachment_fu/README 0 → 100644
... ... @@ -0,0 +1,193 @@
  1 +attachment-fu
  2 +=============
  3 +
  4 +attachment_fu is a plugin by Rick Olson (aka technoweenie <http://techno-weenie.net>) and is the successor to acts_as_attachment. To get a basic run-through of its capabilities, check out Mike Clark's tutorial <http://clarkware.com/cgi/blosxom/2007/02/24#FileUploadFu>.
  5 +
  6 +
  7 +attachment_fu functionality
  8 +===========================
  9 +
  10 +attachment_fu facilitates file uploads in Ruby on Rails. There are a few storage options for the actual file data, but the plugin always at a minimum stores metadata for each file in the database.
  11 +
  12 +There are four storage options for files uploaded through attachment_fu:
  13 + File system
  14 + Database file
  15 + Amazon S3
  16 + Rackspace (Mosso) Cloud Files
  17 +
  18 +Each method of storage many options associated with it that will be covered in the following section. Something to note, however, is that the Amazon S3 storage requires you to modify config/amazon_s3.yml, the Rackspace Cloud Files storage requires you to modify config/rackspace_cloudfiles.yml, and the Database file storage requires an extra table.
  19 +
  20 +
  21 +attachment_fu models
  22 +====================
  23 +
  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 +
  26 +In the model there are two methods made available by this plugins: has_attachment and validates_as_attachment.
  27 +
  28 +has_attachment(options = {})
  29 + This method accepts the options in a hash:
  30 + :content_type # Allowed content types.
  31 + # Allows all by default. Use :image to allow all standard image types.
  32 + :min_size # Minimum size allowed.
  33 + # 1 byte is the default.
  34 + :max_size # Maximum size allowed.
  35 + # 1.megabyte is the default.
  36 + :size # Range of sizes allowed.
  37 + # (1..1.megabyte) is the default. This overrides the :min_size and :max_size options.
  38 + :resize_to # Used by RMagick to resize images.
  39 + # Pass either an array of width/height, or a geometry string.
  40 + :thumbnails # Specifies a set of thumbnails to generate.
  41 + # This accepts a hash of filename suffixes and RMagick resizing options.
  42 + # This option need only be included if you want thumbnailing.
  43 + :thumbnail_class # Set which model class to use for thumbnails.
  44 + # This current attachment class is used by default.
  45 + :path_prefix # Path to store the uploaded files in.
  46 + # Uses public/#{table_name} by default for the filesystem, and just #{table_name} for the S3 and Cloud Files backend.
  47 + # Setting this sets the :storage to :file_system.
  48 + :partition # Whether to partiton files in directories like /0000/0001/image.jpg. Default is true. Only applicable to the :file_system backend.
  49 + :storage # Specifies the storage system to use..
  50 + # Defaults to :db_file. Options are :file_system, :db_file, :s3, and :cloud_files.
  51 + :cloudfront # If using S3 for storage, this option allows for serving the files via Amazon CloudFront.
  52 + # Defaults to false.
  53 + :processor # Sets the image processor to use for resizing of the attached image.
  54 + # Options include ImageScience, Rmagick, and MiniMagick. Default is whatever is installed.
  55 + :uuid_primary_key # If your model's primary key is a 128-bit UUID in hexadecimal format, then set this to true.
  56 + :association_options # attachment_fu automatically defines associations with thumbnails with has_many and belongs_to. If there are any additional options that you want to pass to these methods, then specify them here.
  57 +
  58 +
  59 + Examples:
  60 + has_attachment :max_size => 1.kilobyte
  61 + has_attachment :size => 1.megabyte..2.megabytes
  62 + has_attachment :content_type => 'application/pdf'
  63 + has_attachment :content_type => ['application/pdf', 'application/msword', 'text/plain']
  64 + has_attachment :content_type => :image, :resize_to => [50,50]
  65 + has_attachment :content_type => ['application/pdf', :image], :resize_to => 'x50'
  66 + has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
  67 + has_attachment :storage => :file_system, :path_prefix => 'public/files'
  68 + has_attachment :storage => :file_system, :path_prefix => 'public/files',
  69 + :content_type => :image, :resize_to => [50,50], :partition => false
  70 + has_attachment :storage => :file_system, :path_prefix => 'public/files',
  71 + :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
  72 + has_attachment :storage => :s3
  73 + has_attachment :store => :s3, :cloudfront => true
  74 + has_attachment :storage => :cloud_files
  75 +
  76 +validates_as_attachment
  77 + 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.
  78 +
  79 + Example:
  80 + validates_as_attachment
  81 +
  82 +
  83 +attachment_fu migrations
  84 +========================
  85 +
  86 +Fields for attachment_fu metadata tables...
  87 + in general:
  88 + size, :integer # file size in bytes
  89 + content_type, :string # mime type, ex: application/mp3
  90 + filename, :string # sanitized filename
  91 + that reference images:
  92 + height, :integer # in pixels
  93 + width, :integer # in pixels
  94 + that reference images that will be thumbnailed:
  95 + parent_id, :integer # id of parent image (on the same table, a self-referencing foreign-key).
  96 + # Only populated if the current object is a thumbnail.
  97 + thumbnail, :string # the 'type' of thumbnail this attachment record describes.
  98 + # Only populated if the current object is a thumbnail.
  99 + # Usage:
  100 + # [ In Model 'Avatar' ]
  101 + # has_attachment :content_type => :image,
  102 + # :storage => :file_system,
  103 + # :max_size => 500.kilobytes,
  104 + # :resize_to => '320x200>',
  105 + # :thumbnails => { :small => '10x10>',
  106 + # :thumb => '100x100>' }
  107 + # [ Elsewhere ]
  108 + # @user.avatar.thumbnails.first.thumbnail #=> 'small'
  109 + that reference files stored in the database (:db_file):
  110 + db_file_id, :integer # id of the file in the database (foreign key)
  111 +
  112 +Field for attachment_fu db_files table:
  113 + data, :binary # binary file data, for use in database file storage
  114 +
  115 +
  116 +attachment_fu views
  117 +===================
  118 +
  119 +There are two main views tasks that will be directly affected by attachment_fu: upload forms and displaying uploaded images.
  120 +
  121 +There are two parts of the upload form that differ from typical usage.
  122 + 1. Include ':multipart => true' in the html options of the form_for tag.
  123 + Example:
  124 + <% form_for(:attachment_metadata, :url => { :action => "create" }, :html => { :multipart => true }) do |form| %>
  125 +
  126 + 2. Use the file_field helper with :uploaded_data as the field name.
  127 + Example:
  128 + <%= form.file_field :uploaded_data %>
  129 +
  130 +Displaying uploaded images is made easy by the public_filename method of the ActiveRecord attachment objects using file system, s3, and Cloud Files storage.
  131 +
  132 +public_filename(thumbnail = nil)
  133 + Returns the public path to the file. If a thumbnail prefix is specified it will return the public file path to the corresponding thumbnail.
  134 + Examples:
  135 + attachment_obj.public_filename #=> /attachments/2/file.jpg
  136 + attachment_obj.public_filename(:thumb) #=> /attachments/2/file_thumb.jpg
  137 + attachment_obj.public_filename(:small) #=> /attachments/2/file_small.jpg
  138 +
  139 +When serving files from database storage, doing more than simply downloading the file is beyond the scope of this document.
  140 +
  141 +
  142 +attachment_fu controllers
  143 +=========================
  144 +
  145 +There are two considerations to take into account when using attachment_fu in controllers.
  146 +
  147 +The first is when the files have no publicly accessible path and need to be downloaded through an action.
  148 +
  149 +Example:
  150 + def readme
  151 + send_file '/path/to/readme.txt', :type => 'plain/text', :disposition => 'inline'
  152 + end
  153 +
  154 +See the possible values for send_file for reference.
  155 +
  156 +
  157 +The second is when saving the file when submitted from a form.
  158 +Example in view:
  159 + <%= form.file_field :attachable, :uploaded_data %>
  160 +
  161 +Example in controller:
  162 + def create
  163 + @attachable_file = AttachmentMetadataModel.new(params[:attachable])
  164 + if @attachable_file.save
  165 + flash[:notice] = 'Attachment was successfully created.'
  166 + redirect_to attachable_url(@attachable_file)
  167 + else
  168 + render :action => :new
  169 + end
  170 + end
  171 +
  172 +attachement_fu scripting
  173 +====================================
  174 +
  175 +You may wish to import a large number of images or attachments.
  176 +The following example shows how to upload a file from a script.
  177 +
  178 +#!/usr/bin/env ./script/runner
  179 +
  180 +# required to use ActionController::TestUploadedFile
  181 +require 'action_controller'
  182 +require 'action_controller/test_process.rb'
  183 +
  184 +path = "./public/images/x.jpg"
  185 +
  186 +# mimetype is a string like "image/jpeg". One way to get the mimetype for a given file on a UNIX system
  187 +# mimetype = `file -ib #{path}`.gsub(/\n/,"")
  188 +
  189 +mimetype = "image/jpeg"
  190 +
  191 +# This will "upload" the file at path and create the new model.
  192 +@attachable = AttachmentMetadataModel.new(:uploaded_data => ActionController::TestUploadedFile.new(path, mimetype))
  193 +@attachable.save
... ...
vendor/plugins/pothoven-attachment_fu/README.rdoc 0 → 100644
... ... @@ -0,0 +1,352 @@
  1 += attachment-fu
  2 +
  3 +attachment_fu is a plugin by Rick Olson (aka technoweenie
  4 +http://techno-weenie.net) and is the successor to acts_as_attachment. To get a
  5 +basic run-through of its capabilities, check out {Mike Clark's
  6 +tutorial}[http://clarkware.com/cgi/blosxom/2007/02/24#FileUploadFu].
  7 +
  8 += attachment_fu functionality
  9 +
  10 +attachment_fu facilitates file uploads in Ruby on Rails. There are a few
  11 +storage options for the actual file data, but the plugin always at a minimum
  12 +stores metadata for each file in the database.
  13 +
  14 +There are four storage options for files uploaded through attachment_fu:
  15 +
  16 +* File system
  17 +* Database file
  18 +* Amazon S3
  19 +* Rackspace (Mosso) Cloud Files
  20 +
  21 +Each method of storage many options associated with it that will be covered in
  22 +the following section. Something to note, however, is that the Amazon S3 storage
  23 +requires you to modify +config/amazon_s3.yml+, the Rackspace Cloud Files storage
  24 +requires you to modify +config/rackspace_cloudfiles.yml+, and the Database file
  25 +storage requires an extra table.
  26 +
  27 += attachment_fu models
  28 +
  29 +For all three of these storage options a table of metadata is required. This
  30 +table will contain information about the file (hence the 'meta') and its
  31 +location. This table has no restrictions on naming, unlike the extra table
  32 +required for database storage, which must have a table name of +db_files+ (and
  33 +by convention a model of +DbFile+).
  34 +
  35 +Two methods are available to models: +has_attachment+ and
  36 ++validates_as_attachment+.
  37 +
  38 +== has_attachment(options = {})
  39 +
  40 +This method accepts the options in a hash:
  41 +
  42 +[:content_type]
  43 + Allowed content types.
  44 +
  45 + By default, all content types are allowed. Use +:image+ to allow all
  46 + standard image types.
  47 +
  48 +[:min_size]
  49 + Minimum file size.
  50 +
  51 + By default, set to +1.byte+.
  52 +
  53 +[:max_size]
  54 + Maximum file size.
  55 +
  56 + By default, set to +1.megabyte+.
  57 +
  58 +[:size]
  59 + Minimum and maximum file size.
  60 +
  61 + By default, set to +1..1.megabyte+. Overrides +:min_size+ and
  62 + +:max_size+.
  63 +
  64 +[:resize_to]
  65 + Used by RMagick.
  66 +
  67 + Tells RMagick how to resize images. Pass either an array specifying
  68 + width and height or a geometry string. Prefixing the geometry string
  69 + with a 'c' will crop the image to the specified size.
  70 +
  71 +[:sharpen_on_resize]
  72 + Used by RMagick.
  73 +
  74 + If set to true, images are sharpened after being resized.
  75 +
  76 +[:thumbnails]
  77 + A set of thumbnails to generate.
  78 +
  79 + This accepts a hash of filename suffixes and RMagick resizing options. This
  80 + option need only be included if you want thumbnailing.
  81 +
  82 + If you have a polymorphic parent relationship, you can provide
  83 + parent-type-specific thumbnail settings by using a pair with the type string
  84 + as key and a Hash of thumbnail definitions, or a method symbol, as value.
  85 + The method symbol will call the named method in order to get a
  86 + dynamically-built Hash of thumbnail definitions, which gives you full
  87 + flexibility. AttachmentFu automatically detects your first polymorphic
  88 + +belongs_to+ relationship.
  89 +
  90 +[:thumbnail_class]
  91 + Which model class to use for thumbnails.
  92 +
  93 + By default, the current attachment class is used.
  94 +
  95 +[:jpeg_quality]
  96 + JPEG quality settings for thumbnail resizes.
  97 +
  98 + Arguments can be in multiple formats:
  99 +
  100 + * Integer from 0 (basically crap) to 100 (basically lossless, fat files).
  101 +
  102 + * When relying on tdd-image_science, you can also use one of its +JPEG_xxx+
  103 + constants for predefined ratios/settings.
  104 +
  105 + * You can also use a Hash, with keys being either thumbnail symbols (I
  106 + repeat: _symbols_) or surface boundaries. A surface boundary is a string
  107 + starting with either '<' or '>=', followed by a number of pixels. This
  108 + lets you specify per-thumbnail or per-general-thumbnail-"size" JPEG
  109 + qualities. (which can be useful when you have a _lot_ of thumbnail
  110 + options). Surface example: <code>{'<2000' => 90, '>=2000' => 75}</code>.
  111 +
  112 + Defaults vary depending on the processor (ImageScience: 100%,
  113 + Rmagick/MiniMagick/Gd2: 75%, CoreImage: auto-adjust). Note that only
  114 + tdd-image_science (available from GitHub) currently supports explicit JPEG
  115 + quality; the default image_science currently forces 100%.
  116 +
  117 +[:path_prefix]
  118 + Path to store the uploaded files in. Uses <code>public/#{table_name}</code>
  119 + by default for the filesystem, and just <code>#{table_name}</code> for the
  120 + S3 and Cloud Files backend. Setting this sets the +:storage+ to
  121 + +:file_system+.
  122 +
  123 +[:partition]
  124 + Whether to partiton files in directories like +/0000/0001/image.jpg+.
  125 + Default is true. Only applicable to the +:file_system+ backend.
  126 +
  127 +[:storage]
  128 + Specifies the storage system to use. Defaults to +:db_file+. Options are
  129 + +:file_system+, +:db_file+, +:s3+, and +:cloud_files+.
  130 +
  131 +[:cloudfront]
  132 + If using S3 for storage, this option allows for serving the files via Amazon
  133 + CloudFront. Defaults to false.
  134 +
  135 +[:processor]
  136 + Sets the image processor to use for resizing of the attached image. Options
  137 + include ImageScience, Rmagick, MiniMagick, Gd2 and CoreImage. Default is
  138 + whatever is installed.
  139 +
  140 +[:uuid_primary_key]
  141 + If your model's primary key is a 128-bit UUID in hexadecimal format, then
  142 + set this to true.
  143 +
  144 +[:association_options]
  145 + attachment_fu automatically defines associations with thumbnails with
  146 + +has_many+ and +belongs_to+. If there are any additional options that you
  147 + want to pass to these methods, then specify them here.
  148 +
  149 +Examples:
  150 +
  151 + has_attachment(content_type: 'application/pdf')
  152 + has_attachment(
  153 + content_type: ['application/pdf', 'application/msword', 'text/plain']
  154 + )
  155 + has_attachment(content_type: ['application/pdf', :image], resize_to: 'x50')
  156 + has_attachment(content_type: :image, resize_to: [50,50])
  157 + has_attachment(max_size: 1.kilobyte)
  158 + has_attachment(size: 1.megabyte..2.megabytes)
  159 + has_attachment(storage: :cloud_files)
  160 + has_attachment(storage: :file_system, path_prefix: 'public/files')
  161 + has_attachment(
  162 + storage: :file_system,
  163 + path_prefix: 'public/files',
  164 + content_type: :image,
  165 + resize_to: [50, 50],
  166 + partition: false
  167 + )
  168 + has_attachment(
  169 + storage: :file_system,
  170 + path_prefix: 'public/files',
  171 + thumbnails: {thumb: [50, 50], geometry: 'x50'}
  172 + )
  173 + has_attachment(storage: :s3)
  174 + has_attachment(store: :s3, cloudfront: true)
  175 + has_attachment(thumbnails: {thumb: [50, 50], geometry: 'x50'})
  176 +
  177 + # Let's say we have a polymorphic belongs_to, e.g. called 'imageable', where
  178 + # imageable_type (or whatever the :foreign_type option was set to) can be,
  179 + # among other things, 'Product', 'User' or 'Editorial', each of which should
  180 + # have extra thumbnails:
  181 +
  182 + has_attachment(thumbnails: {
  183 + editorials: {fullsize: '150x100>'},
  184 + geometry: 'x50',
  185 + products: {large_thumb: '169x169!', zoomed: '500x500>'},
  186 + thumb: [50, 50],
  187 + users: {avatar: '64x64!'}
  188 + })
  189 +
  190 + # JPEG qualities…
  191 +
  192 + has_attachment(jpeg_quality: 75)
  193 + has_attachment(jpeg_quality: 80 | ImageScience::JPEG_PROGRESSIVE)
  194 + has_attachment(
  195 + thumbnails: {thumb: [50, 50], geometry: 'x50'},
  196 + jpeg_quality: {'<2000' => 90, '>=2000' => 75}
  197 + )
  198 + has_attachment(
  199 + thumbnails: {thumb: [50, 50], geometry: 'x50'},
  200 + jpeg_quality: {nil => 75, thumb: 90, geometry: 90}
  201 + )
  202 +
  203 +== validates_as_attachment
  204 +
  205 +This method prevents files outside of the valid range (+:min_size+ to
  206 ++:max_size+, or the +:size+ range) from being saved. It does not however, halt
  207 +the upload of such files. They will be uploaded into memory regardless of size
  208 +before validation.
  209 +
  210 +To perform this validation, simply add +validates_as_attachment+ to your model.
  211 +
  212 += attachment_fu migrations
  213 +
  214 +Fields for attachment_fu metadata tables…
  215 +
  216 +In general:
  217 +
  218 + size, :integer # file size in bytes
  219 + content_type, :string # mime type, ex: application/mp3
  220 + filename, :string # sanitized filename
  221 +
  222 +That reference images:
  223 +
  224 + height, :integer # in pixels
  225 + width, :integer # in pixels
  226 +
  227 +That reference images that will be thumbnailed:
  228 +
  229 + parent_id, :integer # id of parent image (on the same table, a
  230 + # self-referencing foreign-key). Only populated if
  231 + # the current object is a thumbnail.
  232 + thumbnail, :string # The type of thumbnail this attachment record
  233 + # describes. Only populated if the current object is
  234 + # a thumbnail. Example:
  235 + #
  236 + # (In Model 'Avatar')
  237 + # has_attachment(
  238 + # :content_type => :image,
  239 + # :storage => :file_system,
  240 + # :max_size => 500.kilobytes,
  241 + # :resize_to => '320x200>',
  242 + # :thumbnails => {
  243 + # :small => '10x10>',
  244 + # :thumb => '100x100>'
  245 + # }
  246 + # )
  247 + #
  248 + # (Elsewhere)
  249 + # @user.avatar.thumbnails.first.thumbnail # => 'small'
  250 + #
  251 + db_file_id, :integer # ID of the file in the database (foreign key) that
  252 + # reference files stored in the database (:db_file).
  253 +
  254 +Field for attachment_fu +db_files+ table:
  255 +
  256 + data, :binary # binary file data, for use in database file storage
  257 +
  258 += attachment_fu views
  259 +
  260 +There are two main views tasks that will be directly affected by attachment_fu:
  261 +upload forms and displaying uploaded images.
  262 +
  263 +There are two parts of the upload form that differ from typical usage.
  264 +
  265 +1. Include <code>multipart: true</code> in the html options of the +form_for+
  266 + tag. Example:
  267 +
  268 + <%=
  269 + form_for(
  270 + :attachment_metadata,
  271 + url: {action: "create"},
  272 + html: {multipart: true}
  273 + ) do |form|
  274 + %>
  275 +
  276 +2. Use the +file_field+ helper with +:uploaded_data+ as the field name. Example:
  277 +
  278 + <%= form.file_field(:uploaded_data) %>
  279 +
  280 +Displaying uploaded images is made easy by the +public_filename+ method of the
  281 +ActiveRecord attachment objects using file system, s3, and Cloud Files storage.
  282 +
  283 +== public_filename(thumbnail = nil)
  284 +
  285 +Returns the public path to the file. If a thumbnail prefix is specified it will
  286 +return the public file path to the corresponding thumbnail. Examples:
  287 +
  288 + attachment_obj.public_filename #=> /attachments/2/file.jpg
  289 + attachment_obj.public_filename(:thumb) #=> /attachments/2/file_thumb.jpg
  290 + attachment_obj.public_filename(:small) #=> /attachments/2/file_small.jpg
  291 +
  292 +When serving files from database storage, doing more than simply downloading the
  293 +file is beyond the scope of this document.
  294 +
  295 += attachment_fu controllers
  296 +
  297 +There are two considerations to take into account when using attachment_fu in
  298 +controllers.
  299 +
  300 +The first is when the files have no publicly accessible path and need to be
  301 +downloaded through an action. Example:
  302 +
  303 + def readme
  304 + send_file(
  305 + '/path/to/readme.txt',
  306 + type: 'plain/text',
  307 + disposition: 'inline'
  308 + )
  309 + end
  310 +
  311 +See the possible values for +send_file+ for reference.
  312 +
  313 +The second is when saving the file when submitted from a form. Example:
  314 +
  315 +In a view:
  316 +
  317 + <%= form.file_field(:attachable, :uploaded_data) %>
  318 +
  319 +In a controller:
  320 +
  321 + def create
  322 + @attachable_file = AttachmentMetadataModel.new(params[:attachable])
  323 + if @attachable_file.save
  324 + flash[:notice] = 'Attachment was successfully created.'
  325 + redirect_to(attachable_url(@attachable_file))
  326 + else
  327 + redirect_to(action: 'new')
  328 + end
  329 + end
  330 +
  331 += attachment_fu scripting
  332 +
  333 +You may wish to import a large number of images or attachments. The following
  334 +example shows how to upload a file from a script.
  335 +
  336 + #!/usr/bin/env ./script/runner
  337 +
  338 + # required to use ActionController::TestUploadedFile
  339 + require 'action_controller'
  340 + require 'action_controller/test_process.rb'
  341 +
  342 + path = "./public/images/x.jpg"
  343 +
  344 + # `mimetype` is a string like "image/jpeg". One way to get the mimetype for
  345 + # a given file on a UNIX system: mimetype = `file -ib #{path}`.gsub(/\n/,"")
  346 + mimetype = "image/jpeg"
  347 +
  348 + # This will "upload" the file at path and create the new model.
  349 + @attachable = AttachmentMetadataModel.new(
  350 + uploaded_data: ActionController::TestUploadedFile.new(path, mimetype)
  351 + )
  352 + @attachable.save
... ...
vendor/plugins/pothoven-attachment_fu/Rakefile 0 → 100644
... ... @@ -0,0 +1,22 @@
  1 +require 'rake'
  2 +require 'rake/testtask'
  3 +require 'rdoc/task'
  4 +
  5 +desc 'Default: run unit tests.'
  6 +task :default => :test
  7 +
  8 +desc 'Test the attachment_fu plugin.'
  9 +Rake::TestTask.new(:test) do |t|
  10 + t.libs << 'lib'
  11 + t.pattern = 'test/**/*_test.rb'
  12 + t.verbose = true
  13 +end
  14 +
  15 +desc 'Generate documentation for the attachment_fu plugin.'
  16 +Rake::RDocTask.new(:rdoc) do |rdoc|
  17 + rdoc.rdoc_dir = 'rdoc'
  18 + rdoc.title = 'ActsAsAttachment'
  19 + rdoc.options << '--line-numbers --inline-source'
  20 + rdoc.rdoc_files.include('README.rdoc')
  21 + rdoc.rdoc_files.include('lib/**/*.rb')
  22 +end
... ...
vendor/plugins/pothoven-attachment_fu/amazon_s3.yml.tpl 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +development:
  2 + bucket_name: appname_development
  3 + access_key_id:
  4 + secret_access_key:
  5 + distribution_domain: XXXX.cloudfront.net
  6 +
  7 +test:
  8 + bucket_name: appname_test
  9 + access_key_id:
  10 + secret_access_key:
  11 + distribution_domain: XXXX.cloudfront.net
  12 +
  13 +production:
  14 + bucket_name: appname
  15 + access_key_id:
  16 + secret_access_key:
  17 + distribution_domain: XXXX.cloudfront.net
... ...
vendor/plugins/pothoven-attachment_fu/attachment_fu.gemspec 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +# -*- encoding: utf-8 -*-
  2 +
  3 +Gem::Specification.new do |s|
  4 + s.name = %q{pothoven-attachment_fu}
  5 + s.authors = ["Rick Olson", "Steven Pothoven"]
  6 + s.summary = %q{attachment_fu as a gem}
  7 + s.description = %q{This is a fork of Rick Olson's attachment_fu adding Ruby 1.9 and Rails 3.2 support as well as some other enhancements.}
  8 + s.email = %q{steven@pothoven.net}
  9 + s.homepage = %q{http://github.com/pothoven/attachment_fu}
  10 + s.version = "3.2.10"
  11 + s.date = %q{2013-08-22}
  12 +
  13 + s.files = Dir.glob("{lib,vendor}/**/*") + %w( CHANGELOG LICENSE README.rdoc amazon_s3.yml.tpl rackspace_cloudfiles.yml.tpl )
  14 + s.extra_rdoc_files = ["README.rdoc"]
  15 + s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
  16 + s.require_paths = ["lib"]
  17 + s.rubyforge_project = "nowarning"
  18 + s.rubygems_version = %q{1.3.5}
  19 +
  20 + if s.respond_to? :specification_version then
  21 + s.specification_version = 2
  22 + end
  23 +end
... ...
vendor/plugins/pothoven-attachment_fu/config/database.yml 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +test:
  2 + adapter: sqlite3
  3 + database: ":memory:"
... ...
vendor/plugins/pothoven-attachment_fu/config/environment.rb 0 → 100644
vendor/plugins/pothoven-attachment_fu/init.rb 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +require 'geometry'
  2 +ActiveRecord::Base.send(:extend, Technoweenie::AttachmentFu::ActMethods)
  3 +Technoweenie::AttachmentFu.tempfile_path = ATTACHMENT_FU_TEMPFILE_PATH if Object.const_defined?(:ATTACHMENT_FU_TEMPFILE_PATH)
  4 +FileUtils.mkdir_p Technoweenie::AttachmentFu.tempfile_path
  5 +
  6 +$:.unshift(File.dirname(__FILE__) + '/vendor')
... ...
vendor/plugins/pothoven-attachment_fu/install.rb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +require 'fileutils'
  2 +
  3 +s3_config = File.dirname(__FILE__) + '/../../../config/amazon_s3.yml'
  4 +FileUtils.cp File.dirname(__FILE__) + '/amazon_s3.yml.tpl', s3_config unless File.exist?(s3_config)
  5 +cloudfiles_config = File.dirname(__FILE__) + '/../../../config/rackspace_cloudfiles.yml'
  6 +FileUtils.cp File.dirname(__FILE__) + '/rackspace_cloudfiles.yml.tpl', cloudfiles_config unless File.exist?(cloudfiles_config)
  7 +puts IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
... ...
vendor/plugins/pothoven-attachment_fu/lib/geometry.rb 0 → 100644
... ... @@ -0,0 +1,96 @@
  1 +# This Geometry class was yanked from RMagick. However, it lets ImageMagick handle the actual change_geometry.
  2 +# Use #new_dimensions_for to get new dimensions
  3 +# Used so I can use spiffy RMagick geometry strings with ImageScience
  4 +class Geometry
  5 + # @ is removed until support for them is added
  6 + FLAGS = ['', '%', '<', '>', '!']#, '@']
  7 + RFLAGS = { '%' => :percent,
  8 + '!' => :aspect,
  9 + '<' => :>,
  10 + '>' => :<,
  11 + '@' => :area }
  12 +
  13 + attr_accessor :width, :height, :x, :y, :flag
  14 +
  15 + def initialize(width=nil, height=nil, x=nil, y=nil, flag=nil)
  16 + # Support floating-point width and height arguments so Geometry
  17 + # objects can be used to specify Image#density= arguments.
  18 + raise ArgumentError, "width must be >= 0: #{width}" if width < 0
  19 + raise ArgumentError, "height must be >= 0: #{height}" if height < 0
  20 + @width = width.to_f
  21 + @height = height.to_f
  22 + @x = x.to_i
  23 + @y = y.to_i
  24 + @flag = flag
  25 + end
  26 +
  27 + # Construct an object from a geometry string
  28 + RE = /\A(\d*)(?:x(\d+)?)?([-+]\d+)?([-+]\d+)?([%!<>@]?)\Z/
  29 +
  30 + def self.from_s(str)
  31 + raise(ArgumentError, "no geometry string specified") unless str
  32 +
  33 + if m = RE.match(str)
  34 + new(m[1].to_i, m[2].to_i, m[3].to_i, m[4].to_i, RFLAGS[m[5]])
  35 + else
  36 + raise ArgumentError, "invalid geometry format"
  37 + end
  38 + end
  39 +
  40 + # Convert object to a geometry string
  41 + def to_s
  42 + str = ''
  43 + str << "%g" % @width if @width > 0
  44 + str << 'x' if (@width > 0 || @height > 0)
  45 + str << "%g" % @height if @height > 0
  46 + str << "%+d%+d" % [@x, @y] if (@x != 0 || @y != 0)
  47 + str << FLAGS[@flag.to_i]
  48 + end
  49 +
  50 + # attempts to get new dimensions for the current geometry string given these old dimensions.
  51 + # This doesn't implement the aspect flag (!) or the area flag (@). PDI
  52 + def new_dimensions_for(orig_width, orig_height)
  53 + new_width = orig_width
  54 + new_height = orig_height
  55 +
  56 + case @flag
  57 + when :percent
  58 + scale_x = @width.zero? ? 100 : @width
  59 + scale_y = @height.zero? ? @width : @height
  60 + new_width = scale_x.to_f * (orig_width.to_f / 100.0)
  61 + new_height = scale_y.to_f * (orig_height.to_f / 100.0)
  62 + when :aspect
  63 + new_width = @width unless @width.nil?
  64 + new_height = @height unless @height.nil?
  65 + when :<, :>, nil
  66 + scale_factor =
  67 + if new_width.zero? || new_height.zero?
  68 + 1.0
  69 + else
  70 + if @width.nonzero? && @height.nonzero?
  71 + [@width.to_f / new_width.to_f, @height.to_f / new_height.to_f].min
  72 + else
  73 + @width.nonzero? ? (@width.to_f / new_width.to_f) : (@height.to_f / new_height.to_f)
  74 + end
  75 + end
  76 + new_width = scale_factor * new_width.to_f
  77 + new_height = scale_factor * new_height.to_f
  78 + new_width = orig_width if @flag && orig_width.send(@flag, new_width)
  79 + new_height = orig_height if @flag && orig_height.send(@flag, new_height)
  80 + end
  81 +
  82 + [new_width, new_height].collect! { |v| [v.round, 1].max }
  83 + end
  84 +end
  85 +
  86 +class Array
  87 + # allows you to get new dimensions for the current array of dimensions with a given geometry string
  88 + #
  89 + # [50, 64] / '40>' # => [40, 51]
  90 + def /(geometry)
  91 + raise ArgumentError, "Only works with a [width, height] pair" if size != 2
  92 + raise ArgumentError, "Must pass a valid geometry string or object" unless geometry.is_a?(String) || geometry.is_a?(Geometry)
  93 + geometry = Geometry.from_s(geometry) if geometry.is_a?(String)
  94 + geometry.new_dimensions_for first, last
  95 + end
  96 +end
... ...
vendor/plugins/pothoven-attachment_fu/lib/pothoven-attachment_fu.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +class Engine < Rails::Engine
  2 + # Mimic old vendored plugin behavior, attachment_fu/lib is autoloaded.
  3 + config.autoload_paths << File.expand_path("..", __FILE__)
  4 +
  5 + initializer "attachment_fu" do
  6 + require 'geometry'
  7 +
  8 + ActiveRecord::Base.send(:extend, Technoweenie::AttachmentFu::ActMethods)
  9 + Technoweenie::AttachmentFu.tempfile_path = ATTACHMENT_FU_TEMPFILE_PATH if Object.const_defined?(:ATTACHMENT_FU_TEMPFILE_PATH)
  10 + FileUtils.mkdir_p Technoweenie::AttachmentFu.tempfile_path
  11 + end
  12 +end
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu.rb 0 → 100644
... ... @@ -0,0 +1,588 @@
  1 +module Technoweenie # :nodoc:
  2 + module AttachmentFu # :nodoc:
  3 + @@default_processors = %w(ImageScience Rmagick MiniMagick Gd2 CoreImage)
  4 + @@tempfile_path = File.join(Rails.root, 'tmp', 'attachment_fu')
  5 + @@content_types = [
  6 + 'image/jpeg',
  7 + 'image/pjpeg',
  8 + 'image/jpg',
  9 + 'image/gif',
  10 + 'image/png',
  11 + 'image/x-png',
  12 + 'image/jpg',
  13 + 'image/x-ms-bmp',
  14 + 'image/bmp',
  15 + 'image/x-bmp',
  16 + 'image/x-bitmap',
  17 + 'image/x-xbitmap',
  18 + 'image/x-win-bitmap',
  19 + 'image/x-windows-bmp',
  20 + 'image/ms-bmp',
  21 + 'application/bmp',
  22 + 'application/x-bmp',
  23 + 'application/x-win-bitmap',
  24 + 'application/preview',
  25 + 'image/jp_',
  26 + 'application/jpg',
  27 + 'application/x-jpg',
  28 + 'image/pipeg',
  29 + 'image/vnd.swiftview-jpeg',
  30 + 'image/x-xbitmap',
  31 + 'application/png',
  32 + 'application/x-png',
  33 + 'image/gi_',
  34 + 'image/x-citrix-pjpeg'
  35 + ]
  36 + mattr_reader :content_types, :tempfile_path, :default_processors
  37 + mattr_writer :tempfile_path
  38 +
  39 + class ThumbnailError < StandardError; end
  40 + class AttachmentError < StandardError; end
  41 +
  42 + module ActMethods
  43 + # Options:
  44 + # * <tt>:content_type</tt> - Allowed content types. Allows all by default. Use :image to allow all standard image types.
  45 + # * <tt>:min_size</tt> - Minimum size allowed. 1 byte is the default.
  46 + # * <tt>:max_size</tt> - Maximum size allowed. 1.megabyte is the default.
  47 + # * <tt>:size</tt> - Range of sizes allowed. (1..1.megabyte) is the default. This overrides the :min_size and :max_size options.
  48 + # * <tt>:resize_to</tt> - Used by RMagick to resize images. Pass either an array of width/height, or a geometry string. Prefix geometry string with 'c' to crop image, ex. 'c100x100'
  49 + # * <tt>:sharpen_on_resize</tt> - When using RMagick, setting to true will sharpen images after resizing.
  50 + # * <tt>:jpeg_quality</tt> - Used to provide explicit JPEG quality for thumbnail/resize saves. Can have multiple formats:
  51 + # * Integer from 0 (basically crap) to 100 (basically lossless, fat files).
  52 + # * When relying on ImageScience, you can also use one of its +JPEG_xxx+ constants for predefined ratios/settings.
  53 + # * You can also use a Hash, with keys being either thumbnail symbols (I repeat: _symbols_) or surface boundaries.
  54 + # A surface boundary is a string starting with either '<' or '>=', followed by a number of pixels. This lets you
  55 + # specify per-thumbnail or per-general-thumbnail-"size" JPEG qualities. (which can be useful when you have a
  56 + # _lot_ of thumbnail options). Surface example: +{ '<2000' => 90, '>=2000' => 75 }+.
  57 + # Defaults vary depending on the processor (ImageScience: 100%, Rmagick/MiniMagick/Gd2: 75%,
  58 + # CoreImage: auto-adjust). Note that only tdd-image_science (available from GitHub) currently supports explicit JPEG quality;
  59 + # the default image_science currently forces 100%.
  60 + # * <tt>:thumbnails</tt> - Specifies a set of thumbnails to generate. This accepts a hash of filename suffixes and
  61 + # RMagick resizing options. If you have a polymorphic parent relationship, you can provide parent-type-specific
  62 + # thumbnail settings by using a pair with the type string as key and a Hash of thumbnail definitions as value.
  63 + # AttachmentFu automatically detects your first polymorphic +belongs_to+ relationship.
  64 + # * <tt>:thumbnail_class</tt> - Set what class to use for thumbnails. This attachment class is used by default.
  65 + # * <tt>:path_prefix</tt> - path to store the uploaded files. Uses public/#{table_name} by default for the filesystem, and just #{table_name}
  66 + # for the S3 backend. Setting this sets the :storage to :file_system.
  67 +
  68 + # * <tt>:storage</tt> - Use :file_system to specify the attachment data is stored with the file system. Defaults to :db_system.
  69 + # * <tt>:cloundfront</tt> - Set to true if you are using S3 storage and want to serve the files through CloudFront. You will need to
  70 + # set a distribution domain in the amazon_s3.yml config file. Defaults to false
  71 + # * <tt>:bucket_key</tt> - Use this to specify a different bucket key other than :bucket_name in the amazon_s3.yml file. This allows you to use
  72 + # different buckets for different models. An example setting would be :image_bucket and the you would need to define the name of the corresponding
  73 + # bucket in the amazon_s3.yml file.
  74 +
  75 + # * <tt>:keep_profile</tt> By default image EXIF data will be stripped to minimize image size. For small thumbnails this proivides important savings. Picture quality is not affected. Set to false if you want to keep the image profile as is. ImageScience will allways keep EXIF data.
  76 + #
  77 + # Examples:
  78 + # has_attachment :max_size => 1.kilobyte
  79 + # has_attachment :size => 1.megabyte..2.megabytes
  80 + # has_attachment :content_type => 'application/pdf'
  81 + # has_attachment :content_type => ['application/pdf', 'application/msword', 'text/plain']
  82 + # has_attachment :content_type => :image, :resize_to => [50,50]
  83 + # has_attachment :content_type => ['application/pdf', :image], :resize_to => 'x50'
  84 + # has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
  85 + # has_attachment :storage => :file_system, :path_prefix => 'public/files'
  86 + # has_attachment :storage => :file_system, :path_prefix => 'public/files',
  87 + # :content_type => :image, :resize_to => [50,50]
  88 + # has_attachment :storage => :file_system, :path_prefix => 'public/files',
  89 + # :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
  90 + # has_attachment :storage => :s3
  91 + def has_attachment(options = {})
  92 + # this allows you to redefine the acts' options for each subclass, however
  93 + options[:min_size] ||= 1
  94 + options[:max_size] ||= 1.megabyte
  95 + options[:size] ||= (options[:min_size]..options[:max_size])
  96 + options[:thumbnails] ||= {}
  97 + options[:thumbnail_class] ||= self
  98 + options[:s3_access] ||= :public_read
  99 + options[:cloudfront] ||= false
  100 + options[:content_type] = [options[:content_type]].flatten.collect! { |t| t == :image ? ::Technoweenie::AttachmentFu.content_types : t }.flatten unless options[:content_type].nil?
  101 + options[:cache_control] ||= "max-age=315360000" # 10 years
  102 +
  103 + unless options[:thumbnails].is_a?(Hash)
  104 + raise ArgumentError, ":thumbnails option should be a hash: e.g. :thumbnails => { :foo => '50x50' }"
  105 + end
  106 +
  107 + extend ClassMethods unless (class << self; included_modules; end).include?(ClassMethods)
  108 + include InstanceMethods unless included_modules.include?(InstanceMethods)
  109 +
  110 + parent_options = attachment_options || {}
  111 + # doing these shenanigans so that #attachment_options is available to processors and backends
  112 + self.attachment_options = options
  113 +
  114 + attr_accessor :thumbnail_resize_options
  115 +
  116 + attachment_options[:storage] ||= (attachment_options[:file_system_path] || attachment_options[:path_prefix]) ? :file_system : :db_file
  117 + attachment_options[:storage] ||= parent_options[:storage]
  118 + attachment_options[:path_prefix] ||= attachment_options[:file_system_path]
  119 + if attachment_options[:path_prefix].nil?
  120 + attachment_options[:path_prefix] = case attachment_options[:storage]
  121 + when :s3 then table_name
  122 + when :cloud_files then table_name
  123 + else File.join("public", table_name)
  124 + end
  125 + end
  126 + attachment_options[:path_prefix] = attachment_options[:path_prefix][1..-1] if options[:path_prefix].first == '/'
  127 +
  128 + association_options = { :foreign_key => 'parent_id' }
  129 + if attachment_options[:association_options]
  130 + association_options.merge!(attachment_options[:association_options])
  131 + end
  132 + with_options(association_options) do |m|
  133 + m.has_many :thumbnails, :class_name => "::#{attachment_options[:thumbnail_class]}"
  134 + m.belongs_to :parent, :class_name => "::#{base_class}" unless options[:thumbnails].empty?
  135 + end
  136 +
  137 + storage_mod = ::Technoweenie::AttachmentFu::Backends.const_get("#{options[:storage].to_s.classify}Backend")
  138 + include storage_mod unless included_modules.include?(storage_mod)
  139 +
  140 + case attachment_options[:processor]
  141 + when :none, nil
  142 + processors = ::Technoweenie::AttachmentFu.default_processors.dup
  143 + begin
  144 + if processors.any?
  145 + attachment_options[:processor] = processors.first
  146 + processor_mod = ::Technoweenie::AttachmentFu::Processors.const_get("#{attachment_options[:processor].to_s.classify}Processor")
  147 + include processor_mod unless included_modules.include?(processor_mod)
  148 + end
  149 + rescue Object, Exception
  150 + raise unless load_related_exception?($!)
  151 +
  152 + processors.shift
  153 + retry
  154 + end
  155 + else
  156 + begin
  157 + processor_mod = ::Technoweenie::AttachmentFu::Processors.const_get("#{attachment_options[:processor].to_s.classify}Processor")
  158 + include processor_mod unless included_modules.include?(processor_mod)
  159 + rescue Object, Exception
  160 + raise unless load_related_exception?($!)
  161 +
  162 + puts "Problems loading #{options[:processor]}Processor: #{$!}"
  163 + end
  164 + end unless parent_options[:processor] # Don't let child override processor
  165 + end
  166 +
  167 + def load_related_exception?(e) #:nodoc: implementation specific
  168 + case
  169 + when e.kind_of?(LoadError), e.kind_of?(MissingSourceFile), $!.class.name == "CompilationError"
  170 + # We can't rescue CompilationError directly, as it is part of the RubyInline library.
  171 + # We must instead rescue RuntimeError, and check the class' name.
  172 + true
  173 + else
  174 + false
  175 + end
  176 + end
  177 + private :load_related_exception?
  178 + end
  179 +
  180 + module ClassMethods
  181 + delegate :content_types, :to => ::Technoweenie::AttachmentFu
  182 +
  183 + # Performs common validations for attachment models.
  184 + def validates_as_attachment
  185 + validates_presence_of :size, :content_type, :filename
  186 + validate :attachment_attributes_valid?
  187 + end
  188 +
  189 + # Returns true or false if the given content type is recognized as an image.
  190 + def image?(content_type)
  191 + content_types.include?(content_type)
  192 + end
  193 +
  194 + def self.extended(base)
  195 + base.class_attribute :attachment_options
  196 + base.before_destroy :destroy_thumbnails
  197 + base.before_validation :set_size_from_temp_path
  198 + base.after_destroy :destroy_file
  199 + base.after_validation :process_attachment
  200 + base.after_save :after_process_attachment
  201 + #if defined?(::ActiveSupport::Callbacks)
  202 + # base.define_callbacks :after_resize, :after_attachment_saved, :before_thumbnail_saved
  203 + #end
  204 + end
  205 +
  206 + unless defined?(::ActiveSupport::Callbacks)
  207 + # Callback after an image has been resized.
  208 + #
  209 + # class Foo < ActiveRecord::Base
  210 + # acts_as_attachment
  211 + # after_resize do |record, img|
  212 + # record.aspect_ratio = img.columns.to_f / img.rows.to_f
  213 + # end
  214 + # end
  215 + def after_resize(&block)
  216 + write_inheritable_array(:after_resize, [block])
  217 + end
  218 +
  219 + # Callback after an attachment has been saved either to the file system or the DB.
  220 + # Only called if the file has been changed, not necessarily if the record is updated.
  221 + #
  222 + # class Foo < ActiveRecord::Base
  223 + # acts_as_attachment
  224 + # after_attachment_saved do |record|
  225 + # ...
  226 + # end
  227 + # end
  228 + def after_attachment_saved(&block)
  229 + write_inheritable_array(:after_attachment_saved, [block])
  230 + end
  231 +
  232 + # Callback before a thumbnail is saved. Use this to pass any necessary extra attributes that may be required.
  233 + #
  234 + # class Foo < ActiveRecord::Base
  235 + # acts_as_attachment
  236 + # before_thumbnail_saved do |thumbnail|
  237 + # record = thumbnail.parent
  238 + # ...
  239 + # end
  240 + # end
  241 + def before_thumbnail_saved(&block)
  242 + write_inheritable_array(:before_thumbnail_saved, [block])
  243 + end
  244 + end
  245 +
  246 + # Get the thumbnail class, which is the current attachment class by default.
  247 + # Configure this with the :thumbnail_class option.
  248 + def thumbnail_class
  249 + attachment_options[:thumbnail_class] = attachment_options[:thumbnail_class].constantize unless attachment_options[:thumbnail_class].is_a?(Class)
  250 + attachment_options[:thumbnail_class]
  251 + end
  252 +
  253 + # Copies the given file path to a new tempfile, returning the closed tempfile.
  254 + def copy_to_temp_file(file, temp_base_name)
  255 + Tempfile.new(temp_base_name, ::Technoweenie::AttachmentFu.tempfile_path).tap do |tmp|
  256 + tmp.close
  257 + FileUtils.cp file, tmp.path
  258 + end
  259 + end
  260 +
  261 + # Writes the given data to a new tempfile, returning the closed tempfile.
  262 + def write_to_temp_file(data, temp_base_name)
  263 + Tempfile.new(temp_base_name, ::Technoweenie::AttachmentFu.tempfile_path).tap do |tmp|
  264 + tmp.binmode
  265 + tmp.write data
  266 + tmp.close
  267 + end
  268 + end
  269 +
  270 + def polymorphic_relation_type_column
  271 + return @@_polymorphic_relation_type_column if defined?(@@_polymorphic_relation_type_column)
  272 + # Checked against ActiveRecord 1.15.6 through Edge @ 2009-08-05.
  273 + ref = reflections.values.detect { |r| r.macro == :belongs_to && r.options[:polymorphic] }
  274 + @@_polymorphic_relation_type_column = ref && ref.options[:foreign_type]
  275 + end
  276 + end
  277 +
  278 + module InstanceMethods
  279 + def self.included(base)
  280 + base.define_callbacks *[:after_resize, :after_attachment_saved, :before_thumbnail_saved] if base.respond_to?(:define_callbacks)
  281 + end
  282 +
  283 + # Checks whether the attachment's content type is an image content type
  284 + def image?
  285 + self.class.image?(content_type)
  286 + end
  287 +
  288 + # Returns true/false if an attachment is thumbnailable. A thumbnailable attachment has an image content type and the parent_id attribute.
  289 + def thumbnailable?
  290 + image? && respond_to?(:parent_id) && parent_id.nil?
  291 + end
  292 +
  293 + # Returns the class used to create new thumbnails for this attachment.
  294 + def thumbnail_class
  295 + self.class.thumbnail_class
  296 + end
  297 +
  298 + # Gets the thumbnail name for a filename. 'foo.jpg' becomes 'foo_thumbnail.jpg'
  299 + def thumbnail_name_for(thumbnail = nil)
  300 + if thumbnail.blank?
  301 + if filename.nil?
  302 + return ''
  303 + else
  304 + return filename
  305 + end
  306 + end
  307 +
  308 + ext = nil
  309 + basename = filename.gsub /\.\w+$/ do |s|
  310 + ext = s; ''
  311 + end
  312 + # ImageScience doesn't create gif thumbnails, only pngs
  313 + ext.sub!(/gif$/i, 'png') if attachment_options[:processor] == "ImageScience"
  314 + "#{basename}_#{thumbnail}#{ext}"
  315 + end
  316 +
  317 + # Creates or updates the thumbnail for the current attachment.
  318 + def create_or_update_thumbnail(temp_file, file_name_suffix, *size)
  319 + thumbnailable? || raise(ThumbnailError.new("Can't create a thumbnail if the content type is not an image or there is no parent_id column"))
  320 + find_or_initialize_thumbnail(file_name_suffix).tap do |thumb|
  321 + thumb.temp_paths.unshift temp_file
  322 + thumb.send(:assign_attributes, {
  323 + :content_type => content_type,
  324 + :filename => thumbnail_name_for(file_name_suffix),
  325 + :thumbnail_resize_options => size
  326 + }, :without_protection => true)
  327 + callback_with_args :before_thumbnail_saved, thumb
  328 + thumb.save!
  329 + end
  330 + end
  331 +
  332 + # Sets the content type.
  333 + def content_type=(new_type)
  334 + write_attribute :content_type, new_type.to_s.strip
  335 + end
  336 +
  337 + # Sanitizes a filename.
  338 + def filename=(new_name)
  339 + write_attribute :filename, sanitize_filename(new_name)
  340 + end
  341 +
  342 + # Returns the width/height in a suitable format for the image_tag helper: (100x100)
  343 + def image_size
  344 + [width.to_s, height.to_s] * 'x'
  345 + end
  346 +
  347 + # Returns true if the attachment data will be written to the storage system on the next save
  348 + def save_attachment?
  349 + File.file?(temp_path.class == String ? temp_path : temp_path.to_filename)
  350 + end
  351 +
  352 + # nil placeholder in case this field is used in a form.
  353 + def uploaded_data() nil; end
  354 +
  355 + # This method handles the uploaded file object. If you set the field name to uploaded_data, you don't need
  356 + # any special code in your controller.
  357 + #
  358 + # <% form_for :attachment, :html => { :multipart => true } do |f| -%>
  359 + # <p><%= f.file_field :uploaded_data %></p>
  360 + # <p><%= submit_tag :Save %>
  361 + # <% end -%>
  362 + #
  363 + # @attachment = Attachment.create! params[:attachment]
  364 + #
  365 + # TODO: Allow it to work with Merb tempfiles too.
  366 + def uploaded_data=(file_data)
  367 + if file_data.respond_to?(:content_type)
  368 + return nil if file_data.size == 0
  369 + self.content_type = file_data.content_type
  370 + self.filename = file_data.original_filename if respond_to?(:filename)
  371 + else
  372 + return nil if file_data.blank? || file_data['size'] == 0
  373 + self.content_type = file_data['content_type']
  374 + self.filename = file_data['filename']
  375 + file_data = file_data['tempfile']
  376 + end
  377 + if file_data.is_a?(StringIO)
  378 + file_data.rewind
  379 + set_temp_data file_data.read
  380 + else
  381 + file_data.respond_to?(:tempfile) ? self.temp_paths.unshift( file_data.tempfile.path ) : self.temp_paths.unshift( file_data.path )
  382 + end
  383 + end
  384 +
  385 + # Gets the latest temp path from the collection of temp paths. While working with an attachment,
  386 + # multiple Tempfile objects may be created for various processing purposes (resizing, for example).
  387 + # An array of all the tempfile objects is stored so that the Tempfile instance is held on to until
  388 + # it's not needed anymore. The collection is cleared after saving the attachment.
  389 + def temp_path
  390 + p = temp_paths.first
  391 + p.respond_to?(:path) ? p.path : p.to_s
  392 + end
  393 +
  394 + # Gets an array of the currently used temp paths. Defaults to a copy of #full_filename.
  395 + def temp_paths
  396 + @temp_paths ||= (new_record? || !respond_to?(:full_filename) || !File.exist?(full_filename) ?
  397 + [] : [copy_to_temp_file(full_filename)])
  398 + end
  399 +
  400 + # Gets the data from the latest temp file. This will read the file into memory.
  401 + def temp_data
  402 + save_attachment? ? File.read(temp_path) : nil
  403 + end
  404 +
  405 + # Writes the given data to a Tempfile and adds it to the collection of temp files.
  406 + def set_temp_data(data)
  407 + temp_paths.unshift write_to_temp_file data unless data.nil?
  408 + end
  409 +
  410 + # Copies the given file to a randomly named Tempfile.
  411 + def copy_to_temp_file(file)
  412 + self.class.copy_to_temp_file file, random_tempfile_filename
  413 + end
  414 +
  415 + # Writes the given file to a randomly named Tempfile.
  416 + def write_to_temp_file(data)
  417 + self.class.write_to_temp_file data, random_tempfile_filename
  418 + end
  419 +
  420 + # Stub for creating a temp file from the attachment data. This should be defined in the backend module.
  421 + def create_temp_file() end
  422 +
  423 + # Allows you to work with a processed representation (RMagick, ImageScience, etc) of the attachment in a block.
  424 + #
  425 + # @attachment.with_image do |img|
  426 + # self.data = img.thumbnail(100, 100).to_blob
  427 + # end
  428 + #
  429 + def with_image(&block)
  430 + self.class.with_image(temp_path, &block)
  431 + end
  432 +
  433 + protected
  434 + # Generates a unique filename for a Tempfile.
  435 + def random_tempfile_filename
  436 + base_filename = filename ? filename.gsub(/\.\w+$/, '') : 'attachment'
  437 + ext = filename.slice(/\.\w+$/)
  438 + ["#{rand Time.now.to_i}#{base_filename}", ext || '']
  439 + end
  440 +
  441 + def sanitize_filename(filename)
  442 + return unless filename
  443 + filename.strip.tap do |name|
  444 + # NOTE: File.basename doesn't work right with Windows paths on Unix
  445 + # get only the filename, not the whole path
  446 + name.gsub! /^.*(\\|\/)/, ''
  447 +
  448 + # Finally, replace all non alphanumeric, underscore or periods with underscore
  449 + name.gsub! /[^A-Za-z0-9\.\-]/, '_'
  450 + end
  451 + end
  452 +
  453 + # before_validation callback.
  454 + def set_size_from_temp_path
  455 + self.size = File.size(temp_path) if save_attachment?
  456 + end
  457 +
  458 + # validates the size and content_type attributes according to the current model's options
  459 + def attachment_attributes_valid?
  460 + [:size, :content_type].each do |attr_name|
  461 + enum = attachment_options[attr_name]
  462 + if Object.const_defined?(:I18n) # Rails >= 2.2
  463 + errors.add attr_name, I18n.translate("activerecord.errors.messages.inclusion", attr_name => enum) unless enum.nil? || enum.include?(send(attr_name))
  464 + else
  465 + errors.add attr_name, ActiveRecord::Errors.default_error_messages[:inclusion] unless enum.nil? || enum.include?(send(attr_name))
  466 + end
  467 + end
  468 + end
  469 +
  470 + # Initializes a new thumbnail with the given suffix.
  471 + def find_or_initialize_thumbnail(file_name_suffix)
  472 + respond_to?(:parent_id) ?
  473 + thumbnail_class.find_or_initialize_by_thumbnail_and_parent_id(file_name_suffix.to_s, id) :
  474 + thumbnail_class.find_or_initialize_by_thumbnail(file_name_suffix.to_s)
  475 + end
  476 +
  477 + # Stub for a #process_attachment method in a processor
  478 + def process_attachment
  479 + @saved_attachment = save_attachment?
  480 + end
  481 +
  482 + # Cleans up after processing. Thumbnails are created, the attachment is stored to the backend, and the temp_paths are cleared.
  483 + def after_process_attachment
  484 + if @saved_attachment
  485 + if respond_to?(:process_attachment_with_processing, true) && thumbnailable? && !attachment_options[:thumbnails].blank? && parent_id.nil?
  486 + temp_file = temp_path || create_temp_file
  487 + attachment_options[:thumbnails].each { |suffix, size|
  488 + if size.is_a?(Symbol)
  489 + parent_type = polymorphic_parent_type
  490 + next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s) && respond_to?(size)
  491 + size = send(size)
  492 + end
  493 + if size.is_a?(Hash)
  494 + parent_type = polymorphic_parent_type
  495 + next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s)
  496 + size.each { |ppt_suffix, ppt_size|
  497 + create_or_update_thumbnail(temp_file, ppt_suffix, *ppt_size)
  498 + }
  499 + else
  500 + create_or_update_thumbnail(temp_file, suffix, *size)
  501 + end
  502 + }
  503 + end
  504 + save_to_storage
  505 + @temp_paths.clear
  506 + @saved_attachment = nil
  507 + #callback :after_attachment_saved
  508 + callback_with_args :after_attachment_saved, nil
  509 + end
  510 + end
  511 +
  512 + # Resizes the given processed img object with either the attachment resize options or the thumbnail resize options.
  513 + def resize_image_or_thumbnail!(img)
  514 + if (!respond_to?(:parent_id) || parent_id.nil?) && attachment_options[:resize_to] # parent image
  515 + resize_image(img, attachment_options[:resize_to])
  516 + elsif thumbnail_resize_options # thumbnail
  517 + resize_image(img, thumbnail_resize_options)
  518 + end
  519 + end
  520 +
  521 + if defined?(Rails) && Rails::VERSION::MAJOR >= 3
  522 + def callback_with_args(method, arg = self)
  523 + if respond_to?(method)
  524 + send(method, arg)
  525 + end
  526 + end
  527 + # Yanked from ActiveRecord::Callbacks, modified so I can pass args to the callbacks besides self.
  528 + # Only accept blocks, however
  529 + elsif ActiveSupport.const_defined?(:Callbacks)
  530 + # Rails 2.1 and beyond!
  531 + def callback_with_args(method, arg = self)
  532 + notify(method)
  533 +
  534 + result = run_callbacks(method, { :object => arg }) { |result, object| result == false }
  535 +
  536 + if result != false && respond_to_without_attributes?(method)
  537 + result = send(method)
  538 + end
  539 +
  540 + result
  541 + end
  542 +
  543 + def run_callbacks(kind, options = {}, &block)
  544 + options.reverse_merge!( :object => self )
  545 + self.class.send("#{kind}_callback_chain").run(options[:object], options, &block)
  546 + end
  547 + else
  548 + # Rails 2.0
  549 + def callback_with_args(method, arg = self)
  550 + notify(method)
  551 +
  552 + result = nil
  553 + callbacks_for(method).each do |callback|
  554 + result = callback.call(self, arg)
  555 + return false if result == false
  556 + end
  557 + result
  558 + end
  559 + end
  560 +
  561 + # Removes the thumbnails for the attachment, if it has any
  562 + def destroy_thumbnails
  563 + self.thumbnails.each { |thumbnail| thumbnail.destroy } if thumbnailable?
  564 + end
  565 +
  566 + def polymorphic_parent_type
  567 + rel_name = self.class.polymorphic_relation_type_column
  568 + rel_name && send(rel_name)
  569 + end
  570 +
  571 + def get_jpeg_quality(require_0_to_100 = true)
  572 + quality = attachment_options[:jpeg_quality]
  573 + if quality.is_a?(Hash)
  574 + sbl_quality = thumbnail && quality[thumbnail.to_sym]
  575 + sbl_quality = nil if sbl_quality && require_0_to_100 && !sbl_quality.to_i.between?(0, 100)
  576 + surface = (width || 1) * (height || 1)
  577 + size_quality = quality.detect { |k, v|
  578 + next unless k.is_a?(String) && k =~ /^(<|>=)(\d+)$/
  579 + op, threshold = $1, $2.to_i
  580 + surface.send(op, threshold)
  581 + }
  582 + quality = sbl_quality || size_quality && size_quality[1]
  583 + end
  584 + return quality && (!require_0_to_100 || quality.to_i.between?(0, 100)) ? quality : nil
  585 + end
  586 + end
  587 + end
  588 +end
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/backends/cloud_file_backend.rb 0 → 100644
... ... @@ -0,0 +1,211 @@
  1 +module Technoweenie # :nodoc:
  2 + module AttachmentFu # :nodoc:
  3 + module Backends
  4 + # = CloudFiles Storage Backend
  5 + #
  6 + # Enables use of {Rackspace Cloud Files}[http://www.mosso.com/cloudfiles.jsp] as a storage mechanism
  7 + #
  8 + # Based heavily on the Amazon S3 backend.
  9 + #
  10 + # == Requirements
  11 + #
  12 + # Requires the {Cloud Files Gem}[http://www.mosso.com/cloudfiles.jsp] by Rackspace
  13 + #
  14 + # == Configuration
  15 + #
  16 + # Configuration is done via <tt>Rails.root.to_s/config/rackspace_cloudfiles.yml</tt> and is loaded according to the <tt>#{Rails.env}</tt>.
  17 + # The minimum connection options that you must specify are a container name, your Mosso login name and your Mosso API key.
  18 + # You can sign up for Cloud Files and get access keys by visiting https://www.mosso.com/buy.htm
  19 + #
  20 + # Example configuration (Rails.root.to_s/config/rackspace_cloudfiles.yml)
  21 + #
  22 + # development:
  23 + # container_name: appname_development
  24 + # username: <your key>
  25 + # api_key: <your key>
  26 + #
  27 + # test:
  28 + # container_name: appname_test
  29 + # username: <your key>
  30 + # api_key: <your key>
  31 + #
  32 + # production:
  33 + # container_name: appname
  34 + # username: <your key>
  35 + # apik_key: <your key>
  36 + #
  37 + # You can change the location of the config path by passing a full path to the :cloudfiles_config_path option.
  38 + #
  39 + # has_attachment :storage => :cloud_files, :cloudfiles_config_path => (Rails.root.to_s + '/config/mosso.yml')
  40 + #
  41 + # === Required configuration parameters
  42 + #
  43 + # * <tt>:username</tt> - The username for your Rackspace Cloud (Mosso) account. Provided by Rackspace.
  44 + # * <tt>:secret_access_key</tt> - The api key for your Rackspace Cloud account. Provided by Rackspace.
  45 + # * <tt>:container_name</tt> - The name of a container in your Cloud Files account.
  46 + #
  47 + # If any of these required arguments is missing, a AuthenticationException will be raised from CloudFiles::Connection.
  48 + #
  49 + # == Usage
  50 + #
  51 + # To specify Cloud Files as the storage mechanism for a model, set the acts_as_attachment <tt>:storage</tt> option to <tt>:cloud_files/tt>.
  52 + #
  53 + # class Photo < ActiveRecord::Base
  54 + # has_attachment :storage => :cloud_files
  55 + # end
  56 + #
  57 + # === Customizing the path
  58 + #
  59 + # By default, files are prefixed using a pseudo hierarchy in the form of <tt>:table_name/:id</tt>, which results
  60 + # in Cloud Files object names (and urls) that look like: http://:server/:container_name/:table_name/:id/:filename with :table_name
  61 + # representing the customizable portion of the path. You can customize this prefix using the <tt>:path_prefix</tt>
  62 + # option:
  63 + #
  64 + # class Photo < ActiveRecord::Base
  65 + # has_attachment :storage => :cloud_files, :path_prefix => 'my/custom/path'
  66 + # end
  67 + #
  68 + # Which would result in public URLs like <tt>http(s)://:server/:container_name/my/custom/path/:id/:filename.</tt>
  69 + #
  70 + # === Permissions
  71 + #
  72 + # File permisisons are determined by the permissions of the container. At present, the options are public (and distributed
  73 + # by the Limelight CDN), and private (only available to your login)
  74 + #
  75 + # === Other options
  76 + #
  77 + # Of course, all the usual configuration options apply, such as content_type and thumbnails:
  78 + #
  79 + # class Photo < ActiveRecord::Base
  80 + # has_attachment :storage => :cloud_files, :content_type => ['application/pdf', :image], :resize_to => 'x50'
  81 + # has_attachment :storage => :cloud_files, :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
  82 + # end
  83 + #
  84 + # === Accessing Cloud Files URLs
  85 + #
  86 + # You can get an object's public URL using the cloudfiles_url accessor. For example, assuming that for your postcard app
  87 + # you had a container name like 'postcard_world_development', and an attachment model called Photo:
  88 + #
  89 + # @postcard.cloudfiles_url # => http://cdn.cloudfiles.mosso.com/c45182/uploaded_files/20/london.jpg
  90 + #
  91 + # The resulting url is in the form: http://:server/:container_name/:table_name/:id/:file.
  92 + # The optional thumbnail argument will output the thumbnail's filename (if any).
  93 + #
  94 + # Additionally, you can get an object's base path relative to the container root using
  95 + # <tt>base_path</tt>:
  96 + #
  97 + # @photo.file_base_path # => uploaded_files/20
  98 + #
  99 + # And the full path (including the filename) using <tt>full_filename</tt>:
  100 + #
  101 + # @photo.full_filename # => uploaded_files/20/london.jpg
  102 + #
  103 + # Niether <tt>base_path</tt> or <tt>full_filename</tt> include the container name as part of the path.
  104 + # You can retrieve the container name using the <tt>container_name</tt> method.
  105 + module CloudFileBackend
  106 + class RequiredLibraryNotFoundError < StandardError; end
  107 + class ConfigFileNotFoundError < StandardError; end
  108 +
  109 + def self.included(base) #:nodoc:
  110 + mattr_reader :container_name, :cloudfiles_config
  111 +
  112 + begin
  113 + require 'cloudfiles'
  114 + rescue LoadError
  115 + raise RequiredLibraryNotFoundError.new('CloudFiles could not be loaded')
  116 + end
  117 +
  118 + begin
  119 + @@cloudfiles_config_path = base.attachment_options[:cloudfiles_config_path] || (Rails.root.to_s + '/config/rackspace_cloudfiles.yml')
  120 + @@cloudfiles_config = @@cloudfiles_config = YAML.load(ERB.new(File.read(@@cloudfiles_config_path)).result)[Rails.env].symbolize_keys
  121 + rescue
  122 + #raise ConfigFileNotFoundError.new('File %s not found' % @@cloudfiles_config_path)
  123 + end
  124 +
  125 + @@container_name = @@cloudfiles_config[:container_name]
  126 + @@cf = CloudFiles::Connection.new(@@cloudfiles_config[:username], @@cloudfiles_config[:api_key])
  127 + @@container = @@cf.container(@@container_name)
  128 +
  129 + base.before_update :rename_file
  130 + end
  131 +
  132 + # Overwrites the base filename writer in order to store the old filename
  133 + def filename=(value)
  134 + @old_filename = filename unless filename.nil? || @old_filename
  135 + write_attribute :filename, sanitize_filename(value)
  136 + end
  137 +
  138 + # The attachment ID used in the full path of a file
  139 + def attachment_path_id
  140 + ((respond_to?(:parent_id) && parent_id) || id).to_s
  141 + end
  142 +
  143 + # The pseudo hierarchy containing the file relative to the container name
  144 + # Example: <tt>:table_name/:id</tt>
  145 + def base_path
  146 + File.join(attachment_options[:path_prefix], attachment_path_id)
  147 + end
  148 +
  149 + # The full path to the file relative to the container name
  150 + # Example: <tt>:table_name/:id/:filename</tt>
  151 + def full_filename(thumbnail = nil)
  152 + File.join(base_path, thumbnail_name_for(thumbnail))
  153 + end
  154 +
  155 + # All public objects are accessible via a GET request to the Cloud Files servers. You can generate a
  156 + # url for an object using the cloudfiles_url method.
  157 + #
  158 + # @photo.cloudfiles_url
  159 + #
  160 + # The resulting url is in the CDN URL for the object
  161 + #
  162 + # The optional thumbnail argument will output the thumbnail's filename (if any).
  163 + #
  164 + # If you are trying to get the URL for a nonpublic container, nil will be returned.
  165 + def cloudfiles_url(thumbnail = nil)
  166 + if @@container.public?
  167 + File.join(@@container.cdn_url, full_filename(thumbnail))
  168 + else
  169 + nil
  170 + end
  171 + end
  172 + alias :public_filename :cloudfiles_url
  173 +
  174 + def create_temp_file
  175 + write_to_temp_file current_data
  176 + end
  177 +
  178 + def current_data
  179 + @@container.get_object(full_filename).data
  180 + end
  181 +
  182 + protected
  183 + # Called in the after_destroy callback
  184 + def destroy_file
  185 + @@container.delete_object(full_filename)
  186 + end
  187 +
  188 + def rename_file
  189 + # Cloud Files doesn't rename right now, so we'll just nuke.
  190 + return unless @old_filename && @old_filename != filename
  191 +
  192 + old_full_filename = File.join(base_path, @old_filename)
  193 + @@container.delete_object(old_full_filename)
  194 +
  195 + @old_filename = nil
  196 + true
  197 + end
  198 +
  199 + def save_to_storage
  200 + if save_attachment?
  201 + @object = @@container.create_object(full_filename)
  202 + @object.write((temp_path ? File.open(temp_path) : temp_data))
  203 + end
  204 +
  205 + @old_filename = nil
  206 + true
  207 + end
  208 + end
  209 + end
  210 + end
  211 +end
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/backends/db_file_backend.rb 0 → 100644
... ... @@ -0,0 +1,39 @@
  1 +module Technoweenie # :nodoc:
  2 + module AttachmentFu # :nodoc:
  3 + module Backends
  4 + # Methods for DB backed attachments
  5 + module DbFileBackend
  6 + def self.included(base) #:nodoc:
  7 + Object.const_set(:DbFile, Class.new(ActiveRecord::Base)) unless Object.const_defined?(:DbFile)
  8 + base.belongs_to :db_file, :class_name => '::DbFile', :foreign_key => 'db_file_id'
  9 + end
  10 +
  11 + # Creates a temp file with the current db data.
  12 + def create_temp_file
  13 + write_to_temp_file current_data
  14 + end
  15 +
  16 + # Gets the current data from the database
  17 + def current_data
  18 + db_file.data
  19 + end
  20 +
  21 + protected
  22 + # Destroys the file. Called in the after_destroy callback
  23 + def destroy_file
  24 + db_file.destroy if db_file
  25 + end
  26 +
  27 + # Saves the data to the DbFile model
  28 + def save_to_storage
  29 + if save_attachment?
  30 + (db_file || build_db_file).data = temp_data
  31 + db_file.save!
  32 + self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
  33 + end
  34 + true
  35 + end
  36 + end
  37 + end
  38 + end
  39 +end
0 40 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/backends/file_system_backend.rb 0 → 100644
... ... @@ -0,0 +1,126 @@
  1 +require 'fileutils'
  2 +require 'digest/sha2'
  3 +
  4 +module Technoweenie # :nodoc:
  5 + module AttachmentFu # :nodoc:
  6 + module Backends
  7 + # Methods for file system backed attachments
  8 + module FileSystemBackend
  9 + def self.included(base) #:nodoc:
  10 + base.before_update :rename_file
  11 + end
  12 +
  13 + # Gets the full path to the filename in this format:
  14 + #
  15 + # # This assumes a model name like MyModel
  16 + # # public/#{table_name} is the default filesystem path
  17 + # #{Rails.root}/public/my_models/5/blah.jpg
  18 + #
  19 + # Overwrite this method in your model to customize the filename.
  20 + # The optional thumbnail argument will output the thumbnail's filename.
  21 + def full_filename(thumbnail = nil)
  22 + file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s
  23 + File.join(Rails.root, file_system_path, *partitioned_path(thumbnail_name_for(thumbnail)))
  24 + end
  25 +
  26 + # Used as the base path that #public_filename strips off full_filename to create the public path
  27 + def base_path
  28 + @base_path ||= File.join(Rails.root, 'public')
  29 + end
  30 +
  31 + # The attachment ID used in the full path of a file
  32 + def attachment_path_id
  33 + ((respond_to?(:parent_id) && parent_id) || id) || 0
  34 + end
  35 +
  36 + # Partitions the given path into an array of path components.
  37 + #
  38 + # For example, given an <tt>*args</tt> of ["foo", "bar"], it will return
  39 + # <tt>["0000", "0001", "foo", "bar"]</tt> (assuming that that id returns 1).
  40 + #
  41 + # If the id is not an integer, then path partitioning will be performed by
  42 + # hashing the string value of the id with SHA-512, and splitting the result
  43 + # into 4 components. If the id a 128-bit UUID (as set by :uuid_primary_key => true)
  44 + # then it will be split into 2 components.
  45 + #
  46 + # To turn this off entirely, set :partition => false.
  47 + def partitioned_path(*args)
  48 + if respond_to?(:attachment_options) && attachment_options[:partition] == false
  49 + args
  50 + elsif attachment_options[:uuid_primary_key]
  51 + # Primary key is a 128-bit UUID in hex format. Split it into 2 components.
  52 + path_id = attachment_path_id.to_s
  53 + component1 = path_id[0..15] || "-"
  54 + component2 = path_id[16..-1] || "-"
  55 + [component1, component2] + args
  56 + else
  57 + path_id = attachment_path_id
  58 + if path_id.is_a?(Integer)
  59 + # Primary key is an integer. Split it after padding it with 0.
  60 + ("%08d" % path_id).scan(/..../) + args
  61 + else
  62 + # Primary key is a String. Hash it, then split it into 4 components.
  63 + hash = Digest::SHA512.hexdigest(path_id.to_s)
  64 + [hash[0..31], hash[32..63], hash[64..95], hash[96..127]] + args
  65 + end
  66 + end
  67 + end
  68 +
  69 + # Gets the public path to the file
  70 + # The optional thumbnail argument will output the thumbnail's filename.
  71 + def public_filename(thumbnail = nil)
  72 + full_filename(thumbnail).gsub %r(^#{Regexp.escape(base_path)}), ''
  73 + end
  74 +
  75 + def filename=(value)
  76 + @old_filename = full_filename unless filename.nil? || @old_filename
  77 + write_attribute :filename, sanitize_filename(value)
  78 + end
  79 +
  80 + # Creates a temp file from the currently saved file.
  81 + def create_temp_file
  82 + copy_to_temp_file full_filename
  83 + end
  84 +
  85 + protected
  86 + # Destroys the file. Called in the after_destroy callback
  87 + def destroy_file
  88 + FileUtils.rm full_filename
  89 + # remove directory also if it is now empty
  90 + Dir.rmdir(File.dirname(full_filename)) if (Dir.entries(File.dirname(full_filename))-['.','..']).empty?
  91 + rescue
  92 + logger.info "Exception destroying #{full_filename.inspect}: [#{$!.class.name}] #{$1.to_s}"
  93 + logger.warn $!.backtrace.collect { |b| " > #{b}" }.join("\n")
  94 + end
  95 +
  96 + # Renames the given file before saving
  97 + def rename_file
  98 + return unless @old_filename && @old_filename != full_filename
  99 + if save_attachment? && File.exists?(@old_filename)
  100 + FileUtils.rm @old_filename
  101 + elsif File.exists?(@old_filename)
  102 + FileUtils.mv @old_filename, full_filename
  103 + end
  104 + @old_filename = nil
  105 + true
  106 + end
  107 +
  108 + # Saves the file to the file system
  109 + def save_to_storage
  110 + if save_attachment?
  111 + # TODO: This overwrites the file if it exists, maybe have an allow_overwrite option?
  112 + FileUtils.mkdir_p(File.dirname(full_filename))
  113 + FileUtils.cp(temp_path, full_filename)
  114 + FileUtils.chmod(attachment_options[:chmod] || 0644, full_filename)
  115 + end
  116 + @old_filename = nil
  117 + true
  118 + end
  119 +
  120 + def current_data
  121 + File.file?(full_filename) ? File.read(full_filename) : nil
  122 + end
  123 + end
  124 + end
  125 + end
  126 +end
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/backends/s3_backend.rb 0 → 100644
... ... @@ -0,0 +1,412 @@
  1 +module Technoweenie # :nodoc:
  2 + module AttachmentFu # :nodoc:
  3 + module Backends
  4 + # = AWS::S3 Storage Backend
  5 + #
  6 + # Enables use of {Amazon's Simple Storage Service}[http://aws.amazon.com/s3] as a storage mechanism
  7 + #
  8 + # == Requirements
  9 + #
  10 + # Requires the {AWS::S3 Library}[http://amazon.rubyforge.org] for S3 by Marcel Molina Jr. installed either
  11 + # as a gem or a as a Rails plugin.
  12 + #
  13 + # == Configuration
  14 + #
  15 + # Configuration is done via <tt>#{Rails.root}/config/amazon_s3.yml</tt> and is loaded according to the <tt>#{Rails.env}</tt>.
  16 + # The minimum connection options that you must specify are a bucket name, your access key id and your secret access key.
  17 + # If you don't already have your access keys, all you need to sign up for the S3 service is an account at Amazon.
  18 + # You can sign up for S3 and get access keys by visiting http://aws.amazon.com/s3.
  19 + #
  20 + # If you wish to use Amazon CloudFront to serve the files, you can also specify a distibution domain for the bucket.
  21 + # To read more about CloudFront, visit http://aws.amazon.com/cloudfront
  22 + #
  23 + # Example configuration (#{Rails.root}/config/amazon_s3.yml)
  24 + #
  25 + # development:
  26 + # bucket_name: appname_development
  27 + # access_key_id: <your key>
  28 + # secret_access_key: <your key>
  29 + # distribution_domain: XXXX.cloudfront.net
  30 + #
  31 + # test:
  32 + # bucket_name: appname_test
  33 + # access_key_id: <your key>
  34 + # secret_access_key: <your key>
  35 + # distribution_domain: XXXX.cloudfront.net
  36 + #
  37 + # production:
  38 + # bucket_name: appname
  39 + # access_key_id: <your key>
  40 + # secret_access_key: <your key>
  41 + # distribution_domain: XXXX.cloudfront.net
  42 + #
  43 + # You can change the location of the config path by passing a full path to the :s3_config_path option.
  44 + #
  45 + # has_attachment :storage => :s3, :s3_config_path => (#{Rails.root} + '/config/s3.yml')
  46 + #
  47 + # === Required configuration parameters
  48 + #
  49 + # * <tt>:access_key_id</tt> - The access key id for your S3 account. Provided by Amazon.
  50 + # * <tt>:secret_access_key</tt> - The secret access key for your S3 account. Provided by Amazon.
  51 + # * <tt>:bucket_name</tt> - A unique bucket name (think of the bucket_name as being like a database name).
  52 + #
  53 + # If any of these required arguments is missing, a MissingAccessKey exception will be raised from AWS::S3.
  54 + #
  55 + # == About bucket names
  56 + #
  57 + # Bucket names have to be globaly unique across the S3 system. And you can only have up to 100 of them,
  58 + # so it's a good idea to think of a bucket as being like a database, hence the correspondance in this
  59 + # implementation to the development, test, and production environments.
  60 + #
  61 + # The number of objects you can store in a bucket is, for all intents and purposes, unlimited.
  62 + #
  63 + # === Optional configuration parameters
  64 + #
  65 + # * <tt>:server</tt> - The server to make requests to. Defaults to <tt>s3.amazonaws.com</tt>.
  66 + # * <tt>:port</tt> - The port to the requests should be made on. Defaults to 80 or 443 if <tt>:use_ssl</tt> is set.
  67 + # * <tt>:use_ssl</tt> - If set to true, <tt>:port</tt> will be implicitly set to 443, unless specified otherwise. Defaults to false.
  68 + # * <tt>:distribution_domain</tt> - The CloudFront distribution domain for the bucket. This can either be the assigned
  69 + # distribution domain (ie. XXX.cloudfront.net) or a chosen domain using a CNAME. See CloudFront for more details.
  70 + #
  71 + # == Usage
  72 + #
  73 + # To specify S3 as the storage mechanism for a model, set the acts_as_attachment <tt>:storage</tt> option to <tt>:s3</tt>.
  74 + #
  75 + # class Photo < ActiveRecord::Base
  76 + # has_attachment :storage => :s3
  77 + # end
  78 + #
  79 + # === Customizing the path
  80 + #
  81 + # By default, files are prefixed using a pseudo hierarchy in the form of <tt>:table_name/:id</tt>, which results
  82 + # in S3 urls that look like: http(s)://:server/:bucket_name/:table_name/:id/:filename with :table_name
  83 + # representing the customizable portion of the path. You can customize this prefix using the <tt>:path_prefix</tt>
  84 + # option:
  85 + #
  86 + # class Photo < ActiveRecord::Base
  87 + # has_attachment :storage => :s3, :path_prefix => 'my/custom/path'
  88 + # end
  89 + #
  90 + # Which would result in URLs like <tt>http(s)://:server/:bucket_name/my/custom/path/:id/:filename.</tt>
  91 + #
  92 + # === Using different bucket names on different models
  93 + #
  94 + # By default the bucket name that the file will be stored to is the one specified by the
  95 + # <tt>:bucket_name</tt> key in the amazon_s3.yml file. You can use the <tt>:bucket_key</tt> option
  96 + # to overide this behavior on a per model basis. For instance if you want a bucket that will hold
  97 + # only Photos you can do this:
  98 + #
  99 + # class Photo < ActiveRecord::Base
  100 + # has_attachment :storage => :s3, :bucket_key => :photo_bucket_name
  101 + # end
  102 + #
  103 + # And then your amazon_s3.yml file needs to look like this.
  104 + #
  105 + # development:
  106 + # bucket_name: appname_development
  107 + # access_key_id: <your key>
  108 + # secret_access_key: <your key>
  109 + #
  110 + # test:
  111 + # bucket_name: appname_test
  112 + # access_key_id: <your key>
  113 + # secret_access_key: <your key>
  114 + #
  115 + # production:
  116 + # bucket_name: appname
  117 + # photo_bucket_name: appname_photos
  118 + # access_key_id: <your key>
  119 + # secret_access_key: <your key>
  120 + #
  121 + # If the bucket_key you specify is not there in a certain environment then attachment_fu will
  122 + # default to the <tt>bucket_name</tt> key. This way you only have to create special buckets
  123 + # this can be helpful if you only need special buckets in certain environments.
  124 + #
  125 + # === Permissions
  126 + #
  127 + # By default, files are stored on S3 with public access permissions. You can customize this using
  128 + # the <tt>:s3_access</tt> option to <tt>has_attachment</tt>. Available values are
  129 + # <tt>:private</tt>, <tt>:public_read_write</tt>, and <tt>:authenticated_read</tt>.
  130 + #
  131 + # === Other options
  132 + #
  133 + # Of course, all the usual configuration options apply, such as content_type and thumbnails:
  134 + #
  135 + # class Photo < ActiveRecord::Base
  136 + # has_attachment :storage => :s3, :content_type => ['application/pdf', :image], :resize_to => 'x50'
  137 + # has_attachment :storage => :s3, :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
  138 + # end
  139 + #
  140 + # === Accessing S3 URLs
  141 + #
  142 + # You can get an object's URL using the s3_url accessor. For example, assuming that for your postcard app
  143 + # you had a bucket name like 'postcard_world_development', and an attachment model called Photo:
  144 + #
  145 + # @postcard.s3_url # => http(s)://s3.amazonaws.com/postcard_world_development/photos/1/mexico.jpg
  146 + #
  147 + # The resulting url is in the form: http(s)://:server/:bucket_name/:table_name/:id/:file.
  148 + # The optional thumbnail argument will output the thumbnail's filename (if any).
  149 + #
  150 + # Additionally, you can get an object's base path relative to the bucket root using
  151 + # <tt>base_path</tt>:
  152 + #
  153 + # @photo.file_base_path # => photos/1
  154 + #
  155 + # And the full path (including the filename) using <tt>full_filename</tt>:
  156 + #
  157 + # @photo.full_filename # => photos/
  158 + #
  159 + # Niether <tt>base_path</tt> or <tt>full_filename</tt> include the bucket name as part of the path.
  160 + # You can retrieve the bucket name using the <tt>bucket_name</tt> method.
  161 + #
  162 + # === Accessing CloudFront URLs
  163 + #
  164 + # You can get an object's CloudFront URL using the cloudfront_url accessor. Using the example from above:
  165 + # @postcard.cloudfront_url # => http://XXXX.cloudfront.net/photos/1/mexico.jpg
  166 + #
  167 + # The resulting url is in the form: http://:distribution_domain/:table_name/:id/:file
  168 + #
  169 + # If you set :cloudfront to true in your model, the public_filename will be the CloudFront
  170 + # URL, not the S3 URL.
  171 + module S3Backend
  172 + class RequiredLibraryNotFoundError < StandardError; end
  173 + class ConfigFileNotFoundError < StandardError; end
  174 +
  175 + def self.included(base) #:nodoc:
  176 + mattr_reader :bucket_name, :s3_config
  177 +
  178 + begin
  179 + require 'aws/s3'
  180 + include AWS::S3
  181 + rescue LoadError
  182 + raise RequiredLibraryNotFoundError.new('AWS::S3 could not be loaded')
  183 + end
  184 +
  185 + begin
  186 + @@s3_config_path = base.attachment_options[:s3_config_path] || File.join(Rails.root, 'config', 'amazon_s3.yml')
  187 + @@s3_config = @@s3_config = YAML.load(ERB.new(File.read(@@s3_config_path)).result)[Rails.env].symbolize_keys
  188 + #rescue
  189 + # raise ConfigFileNotFoundError.new('File %s not found' % @@s3_config_path)
  190 + end
  191 +
  192 + bucket_key = base.attachment_options[:bucket_key]
  193 +
  194 + if bucket_key and s3_config[bucket_key.to_sym]
  195 + eval_string = "def bucket_name()\n \"#{s3_config[bucket_key.to_sym]}\"\nend"
  196 + else
  197 + eval_string = "def bucket_name()\n \"#{s3_config[:bucket_name]}\"\nend"
  198 + end
  199 + base.class_eval(eval_string, __FILE__, __LINE__)
  200 +
  201 + Base.establish_connection!(s3_config.slice(:access_key_id, :secret_access_key, :server, :port, :use_ssl, :persistent, :proxy))
  202 +
  203 + # Bucket.create(@@bucket_name)
  204 +
  205 + base.before_update :rename_file
  206 + end
  207 +
  208 + def self.protocol
  209 + @protocol ||= s3_config[:use_ssl] ? 'https://' : 'http://'
  210 + end
  211 +
  212 + def self.hostname
  213 + @hostname ||= s3_config[:server] || AWS::S3::DEFAULT_HOST
  214 + end
  215 +
  216 + def self.port_string
  217 + @port_string ||= (s3_config[:port].nil? || s3_config[:port] == (s3_config[:use_ssl] ? 443 : 80)) ? '' : ":#{s3_config[:port]}"
  218 + end
  219 +
  220 + def self.distribution_domain
  221 + @distribution_domain = s3_config[:distribution_domain]
  222 + end
  223 +
  224 + module ClassMethods
  225 + def s3_protocol
  226 + Technoweenie::AttachmentFu::Backends::S3Backend.protocol
  227 + end
  228 +
  229 + def s3_hostname
  230 + Technoweenie::AttachmentFu::Backends::S3Backend.hostname
  231 + end
  232 +
  233 + def s3_port_string
  234 + Technoweenie::AttachmentFu::Backends::S3Backend.port_string
  235 + end
  236 +
  237 + def cloudfront_distribution_domain
  238 + Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
  239 + end
  240 + end
  241 +
  242 + # Overwrites the base filename writer in order to store the old filename
  243 + def filename=(value)
  244 + @old_filename = filename unless filename.nil? || @old_filename
  245 + write_attribute :filename, sanitize_filename(value)
  246 + end
  247 +
  248 + # The attachment ID used in the full path of a file
  249 + def attachment_path_id
  250 + ((respond_to?(:parent_id) && parent_id) || id).to_s
  251 + end
  252 +
  253 + # The pseudo hierarchy containing the file relative to the bucket name
  254 + # Example: <tt>:table_name/:id</tt>
  255 + def base_path
  256 + File.join(attachment_options[:path_prefix], attachment_path_id)
  257 + end
  258 +
  259 + # The full path to the file relative to the bucket name
  260 + # Example: <tt>:table_name/:id/:filename</tt>
  261 + def full_filename(thumbnail = nil)
  262 + File.join(base_path, thumbnail_name_for(thumbnail))
  263 + end
  264 +
  265 + # All public objects are accessible via a GET request to the S3 servers. You can generate a
  266 + # url for an object using the s3_url method.
  267 + #
  268 + # @photo.s3_url
  269 + #
  270 + # The resulting url is in the form: <tt>http(s)://:server/:bucket_name/:table_name/:id/:file</tt> where
  271 + # the <tt>:server</tt> variable defaults to <tt>AWS::S3 URL::DEFAULT_HOST</tt> (s3.amazonaws.com) and can be
  272 + # set using the configuration parameters in <tt>#{Rails.root}/config/amazon_s3.yml</tt>.
  273 + #
  274 + # The optional thumbnail argument will output the thumbnail's filename (if any).
  275 + def s3_url(thumbnail = nil)
  276 + File.join(s3_protocol + s3_hostname + s3_port_string, bucket_name, full_filename(thumbnail))
  277 + end
  278 +
  279 + # All public objects are accessible via a GET request to CloudFront. You can generate a
  280 + # url for an object using the cloudfront_url method.
  281 + #
  282 + # @photo.cloudfront_url
  283 + #
  284 + # The resulting url is in the form: <tt>http://:distribution_domain/:table_name/:id/:file</tt> using
  285 + # the <tt>:distribution_domain</tt> variable set in the configuration parameters in <tt>#{Rails.root}/config/amazon_s3.yml</tt>.
  286 + #
  287 + # The optional thumbnail argument will output the thumbnail's filename (if any).
  288 + def cloudfront_url(thumbnail = nil)
  289 + s3_protocol + cloudfront_distribution_domain + "/" + full_filename(thumbnail)
  290 + end
  291 +
  292 + def public_filename(*args)
  293 + if attachment_options[:cloudfront]
  294 + cloudfront_url(*args)
  295 + else
  296 + s3_url(*args)
  297 + end
  298 + end
  299 +
  300 + # All private objects are accessible via an authenticated GET request to the S3 servers. You can generate an
  301 + # authenticated url for an object like this:
  302 + #
  303 + # @photo.authenticated_s3_url
  304 + #
  305 + # By default authenticated urls expire 5 minutes after they were generated.
  306 + #
  307 + # Expiration options can be specified either with an absolute time using the <tt>:expires</tt> option,
  308 + # or with a number of seconds relative to now with the <tt>:expires_in</tt> option:
  309 + #
  310 + # # Absolute expiration date (October 13th, 2025)
  311 + # @photo.authenticated_s3_url(:expires => Time.mktime(2025,10,13).to_i)
  312 + #
  313 + # # Expiration in five hours from now
  314 + # @photo.authenticated_s3_url(:expires_in => 5.hours)
  315 + #
  316 + # You can specify whether the url should go over SSL with the <tt>:use_ssl</tt> option.
  317 + # By default, the ssl settings for the current connection will be used:
  318 + #
  319 + # @photo.authenticated_s3_url(:use_ssl => true)
  320 + #
  321 + # Finally, the optional thumbnail argument will output the thumbnail's filename (if any):
  322 + #
  323 + # @photo.authenticated_s3_url('thumbnail', :expires_in => 5.hours, :use_ssl => true)
  324 + def authenticated_s3_url(*args)
  325 + options = args.extract_options!
  326 + options[:expires_in] = options[:expires_in].to_i if options[:expires_in]
  327 + thumbnail = args.shift
  328 + S3Object.url_for(full_filename(thumbnail), bucket_name, options)
  329 + end
  330 +
  331 + def create_temp_file
  332 + write_to_temp_file current_data
  333 + end
  334 +
  335 + def current_data
  336 + if attachment_options[:encrypted_storage] && self.respond_to?(:encryption_key) && self.encryption_key != nil
  337 + EncryptedData.decrypt_data(S3Object.value(full_filename, bucket_name), self.encryption_key)
  338 + else
  339 + S3Object.value full_filename, bucket_name
  340 + end
  341 + end
  342 +
  343 + def s3_protocol
  344 + Technoweenie::AttachmentFu::Backends::S3Backend.protocol
  345 + end
  346 +
  347 + def s3_hostname
  348 + Technoweenie::AttachmentFu::Backends::S3Backend.hostname
  349 + end
  350 +
  351 + def s3_port_string
  352 + Technoweenie::AttachmentFu::Backends::S3Backend.port_string
  353 + end
  354 +
  355 + def cloudfront_distribution_domain
  356 + Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
  357 + end
  358 +
  359 + protected
  360 + # Called in the after_destroy callback
  361 + def destroy_file
  362 + S3Object.delete full_filename, bucket_name
  363 + end
  364 +
  365 + def rename_file
  366 + return unless @old_filename && @old_filename != filename
  367 +
  368 + old_full_filename = File.join(base_path, @old_filename)
  369 +
  370 + S3Object.rename(
  371 + old_full_filename,
  372 + full_filename,
  373 + bucket_name,
  374 + :access => attachment_options[:s3_access]
  375 + )
  376 +
  377 + @old_filename = nil
  378 + true
  379 + end
  380 +
  381 + def save_to_storage
  382 + if save_attachment?
  383 + if attachment_options[:encrypted_storage]
  384 + S3Object.store(
  385 + full_filename,
  386 + (temp_path ? File.open(temp_path) : temp_data),
  387 + bucket_name,
  388 + :content_type => content_type,
  389 + :cache_control => attachment_options[:cache_control],
  390 + :access => attachment_options[:s3_access],
  391 + 'x-amz-server-side-encryption' => 'AES256',
  392 + 'Content-Disposition' => "attachment; filename=\"#{filename}\""
  393 + )
  394 + else
  395 + S3Object.store(
  396 + full_filename,
  397 + (temp_path ? File.open(temp_path) : temp_data),
  398 + bucket_name,
  399 + :content_type => content_type,
  400 + :cache_control => attachment_options[:cache_control],
  401 + :access => attachment_options[:s3_access]
  402 + )
  403 + end
  404 + end
  405 +
  406 + @old_filename = nil
  407 + true
  408 + end
  409 + end
  410 + end
  411 + end
  412 +end
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/core_image_processor.rb 0 → 100644
... ... @@ -0,0 +1,66 @@
  1 +require 'red_artisan/core_image/processor'
  2 +
  3 +module Technoweenie # :nodoc:
  4 + module AttachmentFu # :nodoc:
  5 + module Processors
  6 + module CoreImageProcessor
  7 + def self.included(base)
  8 + base.send :extend, ClassMethods
  9 + base.alias_method_chain :process_attachment, :processing
  10 + end
  11 +
  12 + module ClassMethods
  13 + def with_image(file, &block)
  14 + block.call OSX::CIImage.from(file)
  15 + end
  16 + end
  17 +
  18 + protected
  19 + def process_attachment_with_processing
  20 + return unless process_attachment_without_processing
  21 + with_image do |img|
  22 + self.width = img.extent.size.width if respond_to?(:width)
  23 + self.height = img.extent.size.height if respond_to?(:height)
  24 + resize_image_or_thumbnail! img
  25 + callback_with_args :after_resize, img
  26 + end if image?
  27 + end
  28 +
  29 + # Performs the actual resizing operation for a thumbnail
  30 + def resize_image(img, size)
  31 + processor = ::RedArtisan::CoreImage::Processor.new(img)
  32 + size = size.first if size.is_a?(Array) && size.length == 1
  33 + if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
  34 + if size.is_a?(Fixnum)
  35 + processor.fit(size)
  36 + else
  37 + processor.resize(size[0], size[1])
  38 + end
  39 + else
  40 + new_size = [img.extent.size.width, img.extent.size.height] / size.to_s
  41 + processor.resize(new_size[0], new_size[1])
  42 + end
  43 +
  44 + processor.render do |result|
  45 + self.width = result.extent.size.width if respond_to?(:width)
  46 + self.height = result.extent.size.height if respond_to?(:height)
  47 + out_file = random_tempfile_filename
  48 + temp_paths.unshift Tempfile.new(out_file, Technoweenie::AttachmentFu.tempfile_path).path
  49 + properties = nil
  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
  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 + #
  58 + self.size = File.size(self.temp_path)
  59 + end
  60 + end
  61 + end
  62 + end
  63 + end
  64 +end
  65 +
  66 +
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/gd2_processor.rb 0 → 100644
... ... @@ -0,0 +1,59 @@
  1 +require 'rubygems'
  2 +require 'gd2'
  3 +module Technoweenie # :nodoc:
  4 + module AttachmentFu # :nodoc:
  5 + module Processors
  6 + module Gd2Processor
  7 + def self.included(base)
  8 + base.send :extend, ClassMethods
  9 + base.alias_method_chain :process_attachment, :processing
  10 + end
  11 +
  12 + module ClassMethods
  13 + # Yields a block containing a GD2 Image for the given binary data.
  14 + def with_image(file, &block)
  15 + im = GD2::Image.import(file)
  16 + block.call(im)
  17 + end
  18 + end
  19 +
  20 + protected
  21 + def process_attachment_with_processing
  22 + return unless process_attachment_without_processing && image?
  23 + with_image do |img|
  24 + resize_image_or_thumbnail! img
  25 + self.width = img.width
  26 + self.height = img.height
  27 + callback_with_args :after_resize, img
  28 + end
  29 + end
  30 +
  31 + # Performs the actual resizing operation for a thumbnail
  32 + def resize_image(img, size)
  33 + size = size.first if size.is_a?(Array) && size.length == 1
  34 + if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
  35 + if size.is_a?(Fixnum)
  36 + # Borrowed from image science's #thumbnail method and adapted
  37 + # for this.
  38 + scale = size.to_f / (img.width > img.height ? img.width.to_f : img.height.to_f)
  39 + img.resize!((img.width * scale).round(1), (img.height * scale).round(1), false)
  40 + else
  41 + img.resize!(size.first, size.last, false)
  42 + end
  43 + else
  44 + w, h = [img.width, img.height] / size.to_s
  45 + img.resize!(w, h, false)
  46 + end
  47 + self.width = img.width if respond_to?(:width)
  48 + self.height = img.height if respond_to?(:height)
  49 + out_file = random_tempfile_filename
  50 + temp_paths.unshift out_file
  51 + jpeg = out_file =~ /\.jpe?g\z/i
  52 + quality = jpeg && get_jpeg_quality
  53 + self.size = img.export(self.temp_path, quality ? { :quality => quality } : {})
  54 + end
  55 +
  56 + end
  57 + end
  58 + end
  59 +end
0 60 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/image_science_processor.rb 0 → 100644
... ... @@ -0,0 +1,80 @@
  1 +require 'image_science'
  2 +module Technoweenie # :nodoc:
  3 + module AttachmentFu # :nodoc:
  4 + module Processors
  5 + module ImageScienceProcessor
  6 + def self.included(base)
  7 + base.send :extend, ClassMethods
  8 + base.alias_method_chain :process_attachment, :processing
  9 + end
  10 +
  11 + module ClassMethods
  12 + # Yields a block containing an Image Science image for the given binary data.
  13 + def with_image(file, &block)
  14 + ::ImageScience.with_image file, &block
  15 + end
  16 + end
  17 +
  18 + protected
  19 + def process_attachment_with_processing
  20 + return unless process_attachment_without_processing && image?
  21 + with_image do |img|
  22 + self.width = img.width if respond_to?(:width)
  23 + self.height = img.height if respond_to?(:height)
  24 + resize_image_or_thumbnail! img
  25 + end
  26 + end
  27 +
  28 + # Performs the actual resizing operation for a thumbnail
  29 + def resize_image(img, size)
  30 + # create a dummy temp file to write to
  31 + # ImageScience doesn't handle all gifs properly, so it converts them to
  32 + # pngs for thumbnails. It has something to do with trying to save gifs
  33 + # with a larger palette than 256 colors, which is all the gif format
  34 + # supports.
  35 + filename.sub! /gif$/i, 'png'
  36 + content_type.sub!(/gif$/, 'png')
  37 + temp_paths.unshift write_to_temp_file(filename)
  38 + grab_dimensions = lambda do |img|
  39 + self.width = img.width if respond_to?(:width)
  40 + self.height = img.height if respond_to?(:height)
  41 +
  42 + # We don't check for quality being a 0-100 value as we also allow FreeImage JPEG_xxx constants.
  43 + quality = content_type[/jpe?g/i] && get_jpeg_quality(false)
  44 + # Traditional ImageScience has a 1-arg save method, tdd-image_science has 1 mandatory + 1 optional
  45 + if quality && img.method(:save).arity == -2
  46 + img.save self.temp_path, quality
  47 + else
  48 + img.save self.temp_path
  49 + end
  50 + self.size = File.size(self.temp_path)
  51 + callback_with_args :after_resize, img
  52 + end
  53 +
  54 + size = size.first if size.is_a?(Array) && size.length == 1
  55 + if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
  56 + if size.is_a?(Fixnum)
  57 + img.thumbnail(size, &grab_dimensions)
  58 + else
  59 + img.resize(size[0], size[1], &grab_dimensions)
  60 + end
  61 + else
  62 + new_size = [img.width, img.height] / size.to_s
  63 + if size.ends_with?('!')
  64 + aspect = new_size[0].to_f / new_size[1].to_f
  65 + ih, iw = img.height, img.width
  66 + w, h = (ih * aspect), (iw / aspect)
  67 + w = [iw, w].min.to_i
  68 + h = [ih, h].min.to_i
  69 + img.with_crop((iw-w)/2, (ih-h)/2, (iw+w)/2, (ih+h)/2) { |crop|
  70 + crop.resize(new_size[0], new_size[1], &grab_dimensions)
  71 + }
  72 + else
  73 + img.resize(new_size[0], new_size[1], &grab_dimensions)
  74 + end
  75 + end
  76 + end
  77 + end
  78 + end
  79 + end
  80 +end
0 81 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/mini_magick_processor.rb 0 → 100644
... ... @@ -0,0 +1,142 @@
  1 +require 'mini_magick'
  2 +module Technoweenie # :nodoc:
  3 + module AttachmentFu # :nodoc:
  4 + module Processors
  5 + module MiniMagickProcessor
  6 + def self.included(base)
  7 + base.send :extend, ClassMethods
  8 + base.alias_method_chain :process_attachment, :processing
  9 + end
  10 +
  11 + module ClassMethods
  12 + # Yields a block containing an MiniMagick Image for the given binary data.
  13 + def with_image(file, &block)
  14 + begin
  15 + binary_data = file.is_a?(MiniMagick::Image) ? file : MiniMagick::Image.open(file) unless !Object.const_defined?(:MiniMagick)
  16 + rescue
  17 + # Log the failure to load the image.
  18 + logger.debug("Exception working with image: #{$!}")
  19 + binary_data = nil
  20 + end
  21 + block.call binary_data if block && binary_data
  22 + ensure
  23 + !binary_data.nil?
  24 + end
  25 + end
  26 +
  27 + protected
  28 + def process_attachment_with_processing
  29 + return unless process_attachment_without_processing
  30 + with_image do |img|
  31 + resize_image_or_thumbnail! img
  32 + self.width = img[:width] if respond_to?(:width)
  33 + self.height = img[:height] if respond_to?(:height)
  34 + callback_with_args :after_resize, img
  35 + end if image?
  36 + end
  37 +
  38 + # Performs the actual resizing operation for a thumbnail
  39 + def resize_image(img, size)
  40 + size = size.first if size.is_a?(Array) && size.length == 1
  41 + format = img[:format]
  42 + img.combine_options do |commands|
  43 + commands.strip unless attachment_options[:keep_profile]
  44 +
  45 + # GIF is not handled correctly, so we move to PNG, as in other processors…
  46 + if format == 'GIF'
  47 + img.format('PNG')
  48 + end
  49 +
  50 + if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
  51 + if size.is_a?(Fixnum)
  52 + size = [size, size]
  53 + commands.resize(size.join('x'))
  54 + else
  55 + commands.resize(size.join('x') + '!')
  56 + end
  57 + # extend to thumbnail size
  58 + elsif size.is_a?(String) and size =~ /e$/
  59 + size = size.gsub(/e/, '')
  60 + commands.resize(size.to_s + '>')
  61 + commands.background('#ffffff')
  62 + commands.gravity('center')
  63 + commands.extent(size)
  64 + # crop thumbnail, the smart way
  65 + elsif size.is_a?(String) and size =~ /c$/
  66 + size = size.gsub(/c/, '')
  67 +
  68 + # calculate sizes and aspect ratio
  69 + thumb_width, thumb_height = size.split("x")
  70 + thumb_width = thumb_width.to_f
  71 + thumb_height = thumb_height.to_f
  72 +
  73 + thumb_aspect = thumb_width.to_f / thumb_height.to_f
  74 + image_width, image_height = img[:width].to_f, img[:height].to_f
  75 + image_aspect = image_width / image_height
  76 +
  77 + # only crop if image is not smaller in both dimensions
  78 + unless image_width < thumb_width and image_height < thumb_height
  79 + command = calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
  80 +
  81 + # crop image
  82 + commands.extract(command)
  83 + end
  84 +
  85 + # don not resize if image is not as height or width then thumbnail
  86 + if image_width < thumb_width or image_height < thumb_height
  87 + commands.background('#ffffff')
  88 + commands.gravity('center')
  89 + commands.extent(size)
  90 + # resize image
  91 + else
  92 + commands.resize("#{size.to_s}")
  93 + end
  94 + # crop end
  95 + else
  96 + commands.resize(size.to_s)
  97 + end
  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
  107 + temp_paths.unshift img
  108 + self.size = File.size(self.temp_path)
  109 + end
  110 +
  111 + def calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
  112 + # only crop if image is not smaller in both dimensions
  113 +
  114 + # special cases, image smaller in one dimension then thumbsize
  115 + if image_width < thumb_width
  116 + offset = (image_height / 2) - (thumb_height / 2)
  117 + command = "#{image_width}x#{thumb_height}+0+#{offset}"
  118 + elsif image_height < thumb_height
  119 + offset = (image_width / 2) - (thumb_width / 2)
  120 + command = "#{thumb_width}x#{image_height}+#{offset}+0"
  121 +
  122 + # normal thumbnail generation
  123 + # calculate height and offset y, width is fixed
  124 + elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
  125 + height = image_width / thumb_aspect
  126 + offset = (image_height / 2) - (height / 2)
  127 + command = "#{image_width}x#{height}+0+#{offset}"
  128 + # calculate width and offset x, height is fixed
  129 + else
  130 + width = image_height * thumb_aspect
  131 + offset = (image_width / 2) - (width / 2)
  132 + command = "#{width}x#{image_height}+#{offset}+0"
  133 + end
  134 + # crop image
  135 + command
  136 + end
  137 +
  138 +
  139 + end
  140 + end
  141 + end
  142 +end
0 143 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/rmagick_processor.rb 0 → 100644
... ... @@ -0,0 +1,66 @@
  1 +require 'RMagick'
  2 +module Technoweenie # :nodoc:
  3 + module AttachmentFu # :nodoc:
  4 + module Processors
  5 + module RmagickProcessor
  6 + def self.included(base)
  7 + base.send :extend, ClassMethods
  8 + base.alias_method_chain :process_attachment, :processing
  9 + end
  10 +
  11 + module ClassMethods
  12 + # Yields a block containing an RMagick Image for the given binary data.
  13 + def with_image(file, &block)
  14 + begin
  15 + binary_data = file.is_a?(Magick::Image) ? file : Magick::Image.read(file).first unless !Object.const_defined?(:Magick)
  16 + binary_data && binary_data.auto_orient!
  17 + rescue
  18 + # Log the failure to load the image. This should match ::Magick::ImageMagickError
  19 + # but that would cause acts_as_attachment to require rmagick.
  20 + logger.debug("Exception working with image: #{$!}")
  21 + binary_data = nil
  22 + end
  23 + block.call binary_data if block && binary_data
  24 + ensure
  25 + !binary_data.nil?
  26 + end
  27 + end
  28 +
  29 + protected
  30 + def process_attachment_with_processing
  31 + return unless process_attachment_without_processing
  32 + with_image do |img|
  33 + resize_image_or_thumbnail! img
  34 + self.width = img.columns if respond_to?(:width)
  35 + self.height = img.rows if respond_to?(:height)
  36 + callback_with_args :after_resize, img
  37 + end if image?
  38 + end
  39 +
  40 + # Performs the actual resizing operation for a thumbnail
  41 + def resize_image(img, size)
  42 + size = size.first if size.is_a?(Array) && size.length == 1 && !size.first.is_a?(Fixnum)
  43 + if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
  44 + size = [size, size] if size.is_a?(Fixnum)
  45 + img.thumbnail!(*size)
  46 + elsif size.is_a?(String) && size =~ /^c.*$/ # Image cropping - example geometry string: c75x75
  47 + dimensions = size[1..size.size].split("x")
  48 + img.crop_resized!(dimensions[0].to_i, dimensions[1].to_i)
  49 + else
  50 + img.change_geometry(size.to_s) { |cols, rows, image|
  51 + image.resize!(cols<1 ? 1 : cols, rows<1 ? 1 : rows)
  52 + }
  53 + end
  54 + self.width = img.columns if respond_to?(:width)
  55 + self.height = img.rows if respond_to?(:height)
  56 + img = img.sharpen if attachment_options[:sharpen_on_resize] && img.changed?
  57 + img.strip! unless attachment_options[:keep_profile]
  58 + quality = img.format.to_s[/JPEG/] && get_jpeg_quality
  59 + out_file = write_to_temp_file(img.to_blob { self.quality = quality if quality })
  60 + temp_paths.unshift out_file
  61 + self.size = File.size(self.temp_path)
  62 + end
  63 + end
  64 + end
  65 + end
  66 +end
... ...
vendor/plugins/pothoven-attachment_fu/rackspace_cloudfiles.yml.tpl 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +development:
  2 + container_name: appname_development
  3 + username:
  4 + api_key:
  5 +
  6 +test:
  7 + container_name: appname_test
  8 + username:
  9 + api_key:
  10 +
  11 +production:
  12 + container_name: appname_production
  13 + username:
  14 + api_key:
... ...
vendor/plugins/pothoven-attachment_fu/test/backends/db_file_test.rb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
  2 +
  3 +class DbFileTest < Test::Unit::TestCase
  4 + include BaseAttachmentTests
  5 + attachment_model Attachment
  6 +
  7 + def test_should_call_after_attachment_saved(klass = Attachment)
  8 + attachment_model.saves = 0
  9 + assert_created do
  10 + upload_file :filename => '/files/rails.png'
  11 + end
  12 + assert_equal 1, attachment_model.saves
  13 + end
  14 +
  15 + test_against_subclass :test_should_call_after_attachment_saved, Attachment
  16 +end
0 17 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/backends/file_system_test.rb 0 → 100644
... ... @@ -0,0 +1,143 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
  2 +require 'digest/sha2'
  3 +
  4 +class FileSystemTest < Test::Unit::TestCase
  5 + include BaseAttachmentTests
  6 + attachment_model FileAttachment
  7 +
  8 + def test_filesystem_size_for_file_attachment(klass = FileAttachment)
  9 + attachment_model klass
  10 + assert_created 1 do
  11 + attachment = upload_file :filename => '/files/rails.png'
  12 + assert_equal attachment.size, File.open(attachment.full_filename).stat.size
  13 + end
  14 + end
  15 +
  16 + test_against_subclass :test_filesystem_size_for_file_attachment, FileAttachment
  17 +
  18 + def test_should_not_overwrite_file_attachment(klass = FileAttachment)
  19 + attachment_model klass
  20 + assert_created 2 do
  21 + real = upload_file :filename => '/files/rails.png'
  22 + assert_valid real
  23 + assert !real.new_record?, real.errors.full_messages.join("\n")
  24 + assert !real.size.zero?
  25 +
  26 + fake = upload_file :filename => '/files/fake/rails.png'
  27 + assert_valid fake
  28 + assert !fake.size.zero?
  29 +
  30 + assert_not_equal File.open(real.full_filename).stat.size, File.open(fake.full_filename).stat.size
  31 + end
  32 + end
  33 +
  34 + test_against_subclass :test_should_not_overwrite_file_attachment, FileAttachment
  35 +
  36 + def test_should_store_file_attachment_in_filesystem(klass = FileAttachment)
  37 + attachment_model klass
  38 + attachment = nil
  39 + assert_created do
  40 + attachment = upload_file :filename => '/files/rails.png'
  41 + assert_valid attachment
  42 + assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
  43 + end
  44 + attachment
  45 + end
  46 +
  47 + test_against_subclass :test_should_store_file_attachment_in_filesystem, FileAttachment
  48 +
  49 + def test_should_delete_old_file_when_updating(klass = FileAttachment)
  50 + attachment_model klass
  51 + attachment = upload_file :filename => '/files/rails.png'
  52 + old_filename = attachment.full_filename
  53 + assert_not_created do
  54 + use_temp_file 'files/rails.png' do |file|
  55 + attachment.filename = 'rails2.png'
  56 + attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
  57 + attachment.save!
  58 + assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
  59 + assert !File.exists?(old_filename), "#{old_filename} still exists"
  60 + end
  61 + end
  62 + end
  63 +
  64 + test_against_subclass :test_should_delete_old_file_when_updating, FileAttachment
  65 +
  66 + def test_should_delete_old_file_when_renaming(klass = FileAttachment)
  67 + attachment_model klass
  68 + attachment = upload_file :filename => '/files/rails.png'
  69 + old_filename = attachment.full_filename
  70 + assert_not_created do
  71 + attachment.filename = 'rails2.png'
  72 + attachment.save
  73 + assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
  74 + assert !File.exists?(old_filename), "#{old_filename} still exists"
  75 + assert !attachment.reload.size.zero?
  76 + assert_equal 'rails2.png', attachment.filename
  77 + end
  78 + end
  79 +
  80 + test_against_subclass :test_should_delete_old_file_when_renaming, FileAttachment
  81 +
  82 + def test_path_partitioning_works_on_integer_id(klass = FileAttachment)
  83 + attachment_model klass
  84 +
  85 + # Create a random attachment object, doesn't matter what.
  86 + attachment = upload_file :filename => '/files/rails.png'
  87 + old_id = attachment.id
  88 + attachment.id = 1
  89 +
  90 + begin
  91 + assert_equal ["0000", "0001", "bar.txt"], attachment.send(:partitioned_path, "bar.txt")
  92 + ensure
  93 + attachment.id = old_id
  94 + end
  95 + end
  96 +
  97 + test_against_subclass :test_path_partitioning_works_on_integer_id, FileAttachment
  98 +
  99 + def test_path_partitioning_with_string_id_works_by_generating_hash(klass = FileAttachmentWithStringId)
  100 + attachment_model klass
  101 +
  102 + # Create a random attachment object, doesn't matter what.
  103 + attachment = upload_file :filename => '/files/rails.png'
  104 + old_id = attachment.id
  105 + attachment.id = "hello world some long string"
  106 + hash = Digest::SHA512.hexdigest("hello world some long string")
  107 +
  108 + begin
  109 + assert_equal [
  110 + hash[0..31],
  111 + hash[32..63],
  112 + hash[64..95],
  113 + hash[96..127],
  114 + "bar.txt"
  115 + ], attachment.send(:partitioned_path, "bar.txt")
  116 + ensure
  117 + attachment.id = old_id
  118 + end
  119 + end
  120 +
  121 + test_against_subclass :test_path_partitioning_with_string_id_works_by_generating_hash, FileAttachmentWithStringId
  122 +
  123 + def test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid(klass = FileAttachmentWithUuid)
  124 + attachment_model klass
  125 +
  126 + # Create a random attachment object, doesn't matter what.
  127 + attachment = upload_file :filename => '/files/rails.png'
  128 + old_id = attachment.id
  129 + attachment.id = "0c0743b698483569dc65909a8cdb3bf9"
  130 +
  131 + begin
  132 + assert_equal [
  133 + "0c0743b698483569",
  134 + "dc65909a8cdb3bf9",
  135 + "bar.txt"
  136 + ], attachment.send(:partitioned_path, "bar.txt")
  137 + ensure
  138 + attachment.id = old_id
  139 + end
  140 + end
  141 +
  142 + test_against_subclass :test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid, FileAttachmentWithUuid
  143 +end
... ...
vendor/plugins/pothoven-attachment_fu/test/backends/remote/cloudfiles_test.rb 0 → 100644
... ... @@ -0,0 +1,102 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
  2 +require 'net/http'
  3 +
  4 +class CloudfilesTest < Test::Unit::TestCase
  5 + def self.test_CloudFiles?
  6 + true unless ENV["TEST_CLOUDFILES"] == "false"
  7 + end
  8 +
  9 + if test_CloudFiles? && File.exist?(File.join(File.dirname(__FILE__), '../../rackspace_cloudfiles.yml'))
  10 + include BaseAttachmentTests
  11 + attachment_model CloudFilesAttachment
  12 +
  13 + def test_should_create_correct_container_name(klass = CloudFilesAttachment)
  14 + attachment_model klass
  15 + attachment = upload_file :filename => '/files/rails.png'
  16 + assert_equal attachment.cloudfiles_config[:container_name], attachment.container_name
  17 + end
  18 +
  19 + test_against_subclass :test_should_create_correct_container_name, CloudFilesAttachment
  20 +
  21 + def test_should_create_default_path_prefix(klass = CloudFilesAttachment)
  22 + attachment_model klass
  23 + attachment = upload_file :filename => '/files/rails.png'
  24 + assert_equal File.join(attachment_model.table_name, attachment.attachment_path_id), attachment.base_path
  25 + end
  26 +
  27 + test_against_subclass :test_should_create_default_path_prefix, CloudFilesAttachment
  28 +
  29 + def test_should_create_custom_path_prefix(klass = CloudFilesWithPathPrefixAttachment)
  30 + attachment_model klass
  31 + attachment = upload_file :filename => '/files/rails.png'
  32 + assert_equal File.join('some/custom/path/prefix', attachment.attachment_path_id), attachment.base_path
  33 + end
  34 +
  35 + test_against_subclass :test_should_create_custom_path_prefix, CloudFilesWithPathPrefixAttachment
  36 +
  37 +
  38 + def test_should_create_valid_url(klass = CloudFilesAttachment)
  39 + attachment_model klass
  40 + attachment = upload_file :filename => '/files/rails.png'
  41 + assert_match(%r!http://cdn.cloudfiles.mosso.com/(.*?)/cloud_files_attachments/1/rails.png!, attachment.cloudfiles_url)
  42 + end
  43 +
  44 + test_against_subclass :test_should_create_valid_url, CloudFilesAttachment
  45 +
  46 + def test_should_save_attachment(klass = CloudFilesAttachment)
  47 + attachment_model klass
  48 + assert_created do
  49 + attachment = upload_file :filename => '/files/rails.png'
  50 + assert_valid attachment
  51 + assert attachment.image?
  52 + assert !attachment.size.zero?
  53 + assert_kind_of Net::HTTPOK, http_response_for(attachment.cloudfiles_url)
  54 + end
  55 + end
  56 +
  57 + test_against_subclass :test_should_save_attachment, CloudFilesAttachment
  58 +
  59 + def test_should_delete_attachment_from_cloud_files_when_attachment_record_destroyed(klass = CloudFilesAttachment)
  60 + attachment_model klass
  61 + attachment = upload_file :filename => '/files/rails.png'
  62 +
  63 + urls = [attachment.cloudfiles_url] + attachment.thumbnails.collect(&:cloudfiles_url)
  64 +
  65 + urls.each {|url| assert_kind_of Net::HTTPOK, http_response_for(url) }
  66 + attachment.destroy
  67 + urls.each do |url|
  68 + begin
  69 + http_response_for(url)
  70 + rescue Net::HTTPForbidden, Net::HTTPNotFound
  71 + nil
  72 + end
  73 + end
  74 + end
  75 +
  76 + test_against_subclass :test_should_delete_attachment_from_cloud_files_when_attachment_record_destroyed, CloudFilesAttachment
  77 +
  78 +
  79 +
  80 + protected
  81 + def http_response_for(url)
  82 + url = URI.parse(url)
  83 + Net::HTTP.start(url.host, url.port) {|http| http.request_head(url.path) }
  84 + end
  85 +
  86 + def s3_protocol
  87 + Technoweenie::AttachmentFu::Backends::S3Backend.protocol
  88 + end
  89 +
  90 + def s3_hostname
  91 + Technoweenie::AttachmentFu::Backends::S3Backend.hostname
  92 + end
  93 +
  94 + def s3_port_string
  95 + Technoweenie::AttachmentFu::Backends::S3Backend.port_string
  96 + end
  97 + else
  98 + def test_flunk_s3
  99 + puts "s3 config file not loaded, tests not running"
  100 + end
  101 + end
  102 +end
0 103 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/backends/remote/s3_test.rb 0 → 100644
... ... @@ -0,0 +1,119 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
  2 +require 'net/http'
  3 +
  4 +class S3Test < Test::Unit::TestCase
  5 + def self.test_S3?
  6 + true unless ENV["TEST_S3"] == "false"
  7 + end
  8 +
  9 + if test_S3? && File.exist?(File.join(File.dirname(__FILE__), '../../amazon_s3.yml'))
  10 + include BaseAttachmentTests
  11 + attachment_model S3Attachment
  12 +
  13 + def test_should_create_correct_bucket_name(klass = S3Attachment)
  14 + attachment_model klass
  15 + attachment = upload_file :filename => '/files/rails.png'
  16 + assert_equal attachment.s3_config[:bucket_name], attachment.bucket_name
  17 + end
  18 +
  19 + test_against_subclass :test_should_create_correct_bucket_name, S3Attachment
  20 +
  21 + def test_should_create_default_path_prefix(klass = S3Attachment)
  22 + attachment_model klass
  23 + attachment = upload_file :filename => '/files/rails.png'
  24 + assert_equal File.join(attachment_model.table_name, attachment.attachment_path_id), attachment.base_path
  25 + end
  26 +
  27 + test_against_subclass :test_should_create_default_path_prefix, S3Attachment
  28 +
  29 + def test_should_create_custom_path_prefix(klass = S3WithPathPrefixAttachment)
  30 + attachment_model klass
  31 + attachment = upload_file :filename => '/files/rails.png'
  32 + assert_equal File.join('some/custom/path/prefix', attachment.attachment_path_id), attachment.base_path
  33 + end
  34 +
  35 + test_against_subclass :test_should_create_custom_path_prefix, S3WithPathPrefixAttachment
  36 +
  37 + def test_should_create_valid_url(klass = S3Attachment)
  38 + attachment_model klass
  39 + attachment = upload_file :filename => '/files/rails.png'
  40 + assert_equal "#{s3_protocol}#{s3_hostname}#{s3_port_string}/#{attachment.bucket_name}/#{attachment.full_filename}", attachment.s3_url
  41 + end
  42 +
  43 + test_against_subclass :test_should_create_valid_url, S3Attachment
  44 +
  45 + def test_should_create_authenticated_url(klass = S3Attachment)
  46 + attachment_model klass
  47 + attachment = upload_file :filename => '/files/rails.png'
  48 + assert_match /^http.+AWSAccessKeyId.+Expires.+Signature.+/, attachment.authenticated_s3_url(:use_ssl => true)
  49 + end
  50 +
  51 + test_against_subclass :test_should_create_authenticated_url, S3Attachment
  52 +
  53 + def test_should_create_authenticated_url_for_thumbnail(klass = S3Attachment)
  54 + attachment_model klass
  55 + attachment = upload_file :filename => '/files/rails.png'
  56 + ['large', :large].each do |thumbnail|
  57 + assert_match(
  58 + /^http.+rails_large\.png.+AWSAccessKeyId.+Expires.+Signature/,
  59 + attachment.authenticated_s3_url(thumbnail),
  60 + "authenticated_s3_url failed with #{thumbnail.class} parameter"
  61 + )
  62 + end
  63 + end
  64 +
  65 + def test_should_save_attachment(klass = S3Attachment)
  66 + attachment_model klass
  67 + assert_created do
  68 + attachment = upload_file :filename => '/files/rails.png'
  69 + assert_valid attachment
  70 + assert attachment.image?
  71 + assert !attachment.size.zero?
  72 + assert_kind_of Net::HTTPOK, http_response_for(attachment.s3_url)
  73 + end
  74 + end
  75 +
  76 + test_against_subclass :test_should_save_attachment, S3Attachment
  77 +
  78 + def test_should_delete_attachment_from_s3_when_attachment_record_destroyed(klass = S3Attachment)
  79 + attachment_model klass
  80 + attachment = upload_file :filename => '/files/rails.png'
  81 +
  82 + urls = [attachment.s3_url] + attachment.thumbnails.collect(&:s3_url)
  83 +
  84 + urls.each {|url| assert_kind_of Net::HTTPOK, http_response_for(url) }
  85 + attachment.destroy
  86 + urls.each do |url|
  87 + begin
  88 + http_response_for(url)
  89 + rescue Net::HTTPForbidden, Net::HTTPNotFound
  90 + nil
  91 + end
  92 + end
  93 + end
  94 +
  95 + test_against_subclass :test_should_delete_attachment_from_s3_when_attachment_record_destroyed, S3Attachment
  96 +
  97 + protected
  98 + def http_response_for(url)
  99 + url = URI.parse(url)
  100 + Net::HTTP.start(url.host, url.port) {|http| http.request_head(url.path) }
  101 + end
  102 +
  103 + def s3_protocol
  104 + Technoweenie::AttachmentFu::Backends::S3Backend.protocol
  105 + end
  106 +
  107 + def s3_hostname
  108 + Technoweenie::AttachmentFu::Backends::S3Backend.hostname
  109 + end
  110 +
  111 + def s3_port_string
  112 + Technoweenie::AttachmentFu::Backends::S3Backend.port_string
  113 + end
  114 + else
  115 + def test_flunk_s3
  116 + puts "s3 config file not loaded, tests not running"
  117 + end
  118 + end
  119 +end
0 120 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/base_attachment_tests.rb 0 → 100644
... ... @@ -0,0 +1,77 @@
  1 +module BaseAttachmentTests
  2 + def test_should_create_file_from_uploaded_file
  3 + assert_created do
  4 + attachment = upload_file :filename => '/files/foo.txt', :content_type => 'text/plain'
  5 + assert_valid attachment
  6 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  7 + assert !attachment.image?
  8 + assert !attachment.size.zero?
  9 + #assert_equal 3, attachment.size
  10 + assert_nil attachment.width
  11 + assert_nil attachment.height
  12 + end
  13 + end
  14 +
  15 + def test_should_create_file_from_merb_temp_file
  16 + assert_created do
  17 + attachment = upload_merb_file :filename => '/files/foo.txt', :content_type => 'text/plain'
  18 + assert_valid attachment
  19 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  20 + assert !attachment.image?
  21 + assert !attachment.size.zero?
  22 + #assert_equal 3, attachment.size
  23 + assert_nil attachment.width
  24 + assert_nil attachment.height
  25 + end
  26 + end
  27 +
  28 + def test_reassign_attribute_data
  29 + assert_created 1 do
  30 + attachment = upload_file :filename => '/files/rails.png'
  31 + assert_valid attachment
  32 + assert attachment.size > 0, "no data was set"
  33 +
  34 + attachment.set_temp_data 'wtf'
  35 + assert attachment.save_attachment?
  36 + attachment.save!
  37 +
  38 + assert_equal 'wtf', attachment_model.find(attachment.id).send(:current_data)
  39 + end
  40 + end
  41 +
  42 + def test_no_reassign_attribute_data_on_nil
  43 + assert_created 1 do
  44 + attachment = upload_file :filename => '/files/rails.png'
  45 + assert_valid attachment
  46 + assert attachment.size > 0, "no data was set"
  47 +
  48 + attachment.set_temp_data nil
  49 + assert !attachment.save_attachment?
  50 + end
  51 + end
  52 +
  53 + def test_should_overwrite_old_contents_when_updating
  54 + attachment = upload_file :filename => '/files/rails.png'
  55 + assert_not_created do # no new db_file records
  56 + use_temp_file 'files/rails.png' do |file|
  57 + attachment.filename = 'rails2.png'
  58 + attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
  59 + attachment.save!
  60 + end
  61 + end
  62 + end
  63 +
  64 + def test_should_save_without_updating_file
  65 + attachment = upload_file :filename => '/files/foo.txt'
  66 + assert_valid attachment
  67 + assert !attachment.save_attachment?
  68 + assert_nothing_raised { attachment.save! }
  69 + end
  70 +
  71 + def test_should_handle_nil_file_upload
  72 + attachment = attachment_model.create :uploaded_data => ''
  73 + assert_raise ActiveRecord::RecordInvalid do
  74 + attachment.save!
  75 + end
  76 + end
  77 +end
0 78 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/basic_test.rb 0 → 100644
... ... @@ -0,0 +1,121 @@
  1 +# -*- coding: utf-8 -*-
  2 +require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
  3 +
  4 +class BasicTest < Test::Unit::TestCase
  5 + def test_should_set_default_min_size
  6 + assert_equal 1, Attachment.attachment_options[:min_size]
  7 + end
  8 +
  9 + def test_should_set_default_max_size
  10 + assert_equal 1.megabyte, Attachment.attachment_options[:max_size]
  11 + end
  12 +
  13 + def test_should_set_default_size
  14 + assert_equal (1..1.megabyte), Attachment.attachment_options[:size]
  15 + end
  16 +
  17 + def test_should_set_default_thumbnails_option
  18 + assert_equal Hash.new, Attachment.attachment_options[:thumbnails]
  19 + end
  20 +
  21 + def test_should_set_default_thumbnail_class
  22 + assert_equal Attachment, Attachment.attachment_options[:thumbnail_class]
  23 + end
  24 +
  25 + def test_should_normalize_content_types_to_array
  26 + assert_equal %w(pdf), PdfAttachment.attachment_options[:content_type]
  27 + assert_equal %w(pdf doc txt), DocAttachment.attachment_options[:content_type]
  28 + assert_equal Technoweenie::AttachmentFu.content_types, ImageAttachment.attachment_options[:content_type]
  29 + assert_equal ['pdf'] + Technoweenie::AttachmentFu.content_types, ImageOrPdfAttachment.attachment_options[:content_type]
  30 + end
  31 +
  32 + def test_should_sanitize_content_type
  33 + @attachment = Attachment.new :content_type => ' foo '
  34 + assert_equal 'foo', @attachment.content_type
  35 + end
  36 +
  37 + def test_should_sanitize_filenames
  38 + @attachment = Attachment.new :filename => 'blah/foo.bar'
  39 + assert_equal 'foo.bar', @attachment.filename
  40 +
  41 + @attachment.filename = 'blah\\foo.bar'
  42 + assert_equal 'foo.bar', @attachment.filename
  43 +
  44 + @attachment.filename = 'f o!O-.bar'
  45 + assert_equal 'f_o_O-.bar', @attachment.filename
  46 +
  47 +# @attachment.filename = 'sheeps_says_bææ'
  48 +# assert_equal 'sheeps_says_b__', @attachment.filename
  49 +
  50 + @attachment.filename = nil
  51 + assert_nil @attachment.filename
  52 + end
  53 +
  54 + def test_should_convert_thumbnail_name
  55 + @attachment = FileAttachment.new :filename => 'foo.bar'
  56 + assert_equal 'foo.bar', @attachment.thumbnail_name_for(nil)
  57 + assert_equal 'foo.bar', @attachment.thumbnail_name_for('')
  58 + assert_equal 'foo_blah.bar', @attachment.thumbnail_name_for(:blah)
  59 + assert_equal 'foo_blah.blah.bar', @attachment.thumbnail_name_for('blah.blah')
  60 +
  61 + @attachment.filename = 'foo.bar.baz'
  62 + assert_equal 'foo.bar_blah.baz', @attachment.thumbnail_name_for(:blah)
  63 + end
  64 +
  65 + def test_should_require_valid_thumbnails_option
  66 + klass = Class.new(ActiveRecord::Base)
  67 + assert_raise ArgumentError do
  68 + klass.has_attachment :thumbnails => []
  69 + end
  70 + end
  71 +
  72 + class ::ImageWithPolymorphicThumbsAttachment
  73 + cattr_accessor :thumbnail_creations
  74 +
  75 + def create_or_update_thumbnail(path, thumb, *size)
  76 + @@thumbnail_creations[thumb] = size.size == 1 ? size.first : size
  77 + end
  78 +
  79 + def self.reset_creations
  80 + @@thumbnail_creations = {}
  81 + end
  82 + end
  83 +
  84 + def test_should_handle_polymorphic_thumbnails_option
  85 + assert_polymorphic_thumb_creation nil,
  86 + :thumb => [50, 50], :geometry => 'x50'
  87 + assert_polymorphic_thumb_creation 'Product',
  88 + :thumb => [50, 50], :geometry => 'x50', :large_thumb => '169x169!', :zoomed => '500x500>'
  89 + assert_polymorphic_thumb_creation 'Editorial',
  90 + :thumb => [50, 50], :geometry => 'x50', :fullsize => '150x100>'
  91 + assert_polymorphic_thumb_creation 'User',
  92 + :thumb => [50, 50], :geometry => 'x50', :avatar => '64x64!'
  93 + end
  94 +
  95 + def test_should_compute_per_thumbnail_jpeg_quality
  96 + assert_jpeg_quality :thumb, 90
  97 + assert_jpeg_quality :avatar, 85
  98 + assert_jpeg_quality :large, 75
  99 + assert_jpeg_quality :large, 0x200 | 75, false
  100 + assert_jpeg_quality nil, 75
  101 + end
  102 +
  103 +private
  104 + def assert_jpeg_quality(thumbnail, quality, require_0_to_100 = true)
  105 + klass = ImageWithPerThumbJpegAttachment
  106 + w, h = if thumbnail
  107 + klass.attachment_options[:thumbnails][thumbnail].scan(/\d+/)
  108 + else
  109 + klass.attachment_options[:resize_to].scan(/\d+/)
  110 + end
  111 + attachment = klass.new(:thumbnail => thumbnail, :width => w, :height => h)
  112 + assert_equal quality, attachment.send(:get_jpeg_quality, require_0_to_100)
  113 + end
  114 +
  115 + def assert_polymorphic_thumb_creation(parent, defs)
  116 + attachment_model ImageWithPolymorphicThumbsAttachment
  117 + attachment_model.reset_creations
  118 + attachment = upload_file :filename => '/files/rails.png', :imageable_type => parent.to_s.classify, :imageable_id => nil
  119 + assert_equal defs, attachment_model.thumbnail_creations
  120 + end
  121 +end
... ...
vendor/plugins/pothoven-attachment_fu/test/database.yml 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +sqlite:
  2 + :adapter: sqlite
  3 + :database: attachment_fu_plugin.sqlite.db
  4 +sqlite3:
  5 + :adapter: sqlite3
  6 + :database: attachment_fu_plugin.sqlite3.db
  7 +postgresql:
  8 + :adapter: postgresql
  9 + :username: postgres
  10 + :password: postgres
  11 + :database: attachment_fu_plugin_test
  12 + :min_messages: ERROR
  13 +mysql:
  14 + :adapter: mysql
  15 + :host: localhost
  16 + :username: rails
  17 + :password:
  18 + :database: attachment_fu_plugin_test
0 19 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/extra_attachment_test.rb 0 → 100644
... ... @@ -0,0 +1,67 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
  2 +
  3 +class OrphanAttachmentTest < Test::Unit::TestCase
  4 + include BaseAttachmentTests
  5 + attachment_model OrphanAttachment
  6 +
  7 + def test_should_create_image_from_uploaded_file
  8 + assert_created do
  9 + attachment = upload_file :filename => '/files/rails.png'
  10 + assert_valid attachment
  11 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  12 + assert attachment.image?
  13 + assert !attachment.size.zero?
  14 + end
  15 + end
  16 +
  17 + def test_should_create_file_from_uploaded_file
  18 + assert_created do
  19 + attachment = upload_file :filename => '/files/foo.txt'
  20 + assert_valid attachment
  21 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  22 + assert attachment.image?
  23 + assert !attachment.size.zero?
  24 + end
  25 + end
  26 +
  27 + def test_should_create_file_from_merb_temp_file
  28 + assert_created do
  29 + attachment = upload_merb_file :filename => '/files/foo.txt'
  30 + assert_valid attachment
  31 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  32 + assert attachment.image?
  33 + assert !attachment.size.zero?
  34 + end
  35 + end
  36 +
  37 + def test_should_create_image_from_uploaded_file_with_custom_content_type
  38 + assert_created do
  39 + attachment = upload_file :content_type => 'foo/bar', :filename => '/files/rails.png'
  40 + assert_valid attachment
  41 + assert !attachment.image?
  42 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  43 + assert !attachment.size.zero?
  44 + #assert_equal 1784, attachment.size
  45 + end
  46 + end
  47 +
  48 + def test_should_create_thumbnail
  49 + attachment = upload_file :filename => '/files/rails.png'
  50 +
  51 + assert_raise Technoweenie::AttachmentFu::ThumbnailError do
  52 + attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', 50, 50)
  53 + end
  54 + end
  55 +
  56 + def test_should_create_thumbnail_with_geometry_string
  57 + attachment = upload_file :filename => '/files/rails.png'
  58 +
  59 + assert_raise Technoweenie::AttachmentFu::ThumbnailError do
  60 + attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', 'x50')
  61 + end
  62 + end
  63 +end
  64 +
  65 +class MinimalAttachmentTest < OrphanAttachmentTest
  66 + attachment_model MinimalAttachment
  67 +end
0 68 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/fixtures/attachment.rb 0 → 100644
... ... @@ -0,0 +1,297 @@
  1 +class Attachment < ActiveRecord::Base
  2 + @@saves = 0
  3 + cattr_accessor :saves
  4 + has_attachment :processor => :rmagick
  5 + validates_as_attachment
  6 + after_save do |record|
  7 + self.saves += 1
  8 + end
  9 +end
  10 +
  11 +class LowerQualityAttachment < Attachment
  12 + self.table_name = 'attachments'
  13 + has_attachment :resize_to => [55,55], :jpeg_quality => 50
  14 +end
  15 +
  16 +class SmallAttachment < Attachment
  17 + has_attachment :max_size => 1.kilobyte
  18 +end
  19 +
  20 +class BigAttachment < Attachment
  21 + has_attachment :size => 1.megabyte..2.megabytes
  22 +end
  23 +
  24 +class PdfAttachment < Attachment
  25 + has_attachment :content_type => 'pdf'
  26 +end
  27 +
  28 +class DocAttachment < Attachment
  29 + has_attachment :content_type => %w(pdf doc txt)
  30 +end
  31 +
  32 +class ImageAttachment < Attachment
  33 + has_attachment :content_type => :image, :resize_to => [50,50]
  34 +end
  35 +
  36 +class ImageOrPdfAttachment < Attachment
  37 + has_attachment :content_type => ['pdf', :image], :resize_to => 'x50'
  38 +end
  39 +
  40 +class ImageWithThumbsAttachment < Attachment
  41 + has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }, :resize_to => [55,55]
  42 + # after_resize do |record, img|
  43 + # record.aspect_ratio = img.columns.to_f / img.rows.to_f
  44 + # end
  45 +end
  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 +
  64 +class FileAttachment < ActiveRecord::Base
  65 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
  66 + validates_as_attachment
  67 +end
  68 +
  69 +class FileAttachmentWithStringId < ActiveRecord::Base
  70 + self.table_name = 'file_attachments_with_string_id'
  71 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
  72 + validates_as_attachment
  73 +
  74 + before_validation :auto_generate_id
  75 + before_save :auto_generate_id
  76 + @@last_id = 0
  77 +
  78 + private
  79 + def auto_generate_id
  80 + @@last_id += 1
  81 + self.id = "id_#{@@last_id}"
  82 + end
  83 +end
  84 +
  85 +class FileAttachmentWithUuid < ActiveRecord::Base
  86 + self.table_name = 'file_attachments_with_string_id'
  87 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick, :uuid_primary_key => true
  88 + validates_as_attachment
  89 +
  90 + before_validation :auto_generate_id
  91 + before_save :auto_generate_id
  92 + @@last_id = 0
  93 +
  94 + private
  95 + def auto_generate_id
  96 + @@last_id += 1
  97 + self.id = "%0127dx" % @@last_id
  98 + end
  99 +end
  100 +
  101 +class ImageFileAttachment < FileAttachment
  102 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  103 + :content_type => :image, :resize_to => [50,50]
  104 +end
  105 +
  106 +class ImageWithThumbsFileAttachment < FileAttachment
  107 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  108 + :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }, :resize_to => [55,55]
  109 + # after_resize do |record, img|
  110 + # record.aspect_ratio = img.columns.to_f / img.rows.to_f
  111 + # end
  112 +end
  113 +
  114 +class ImageWithThumbsClassFileAttachment < FileAttachment
  115 + # use file_system_path to test backwards compatibility
  116 + has_attachment :file_system_path => 'vendor/plugins/attachment_fu/test/files',
  117 + :thumbnails => { :thumb => [50, 50] }, :resize_to => [55,55],
  118 + :thumbnail_class => 'ImageThumbnail'
  119 +end
  120 +
  121 +class ImageThumbnail < FileAttachment
  122 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files/thumbnails'
  123 +end
  124 +
  125 +# no parent
  126 +class OrphanAttachment < ActiveRecord::Base
  127 + has_attachment :processor => :rmagick
  128 + validates_as_attachment
  129 +end
  130 +
  131 +# no filename, no size, no content_type
  132 +class MinimalAttachment < ActiveRecord::Base
  133 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
  134 + validates_as_attachment
  135 +
  136 + def filename
  137 + "#{id}.file"
  138 + end
  139 +end
  140 +
  141 +begin
  142 + class ImageScienceAttachment < ActiveRecord::Base
  143 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  144 + :processor => :image_science, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
  145 + end
  146 +
  147 + class ImageScienceLowerQualityAttachment < ActiveRecord::Base
  148 + self.table_name = 'image_science_attachments'
  149 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  150 + :processor => :image_science, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
  151 + :jpeg_quality => 75
  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
  161 +rescue MissingSourceFile
  162 + puts $!.message
  163 + puts "no ImageScience"
  164 +end
  165 +
  166 +begin
  167 + class CoreImageAttachment < ActiveRecord::Base
  168 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  169 + :processor => :core_image, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
  170 + end
  171 +
  172 + class LowerQualityCoreImageAttachment < CoreImageAttachment
  173 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  174 + :processor => :core_image, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
  175 + :jpeg_quality => 50
  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
  185 +rescue MissingSourceFile
  186 + puts $!.message
  187 + puts "no CoreImage"
  188 +end
  189 +
  190 +begin
  191 + class MiniMagickAttachment < ActiveRecord::Base
  192 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  193 + :processor => :mini_magick, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
  194 + end
  195 +
  196 + class ImageThumbnailCrop < MiniMagickAttachment
  197 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  198 + :thumbnails => { :square => "50x50c", :vertical => "30x60c", :horizontal => "60x30c"}
  199 +
  200 + # TODO this is a bad duplication, this method is in the MiniMagick Processor
  201 + def self.calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
  202 + # only crop if image is not smaller in both dimensions
  203 +
  204 + # special cases, image smaller in one dimension then thumbsize
  205 + if image_width < thumb_width
  206 + offset = (image_height / 2) - (thumb_height / 2)
  207 + command = "#{image_width}x#{thumb_height}+0+#{offset}"
  208 + elsif image_height < thumb_height
  209 + offset = (image_width / 2) - (thumb_width / 2)
  210 + command = "#{thumb_width}x#{image_height}+#{offset}+0"
  211 +
  212 + # normal thumbnail generation
  213 + # calculate height and offset y, width is fixed
  214 + elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
  215 + height = image_width / thumb_aspect
  216 + offset = (image_height / 2) - (height / 2)
  217 + command = "#{image_width}x#{height}+0+#{offset}"
  218 + # calculate width and offset x, height is fixed
  219 + else
  220 + width = image_height * thumb_aspect
  221 + offset = (image_width / 2) - (width / 2)
  222 + command = "#{width}x#{image_height}+#{offset}+0"
  223 + end
  224 + # crop image
  225 + command
  226 + end
  227 + end
  228 +
  229 + class LowerQualityMiniMagickAttachment < ActiveRecord::Base
  230 + self.table_name = 'mini_magick_attachments'
  231 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  232 + :processor => :mini_magick, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
  233 + :jpeg_quality => 50
  234 + end
  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 +
  244 +rescue MissingSourceFile
  245 + puts $!.message
  246 + puts "no Mini Magick"
  247 +end
  248 +
  249 +begin
  250 + class GD2Attachment < ActiveRecord::Base
  251 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  252 + :processor => :gd2, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
  253 + end
  254 +
  255 + class LowerQualityGD2Attachment < GD2Attachment
  256 + has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
  257 + :processor => :gd2, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
  258 + :jpeg_quality => 50
  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
  268 +rescue MissingSourceFile
  269 + puts $!.message
  270 + puts "no GD2"
  271 +end
  272 +
  273 +
  274 +begin
  275 + class S3Attachment < ActiveRecord::Base
  276 + has_attachment :storage => :s3, :processor => :rmagick, :s3_config_path => File.join(File.dirname(__FILE__), '../amazon_s3.yml')
  277 + validates_as_attachment
  278 + end
  279 +
  280 + class CloudFilesAttachment < ActiveRecord::Base
  281 + has_attachment :storage => :cloud_files, :processor => :rmagick, :cloudfiles_config_path => File.join(File.dirname(__FILE__), '../rackspace_cloudfiles.yml')
  282 + validates_as_attachment
  283 + end
  284 +
  285 + class S3WithPathPrefixAttachment < S3Attachment
  286 + has_attachment :storage => :s3, :path_prefix => 'some/custom/path/prefix', :processor => :rmagick
  287 + validates_as_attachment
  288 + end
  289 +
  290 + class CloudFilesWithPathPrefixAttachment < CloudFilesAttachment
  291 + has_attachment :storage => :cloud_files, :path_prefix => 'some/custom/path/prefix', :processor => :rmagick
  292 + validates_as_attachment
  293 + end
  294 +
  295 +rescue
  296 + puts "S3 error: #{$!}"
  297 +end
... ...
vendor/plugins/pothoven-attachment_fu/test/fixtures/files/fake/rails.png 0 → 100644

4.12 KB

vendor/plugins/pothoven-attachment_fu/test/fixtures/files/foo.txt 0 → 100644
... ... @@ -0,0 +1 @@
  1 +foo
0 2 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/fixtures/files/rails.jpg 0 → 100644

2.43 KB

vendor/plugins/pothoven-attachment_fu/test/fixtures/files/rails.png 0 → 100644

1.75 KB

vendor/plugins/pothoven-attachment_fu/test/geometry_test.rb 0 → 100644
... ... @@ -0,0 +1,114 @@
  1 +require 'test/unit'
  2 +require File.expand_path(File.join(File.dirname(__FILE__), '../lib/geometry')) unless Object.const_defined?(:Geometry)
  3 +
  4 +class GeometryTest < Test::Unit::TestCase
  5 + def test_should_resize
  6 + assert_geometry 50, 64,
  7 + "50x50" => [39, 50],
  8 + "60x60" => [47, 60],
  9 + "100x100" => [78, 100]
  10 + end
  11 +
  12 + def test_should_resize_no_width
  13 + assert_geometry 50, 64,
  14 + "x50" => [39, 50],
  15 + "x60" => [47, 60],
  16 + "x100" => [78, 100]
  17 + end
  18 +
  19 + def test_should_resize_no_height
  20 + assert_geometry 50, 64,
  21 + "50" => [50, 64],
  22 + "60" => [60, 77],
  23 + "100" => [100, 128]
  24 + end
  25 +
  26 + def test_should_resize_no_height_with_x
  27 + assert_geometry 50, 64,
  28 + "50x" => [50, 64],
  29 + "60x" => [60, 77],
  30 + "100x" => [100, 128]
  31 + end
  32 +
  33 + def test_should_resize_with_percent
  34 + assert_geometry 50, 64,
  35 + "50x50%" => [25, 32],
  36 + "60x60%" => [30, 38],
  37 + "120x112%" => [60, 72]
  38 + end
  39 +
  40 + def test_should_resize_with_percent_and_no_width
  41 + assert_geometry 50, 64,
  42 + "x50%" => [50, 32],
  43 + "x60%" => [50, 38],
  44 + "x112%" => [50, 72]
  45 + end
  46 +
  47 + def test_should_resize_with_percent_and_no_height
  48 + assert_geometry 50, 64,
  49 + "50%" => [25, 32],
  50 + "60%" => [30, 38],
  51 + "120%" => [60, 77]
  52 + end
  53 +
  54 + def test_should_resize_with_less
  55 + assert_geometry 50, 64,
  56 + "50x50<" => [50, 64],
  57 + "60x60<" => [50, 64],
  58 + "100x100<" => [78, 100],
  59 + "100x112<" => [88, 112],
  60 + "40x70<" => [50, 64]
  61 + end
  62 +
  63 + def test_should_resize_with_less_and_no_width
  64 + assert_geometry 50, 64,
  65 + "x50<" => [50, 64],
  66 + "x60<" => [50, 64],
  67 + "x100<" => [78, 100]
  68 + end
  69 +
  70 + def test_should_resize_with_less_and_no_height
  71 + assert_geometry 50, 64,
  72 + "50<" => [50, 64],
  73 + "60<" => [60, 77],
  74 + "100<" => [100, 128]
  75 + end
  76 +
  77 + def test_should_resize_with_greater
  78 + assert_geometry 50, 64,
  79 + "50x50>" => [39, 50],
  80 + "60x60>" => [47, 60],
  81 + "100x100>" => [50, 64],
  82 + "100x112>" => [50, 64],
  83 + "40x70>" => [40, 51]
  84 + end
  85 +
  86 + def test_should_resize_with_greater_and_no_width
  87 + assert_geometry 50, 64,
  88 + "x40>" => [31, 40],
  89 + "x60>" => [47, 60],
  90 + "x100>" => [50, 64]
  91 + end
  92 +
  93 + def test_should_resize_with_greater_and_no_height
  94 + assert_geometry 50, 64,
  95 + "40>" => [40, 51],
  96 + "60>" => [50, 64],
  97 + "100>" => [50, 64]
  98 + end
  99 +
  100 + def test_should_resize_with_aspect
  101 + assert_geometry 50, 64,
  102 + "35x35!" => [35, 35],
  103 + "70x70!" => [70, 70]
  104 + end
  105 +
  106 + protected
  107 + def assert_geometry(width, height, values)
  108 + values.each do |geo, result|
  109 + # run twice to verify the Geometry string isn't modified after a run
  110 + geo = Geometry.from_s(geo)
  111 + 2.times { assert_equal result, [width, height] / geo }
  112 + end
  113 + end
  114 +end
0 115 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/processors/core_image_test.rb 0 → 100644
... ... @@ -0,0 +1,58 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
  2 +
  3 +class CoreImageTest < Test::Unit::TestCase
  4 + attachment_model CoreImageAttachment
  5 +
  6 + if Object.const_defined?(:OSX)
  7 + def test_should_resize_image
  8 + attachment = upload_file :filename => '/files/rails.png'
  9 + assert_valid attachment
  10 + assert attachment.image?
  11 + # test core image thumbnail
  12 + assert_equal 42, attachment.width
  13 + assert_equal 55, attachment.height
  14 +
  15 + thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
  16 + geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
  17 + aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
  18 +
  19 + # test exact resize dimensions
  20 + assert_equal 50, thumb.width
  21 + assert_equal 51, thumb.height
  22 +
  23 + # test geometry strings
  24 + assert_equal 31, geo.width
  25 + assert_equal 41, geo.height
  26 + assert_equal 25, aspect.width
  27 + assert_equal 25, aspect.height
  28 +
  29 + # This makes sure that we didn't overwrite the original file
  30 + # and will end up with a thumbnail instead of the original
  31 + assert_equal 42, attachment.width
  32 + assert_equal 55, attachment.height
  33 +
  34 + end
  35 +
  36 + def test_should_handle_jpeg_quality
  37 + attachment_model CoreImageAttachment
  38 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  39 + full_size = attachment.size
  40 + attachment_model LowerQualityCoreImageAttachment
  41 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  42 + lq_size = attachment.size
  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
  52 + end
  53 + else
  54 + def test_flunk
  55 + puts "CoreImage not loaded, tests not running"
  56 + end
  57 + end
  58 +end
0 59 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/processors/gd2_test.rb 0 → 100644
... ... @@ -0,0 +1,51 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
  2 +
  3 +class GD2Test < Test::Unit::TestCase
  4 + attachment_model GD2Attachment
  5 +
  6 + if Object.const_defined?(:GD2)
  7 + def test_should_resize_image
  8 + attachment = upload_file :filename => '/files/rails.png'
  9 + assert_valid attachment
  10 + assert attachment.image?
  11 + # test gd2 thumbnail
  12 + assert_equal 43, attachment.width
  13 + assert_equal 55, attachment.height
  14 +
  15 + thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
  16 + geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
  17 + aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
  18 +
  19 + # test exact resize dimensions
  20 + assert_equal 50, thumb.width
  21 + assert_equal 51, thumb.height
  22 +
  23 + # test geometry strings
  24 + assert_equal 31, geo.width
  25 + assert_equal 40, geo.height
  26 + assert_equal 25, aspect.width
  27 + assert_equal 25, aspect.height
  28 + end
  29 +
  30 + def test_should_handle_jpeg_quality
  31 + attachment_model GD2Attachment
  32 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  33 + full_size = attachment.size
  34 + attachment_model LowerQualityGD2Attachment
  35 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  36 + lq_size = attachment.size
  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
  45 + end
  46 + else
  47 + def test_flunk
  48 + puts "GD2 not loaded, tests not running"
  49 + end
  50 + end
  51 +end
0 52 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/processors/image_science_test.rb 0 → 100644
... ... @@ -0,0 +1,54 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
  2 +
  3 +class ImageScienceTest < Test::Unit::TestCase
  4 + attachment_model ImageScienceAttachment
  5 +
  6 + if Object.const_defined?(:ImageScience)
  7 + def test_should_resize_image
  8 + attachment = upload_file :filename => '/files/rails.png'
  9 + assert_valid attachment
  10 + assert attachment.image?
  11 + # test image science thumbnail
  12 + assert_equal 42, attachment.width
  13 + assert_equal 55, attachment.height
  14 +
  15 + thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
  16 + geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
  17 + aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
  18 +
  19 + # test exact resize dimensions
  20 + assert_equal 50, thumb.width
  21 + assert_equal 51, thumb.height
  22 +
  23 + # test geometry strings
  24 + assert_equal 31, geo.width
  25 + assert_equal 41, geo.height
  26 + assert_equal 25, aspect.width
  27 + assert_equal 25, aspect.height
  28 + end
  29 +
  30 + def test_should_handle_jpeg_quality
  31 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  32 + full_size = attachment.size
  33 + attachment_model ImageScienceLowerQualityAttachment
  34 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  35 + lq_size = attachment.size
  36 + if ImageScience.instance_method(:save).arity == -2 # tdd-image_science: JPEG quality processing
  37 + assert lq_size <= full_size * 0.75, 'Lower-quality JPEG filesize should be congruently smaller'
  38 + else
  39 + assert_equal full_size, lq_size, 'Unsupported lower-quality JPEG should yield exact same file size'
  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
  48 + end
  49 + else
  50 + def test_flunk
  51 + puts "ImageScience not loaded, tests not running"
  52 + end
  53 + end
  54 +end
0 55 \ No newline at end of file
... ...
vendor/plugins/pothoven-attachment_fu/test/processors/mini_magick_test.rb 0 → 100644
... ... @@ -0,0 +1,122 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
  2 +
  3 +class MiniMagickTest < Test::Unit::TestCase
  4 + attachment_model MiniMagickAttachment
  5 +
  6 + if Object.const_defined?(:MiniMagick)
  7 + def test_should_resize_image
  8 + attachment = upload_file :filename => '/files/rails.png'
  9 + assert_valid attachment
  10 + assert attachment.image?
  11 + # test MiniMagick thumbnail
  12 + assert_equal 43, attachment.width
  13 + assert_equal 55, attachment.height
  14 +
  15 + thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
  16 + geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
  17 + aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
  18 +
  19 + # test exact resize dimensions
  20 + assert_equal 50, thumb.width
  21 + assert_equal 51, thumb.height
  22 +
  23 + # test geometry strings
  24 + assert_equal 31, geo.width
  25 + assert_equal 40, geo.height
  26 + assert_equal 25, aspect.width
  27 + assert_equal 25, aspect.height
  28 + end
  29 +
  30 + def test_should_crop_image(klass = ImageThumbnailCrop)
  31 + attachment_model klass
  32 + attachment = upload_file :filename => '/files/rails.png'
  33 + assert_valid attachment
  34 + assert attachment.image?
  35 + # has_attachment :thumbnails => { :square => "50x50c", :vertical => "30x60c", :horizontal => "60x30c"}
  36 +
  37 + square = attachment.thumbnails.detect { |t| t.filename =~ /_square/ }
  38 + vertical = attachment.thumbnails.detect { |t| t.filename =~ /_vertical/ }
  39 + horizontal = attachment.thumbnails.detect { |t| t.filename =~ /_horizontal/ }
  40 +
  41 + # test excat resize
  42 + assert_equal 50, square.width
  43 + assert_equal 50, square.height
  44 +
  45 + assert_equal 30, vertical.width
  46 + assert_equal 60, vertical.height
  47 +
  48 + assert_equal 60, horizontal.width
  49 + assert_equal 30, horizontal.height
  50 + end
  51 +
  52 + # tests the first step in resize, crop the image in original size to right format
  53 + def test_should_crop_image_right(klass = ImageThumbnailCrop)
  54 + @@testcases.collect do |testcase|
  55 + image_width, image_height, thumb_width, thumb_height = testcase[:data]
  56 + image_aspect, thumb_aspect = image_width/image_height, thumb_width/thumb_height
  57 + crop_comand = klass.calculate_offset(image_width, image_height, image_aspect, thumb_width, thumb_height,thumb_aspect)
  58 + # pattern matching on crop command
  59 + if testcase.has_key?(:height)
  60 + assert crop_comand.match(/^#{image_width}x#{testcase[:height]}\+0\+#{testcase[:yoffset]}$/)
  61 + else
  62 + assert crop_comand.match(/^#{testcase[:width]}x#{image_height}\+#{testcase[:xoffset]}\+0$/)
  63 + end
  64 + end
  65 + end
  66 +
  67 + def test_should_handle_jpeg_quality
  68 + attachment_model MiniMagickAttachment
  69 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  70 + full_size = attachment.size
  71 + attachment_model LowerQualityMiniMagickAttachment
  72 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  73 + lq_size = attachment.size
  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
  82 + end
  83 + else
  84 + def test_flunk
  85 + puts "MiniMagick not loaded, tests not running"
  86 + end
  87 + end
  88 +
  89 + @@testcases = [
  90 + # image_aspect <= 1 && thumb_aspect >= 1
  91 + {:data => [10.0,40.0,2.0,1.0], :height => 5.0, :yoffset => 17.5}, # 1b
  92 + {:data => [10.0,40.0,1.0,1.0], :height => 10.0, :yoffset => 15.0}, # 1b
  93 +
  94 + # image_aspect < 1 && thumb_aspect < 1
  95 + {:data => [10.0,40.0,1.0,2.0], :height => 20.0, :yoffset => 10.0}, # 1a
  96 + {:data => [2.0,3.0,1.0,2.0], :width => 1.5, :xoffset => 0.25}, # 1a
  97 +
  98 + # image_aspect = thumb_aspect
  99 + {:data => [10.0,10.0,1.0,1.0], :height => 10.0, :yoffset => 0.0}, # QUADRAT 1c
  100 +
  101 + # image_aspect >= 1 && thumb_aspect > 1 && image_aspect < thumb_aspect
  102 + {:data => [6.0,3.0,4.0,1.0], :height => 1.5, :yoffset => 0.75}, # 2b
  103 + {:data => [6.0,6.0,4.0,1.0], :height => 1.5, :yoffset => 2.25}, # 2b
  104 +
  105 + # image_aspect > 1 && thumb_aspect > 1 && image_aspect > thumb_aspect
  106 + {:data => [9.0,3.0,2.0,1.0], :width => 6.0, :xoffset => 1.5}, # 2a
  107 +
  108 + # image_aspect > 1 && thumb_aspect < 1 && image_aspect < thumb_aspect
  109 + {:data => [10.0,5.0,0.1,2.0], :width => 0.25, :xoffset => 4.875}, # 4
  110 + {:data => [10.0,5.0,1.0,2.0], :width => 2.5, :xoffset => 3.75}, # 4
  111 +
  112 + # image_aspect > 1 && thumb_aspect > 1 && image_aspect > thumb_aspect
  113 + {:data => [9.0,3.0,2.0,1.0], :width => 6.0, :xoffset => 1.5}, # 3a
  114 + # image_aspect > 1 && thumb_aspect > 1 && image_aspect < thumb_aspect
  115 + {:data => [9.0,3.0,5.0,1.0], :height => 1.8, :yoffset => 0.6} # 3a
  116 + ]
  117 +
  118 +
  119 +
  120 +
  121 +
  122 +end
... ...
vendor/plugins/pothoven-attachment_fu/test/processors/rmagick_test.rb 0 → 100644
... ... @@ -0,0 +1,272 @@
  1 +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
  2 +class RmagickTest < Test::Unit::TestCase
  3 + attachment_model Attachment
  4 +
  5 + if Object.const_defined?(:Magick)
  6 + def test_should_create_image_from_uploaded_file
  7 + assert_created do
  8 + attachment = upload_file :filename => '/files/rails.png'
  9 + assert_valid attachment
  10 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  11 + assert attachment.image?
  12 + assert !attachment.size.zero?
  13 + #assert_equal 1784, attachment.size
  14 + assert_equal 50, attachment.width
  15 + assert_equal 64, attachment.height
  16 + assert_equal '50x64', attachment.image_size
  17 + end
  18 + end
  19 +
  20 + def test_should_create_image_from_uploaded_file_with_custom_content_type
  21 + assert_created do
  22 + attachment = upload_file :content_type => 'foo/bar', :filename => '/files/rails.png'
  23 + assert_valid attachment
  24 + assert !attachment.image?
  25 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  26 + assert !attachment.size.zero?
  27 + #assert_equal 1784, attachment.size
  28 + assert_nil attachment.width
  29 + assert_nil attachment.height
  30 + assert_equal [], attachment.thumbnails
  31 + end
  32 + end
  33 +
  34 + def test_should_create_thumbnail
  35 + attachment = upload_file :filename => '/files/rails.png'
  36 +
  37 + assert_created do
  38 + basename, ext = attachment.filename.split '.'
  39 + thumbnail = attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', 50, 50)
  40 + assert_valid thumbnail
  41 + assert !thumbnail.size.zero?
  42 + #assert_in_delta 4673, thumbnail.size, 2
  43 + assert_equal 50, thumbnail.width
  44 + assert_equal 50, thumbnail.height
  45 + assert_equal [thumbnail.id], attachment.thumbnails.collect(&:id)
  46 + assert_equal attachment.id, thumbnail.parent_id if thumbnail.respond_to?(:parent_id)
  47 + assert_equal "#{basename}_thumb.#{ext}", thumbnail.filename
  48 + end
  49 + end
  50 +
  51 + def test_should_create_thumbnail_with_geometry_strings
  52 + attachment = upload_file :filename => '/files/rails.png'
  53 +
  54 + assert_created do
  55 + basename, ext = attachment.filename.split '.'
  56 + { 'x50' => [39, 50], '25x25!' => [25, 25] }.each do |geo, (w, h)|
  57 + thumbnail = attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', geo)
  58 + assert_valid thumbnail
  59 + assert !thumbnail.size.zero?
  60 + assert_equal w, thumbnail.width
  61 + assert_equal h, thumbnail.height
  62 + assert_equal [thumbnail], attachment.thumbnails
  63 + assert_equal attachment.id, thumbnail.parent_id if thumbnail.respond_to?(:parent_id)
  64 + assert_equal "#{basename}_thumb.#{ext}", thumbnail.filename
  65 + end
  66 + end
  67 + end
  68 +
  69 + def test_should_resize_image(klass = ImageAttachment)
  70 + attachment_model klass
  71 + assert_equal [50, 50], attachment_model.attachment_options[:resize_to]
  72 + attachment = upload_file :filename => '/files/rails.png'
  73 + assert_valid attachment
  74 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  75 + assert attachment.image?
  76 + assert !attachment.size.zero?
  77 + #assert_in_delta 4673, attachment.size, 2
  78 + assert_equal 50, attachment.width
  79 + assert_equal 50, attachment.height
  80 + end
  81 +
  82 + test_against_subclass :test_should_resize_image, ImageAttachment
  83 +
  84 + def test_should_resize_image_with_geometry(klass = ImageOrPdfAttachment)
  85 + attachment_model klass
  86 + assert_equal 'x50', attachment_model.attachment_options[:resize_to]
  87 + attachment = upload_file :filename => '/files/rails.png'
  88 + assert_valid attachment
  89 + assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
  90 + assert attachment.image?
  91 + assert !attachment.size.zero?
  92 + #assert_equal 3915, attachment.size
  93 + assert_equal 39, attachment.width
  94 + assert_equal 50, attachment.height
  95 + end
  96 +
  97 + test_against_subclass :test_should_resize_image_with_geometry, ImageOrPdfAttachment
  98 +
  99 + def test_should_give_correct_thumbnail_filenames(klass = ImageWithThumbsFileAttachment)
  100 + attachment_model klass
  101 + assert_created 3 do
  102 + attachment = upload_file :filename => '/files/rails.png'
  103 + thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
  104 + geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
  105 +
  106 + [attachment, thumb, geo].each { |record| assert_valid record }
  107 +
  108 + assert_match /rails\.png$/, attachment.full_filename
  109 + assert_match /rails_geometry\.png$/, attachment.full_filename(:geometry)
  110 + assert_match /rails_thumb\.png$/, attachment.full_filename(:thumb)
  111 + end
  112 + end
  113 +
  114 + test_against_subclass :test_should_give_correct_thumbnail_filenames, ImageWithThumbsFileAttachment
  115 +
  116 + def test_should_automatically_create_thumbnails(klass = ImageWithThumbsAttachment)
  117 + attachment_model klass
  118 + assert_created 3 do
  119 + attachment = upload_file :filename => '/files/rails.png'
  120 + assert_valid attachment
  121 + assert !attachment.size.zero?
  122 + #assert_equal 1784, attachment.size
  123 + assert_equal 55, attachment.width
  124 + assert_equal 55, attachment.height
  125 + assert_equal 2, attachment.thumbnails.length
  126 + # assert_equal 1.0, attachment.aspect_ratio
  127 +
  128 + thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
  129 + assert !thumb.new_record?, thumb.errors.full_messages.join("\n")
  130 + assert !thumb.size.zero?
  131 + #assert_in_delta 4673, thumb.size, 2
  132 + assert_equal 50, thumb.width
  133 + assert_equal 50, thumb.height
  134 + # assert_equal 1.0, thumb.aspect_ratio
  135 +
  136 + geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
  137 + assert !geo.new_record?, geo.errors.full_messages.join("\n")
  138 + assert !geo.size.zero?
  139 + #assert_equal 3915, geo.size
  140 + assert_equal 50, geo.width
  141 + assert_equal 50, geo.height
  142 + # assert_equal 1.0, geo.aspect_ratio
  143 + end
  144 + end
  145 +
  146 + test_against_subclass :test_should_automatically_create_thumbnails, ImageWithThumbsAttachment
  147 +
  148 + # same as above method, but test it on a file model
  149 + test_against_class :test_should_automatically_create_thumbnails, ImageWithThumbsFileAttachment
  150 + test_against_subclass :test_should_automatically_create_thumbnails_on_class, ImageWithThumbsFileAttachment
  151 +
  152 + def test_should_use_thumbnail_subclass(klass = ImageWithThumbsClassFileAttachment)
  153 + attachment_model klass
  154 + attachment = nil
  155 + assert_difference ImageThumbnail, :count do
  156 + attachment = upload_file :filename => '/files/rails.png'
  157 + assert_valid attachment
  158 + end
  159 + assert_kind_of ImageThumbnail, attachment.thumbnails.first
  160 + if attachment.thumbnails.first.respond_to?(:parent)
  161 + assert_equal attachment.id, attachment.thumbnails.first.parent.id
  162 + assert_kind_of FileAttachment, attachment.thumbnails.first.parent
  163 + end
  164 + assert_equal 'rails_thumb.png', attachment.thumbnails.first.filename
  165 + assert_equal attachment.thumbnails.first.full_filename, attachment.full_filename(attachment.thumbnails.first.thumbnail),
  166 + "#full_filename does not use thumbnail class' path."
  167 + assert_equal attachment.destroy, attachment
  168 + end
  169 +
  170 + test_against_subclass :test_should_use_thumbnail_subclass, ImageWithThumbsClassFileAttachment
  171 +
  172 + def test_should_remove_old_thumbnail_files_when_updating(klass = ImageWithThumbsFileAttachment)
  173 + attachment_model klass
  174 + attachment = nil
  175 + assert_created 3 do
  176 + attachment = upload_file :filename => '/files/rails.png'
  177 + end
  178 +
  179 + old_filenames = [attachment.full_filename] + attachment.thumbnails.collect(&:full_filename)
  180 +
  181 + assert_not_created do
  182 + use_temp_file "files/rails.png" do |file|
  183 + attachment.filename = 'rails2.png'
  184 + attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
  185 + attachment.save
  186 + new_filenames = [attachment.reload.full_filename] + attachment.thumbnails.collect { |t| t.reload.full_filename }
  187 + new_filenames.each { |f| assert File.exists?(f), "#{f} does not exist" }
  188 + old_filenames.each { |f| assert !File.exists?(f), "#{f} still exists" }
  189 + end
  190 + end
  191 + end
  192 +
  193 + test_against_subclass :test_should_remove_old_thumbnail_files_when_updating, ImageWithThumbsFileAttachment
  194 +
  195 + def test_should_delete_file_when_in_file_system_when_attachment_record_destroyed(klass = ImageWithThumbsFileAttachment)
  196 + attachment_model klass
  197 + attachment = upload_file :filename => '/files/rails.png'
  198 + filenames = [attachment.full_filename] + attachment.thumbnails.collect(&:full_filename)
  199 + filenames.each { |f| assert File.exists?(f), "#{f} never existed to delete on destroy" }
  200 + attachment.destroy
  201 + filenames.each { |f| assert !File.exists?(f), "#{f} still exists" }
  202 + end
  203 +
  204 + test_against_subclass :test_should_delete_file_when_in_file_system_when_attachment_record_destroyed, ImageWithThumbsFileAttachment
  205 +
  206 + def test_should_have_full_filename_method(klass = FileAttachment)
  207 + attachment_model klass
  208 + attachment = upload_file :filename => '/files/rails.png'
  209 + assert_respond_to attachment, :full_filename
  210 + end
  211 +
  212 + test_against_subclass :test_should_have_full_filename_method, FileAttachment
  213 +
  214 + def test_should_overwrite_old_thumbnail_records_when_updating(klass = ImageWithThumbsAttachment)
  215 + attachment_model klass
  216 + attachment = nil
  217 + assert_created 3 do
  218 + attachment = upload_file :filename => '/files/rails.png'
  219 + end
  220 + assert_not_created do # no new db_file records
  221 + use_temp_file "files/rails.png" do |file|
  222 + attachment.filename = 'rails2.png'
  223 + # The above test (#test_should_have_full_filename_method) to pass before be can set the temp_path below --
  224 + # #temp_path calls #full_filename, which is not getting mixed into the attachment. Maybe we don't need to
  225 + # set temp_path at all?
  226 + #
  227 + # attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
  228 + attachment.save!
  229 + end
  230 + end
  231 + end
  232 +
  233 + test_against_subclass :test_should_overwrite_old_thumbnail_records_when_updating, ImageWithThumbsAttachment
  234 +
  235 + def test_should_overwrite_old_thumbnail_records_when_renaming(klass = ImageWithThumbsAttachment)
  236 + attachment_model klass
  237 + attachment = nil
  238 + assert_created 3 do
  239 + attachment = upload_file :class => klass, :filename => '/files/rails.png'
  240 + end
  241 + assert_not_created do # no new db_file records
  242 + attachment.filename = 'rails2.png'
  243 + attachment.save
  244 + assert !attachment.reload.size.zero?
  245 + assert_equal 'rails2.png', attachment.filename
  246 + end
  247 + end
  248 +
  249 + test_against_subclass :test_should_overwrite_old_thumbnail_records_when_renaming, ImageWithThumbsAttachment
  250 +
  251 + def test_should_handle_jpeg_quality
  252 + attachment_model ImageWithThumbsAttachment
  253 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  254 + full_size = attachment.size
  255 + attachment_model LowerQualityAttachment
  256 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  257 + lq_size = attachment.size
  258 + assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
  259 +
  260 + attachment_model ImageWithPerThumbJpegAttachment
  261 + attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
  262 + assert_file_jpeg_quality attachment, :thumb, 90
  263 + assert_file_jpeg_quality attachment, :avatar, 85
  264 + assert_file_jpeg_quality attachment, :large, 75
  265 + assert_file_jpeg_quality attachment, nil, 75
  266 + end
  267 + else
  268 + def test_flunk
  269 + puts "RMagick not installed, no tests running"
  270 + end
  271 + end
  272 +end
... ...