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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 \ No newline at end of file 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,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,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,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,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 \ No newline at end of file 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,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 \ No newline at end of file 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,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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/processors/rmagick_processor.rb
@@ -1,66 +0,0 @@ @@ -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,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,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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/backends/file_system_test.rb
@@ -1,143 +0,0 @@ @@ -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,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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/backends/remote/s3_test.rb
@@ -1,119 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/base_attachment_tests.rb
@@ -1,77 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/basic_test.rb
@@ -1,121 +0,0 @@ @@ -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,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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/extra_attachment_test.rb
@@ -1,67 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/fixtures/attachment.rb
@@ -1,297 +0,0 @@ @@ -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 +0,0 @@
1 -foo  
2 \ No newline at end of file 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,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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/processors/core_image_test.rb
@@ -1,58 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/processors/gd2_test.rb
@@ -1,51 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/processors/image_science_test.rb
@@ -1,54 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/test/processors/mini_magick_test.rb
@@ -1,122 +0,0 @@ @@ -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,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,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,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,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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/color.rb
@@ -1,27 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/effects.rb
@@ -1,31 +0,0 @@ @@ -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,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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/quality.rb
@@ -1,25 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/scale.rb
@@ -1,47 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/filters/watermark.rb
@@ -1,32 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
vendor/plugins/attachment_fu/vendor/red_artisan/core_image/processor.rb
@@ -1,123 +0,0 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 \ No newline at end of file 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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 \ No newline at end of file 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 @@ @@ -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 \ No newline at end of file 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 @@ @@ -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 \ No newline at end of file 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 @@ @@ -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 @@ @@ -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 @@ @@ -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 \ No newline at end of file 17 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/backends/file_system_test.rb 0 → 100644
@@ -0,0 +1,143 @@ @@ -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 @@ @@ -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 \ No newline at end of file 103 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/backends/remote/s3_test.rb 0 → 100644
@@ -0,0 +1,119 @@ @@ -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 \ No newline at end of file 120 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/base_attachment_tests.rb 0 → 100644
@@ -0,0 +1,77 @@ @@ -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 \ No newline at end of file 78 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/basic_test.rb 0 → 100644
@@ -0,0 +1,121 @@ @@ -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 @@ @@ -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 \ No newline at end of file 19 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/extra_attachment_test.rb 0 → 100644
@@ -0,0 +1,67 @@ @@ -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 \ No newline at end of file 68 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/fixtures/attachment.rb 0 → 100644
@@ -0,0 +1,297 @@ @@ -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 @@ @@ -0,0 +1 @@
  1 +foo
0 \ No newline at end of file 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 @@ @@ -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 \ No newline at end of file 115 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/processors/core_image_test.rb 0 → 100644
@@ -0,0 +1,58 @@ @@ -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 \ No newline at end of file 59 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/processors/gd2_test.rb 0 → 100644
@@ -0,0 +1,51 @@ @@ -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 \ No newline at end of file 52 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/processors/image_science_test.rb 0 → 100644
@@ -0,0 +1,54 @@ @@ -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 \ No newline at end of file 55 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/processors/mini_magick_test.rb 0 → 100644
@@ -0,0 +1,122 @@ @@ -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 @@ @@ -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