Commit eb5546cefff84ef53c305e3dd52d0bb5e0d29ddc

Authored by Dan Croak
1 parent 8a3201bc

replaced thoughtbot-paperclip with tristandunn-paperclip

Showing 94 changed files with 5038 additions and 4959 deletions   Show diff stats
vendor/gems/thoughtbot-paperclip-2.2.9.2/.specification
... ... @@ -1,126 +0,0 @@
1   ---- !ruby/object:Gem::Specification
2   -name: thoughtbot-paperclip
3   -version: !ruby/object:Gem::Version
4   - version: 2.2.9.2
5   -platform: ruby
6   -authors:
7   -- Jon Yurek
8   -autorequire:
9   -bindir: bin
10   -cert_chain: []
11   -
12   -date: 2009-06-18 00:00:00 -04:00
13   -default_executable:
14   -dependencies:
15   -- !ruby/object:Gem::Dependency
16   - name: thoughtbot-shoulda
17   - type: :development
18   - version_requirement:
19   - version_requirements: !ruby/object:Gem::Requirement
20   - requirements:
21   - - - ">="
22   - - !ruby/object:Gem::Version
23   - version: "0"
24   - version:
25   -- !ruby/object:Gem::Dependency
26   - name: mocha
27   - type: :development
28   - version_requirement:
29   - version_requirements: !ruby/object:Gem::Requirement
30   - requirements:
31   - - - ">="
32   - - !ruby/object:Gem::Version
33   - version: "0"
34   - version:
35   -description:
36   -email: jyurek@thoughtbot.com
37   -executables: []
38   -
39   -extensions: []
40   -
41   -extra_rdoc_files:
42   -- README.rdoc
43   -files:
44   -- README.rdoc
45   -- LICENSE
46   -- Rakefile
47   -- init.rb
48   -- generators/paperclip
49   -- generators/paperclip/paperclip_generator.rb
50   -- generators/paperclip/templates
51   -- generators/paperclip/templates/paperclip_migration.rb.erb
52   -- generators/paperclip/USAGE
53   -- lib/paperclip
54   -- lib/paperclip/attachment.rb
55   -- lib/paperclip/callback_compatability.rb
56   -- lib/paperclip/geometry.rb
57   -- lib/paperclip/interpolations.rb
58   -- lib/paperclip/iostream.rb
59   -- lib/paperclip/matchers
60   -- lib/paperclip/matchers/have_attached_file_matcher.rb
61   -- lib/paperclip/matchers/validate_attachment_content_type_matcher.rb
62   -- lib/paperclip/matchers/validate_attachment_presence_matcher.rb
63   -- lib/paperclip/matchers/validate_attachment_size_matcher.rb
64   -- lib/paperclip/matchers.rb
65   -- lib/paperclip/processor.rb
66   -- lib/paperclip/storage.rb
67   -- lib/paperclip/thumbnail.rb
68   -- lib/paperclip/upfile.rb
69   -- lib/paperclip.rb
70   -- tasks/paperclip_tasks.rake
71   -- test/attachment_test.rb
72   -- test/database.yml
73   -- test/fixtures
74   -- test/fixtures/12k.png
75   -- test/fixtures/50x50.png
76   -- test/fixtures/5k.png
77   -- test/fixtures/bad.png
78   -- test/fixtures/s3.yml
79   -- test/fixtures/text.txt
80   -- test/fixtures/twopage.pdf
81   -- test/geometry_test.rb
82   -- test/helper.rb
83   -- test/integration_test.rb
84   -- test/interpolations_test.rb
85   -- test/iostream_test.rb
86   -- test/matchers
87   -- test/matchers/have_attached_file_matcher_test.rb
88   -- test/matchers/validate_attachment_content_type_matcher_test.rb
89   -- test/matchers/validate_attachment_presence_matcher_test.rb
90   -- test/matchers/validate_attachment_size_matcher_test.rb
91   -- test/paperclip_test.rb
92   -- test/processor_test.rb
93   -- test/storage_test.rb
94   -- test/thumbnail_test.rb
95   -- shoulda_macros/paperclip.rb
96   -has_rdoc: true
97   -homepage: http://www.thoughtbot.com/projects/paperclip
98   -licenses: []
99   -
100   -post_install_message:
101   -rdoc_options:
102   -- --line-numbers
103   -- --inline-source
104   -require_paths:
105   -- lib
106   -required_ruby_version: !ruby/object:Gem::Requirement
107   - requirements:
108   - - - ">="
109   - - !ruby/object:Gem::Version
110   - version: "0"
111   - version:
112   -required_rubygems_version: !ruby/object:Gem::Requirement
113   - requirements:
114   - - - ">="
115   - - !ruby/object:Gem::Version
116   - version: "0"
117   - version:
118   -requirements:
119   -- ImageMagick
120   -rubyforge_project: paperclip
121   -rubygems_version: 1.3.4
122   -signing_key:
123   -specification_version: 2
124   -summary: File attachments as attributes for ActiveRecord
125   -test_files: []
126   -
vendor/gems/thoughtbot-paperclip-2.2.9.2/LICENSE
... ... @@ -1,26 +0,0 @@
1   -
2   -LICENSE
3   -
4   -The MIT License
5   -
6   -Copyright (c) 2008 Jon Yurek and thoughtbot, inc.
7   -
8   -Permission is hereby granted, free of charge, to any person obtaining a copy
9   -of this software and associated documentation files (the "Software"), to deal
10   -in the Software without restriction, including without limitation the rights
11   -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12   -copies of the Software, and to permit persons to whom the Software is
13   -furnished to do so, subject to the following conditions:
14   -
15   -The above copyright notice and this permission notice shall be included in
16   -all copies or substantial portions of the Software.
17   -
18   -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24   -THE SOFTWARE.
25   -
26   -
vendor/gems/thoughtbot-paperclip-2.2.9.2/README.rdoc
... ... @@ -1,174 +0,0 @@
1   -=Paperclip
2   -
3   -Paperclip is intended as an easy file attachment library for ActiveRecord. The
4   -intent behind it was to keep setup as easy as possible and to treat files as
5   -much like other attributes as possible. This means they aren't saved to their
6   -final locations on disk, nor are they deleted if set to nil, until
7   -ActiveRecord::Base#save is called. It manages validations based on size and
8   -presence, if required. It can transform its assigned image into thumbnails if
9   -needed, and the prerequisites are as simple as installing ImageMagick (which,
10   -for most modern Unix-based systems, is as easy as installing the right
11   -packages). Attached files are saved to the filesystem and referenced in the
12   -browser by an easily understandable specification, which has sensible and
13   -useful defaults.
14   -
15   -See the documentation for +has_attached_file+ in Paperclip::ClassMethods for
16   -more detailed options.
17   -
18   -==Quick Start
19   -
20   -In your model:
21   -
22   - class User < ActiveRecord::Base
23   - has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }
24   - end
25   -
26   -In your migrations:
27   -
28   - class AddAvatarColumnsToUser < ActiveRecord::Migration
29   - def self.up
30   - add_column :users, :avatar_file_name, :string
31   - add_column :users, :avatar_content_type, :string
32   - add_column :users, :avatar_file_size, :integer
33   - add_column :users, :avatar_updated_at, :datetime
34   - end
35   -
36   - def self.down
37   - remove_column :users, :avatar_file_name
38   - remove_column :users, :avatar_content_type
39   - remove_column :users, :avatar_file_size
40   - remove_column :users, :avatar_updated_at
41   - end
42   - end
43   -
44   -In your edit and new views:
45   -
46   - <% form_for :user, @user, :url => user_path, :html => { :multipart => true } do |form| %>
47   - <%= form.file_field :avatar %>
48   - <% end %>
49   -
50   -In your controller:
51   -
52   - def create
53   - @user = User.create( params[:user] )
54   - end
55   -
56   -In your show view:
57   -
58   - <%= image_tag @user.avatar.url %>
59   - <%= image_tag @user.avatar.url(:medium) %>
60   - <%= image_tag @user.avatar.url(:thumb) %>
61   -
62   -==Usage
63   -
64   -The basics of paperclip are quite simple: Declare that your model has an
65   -attachment with the has_attached_file method, and give it a name. Paperclip
66   -will wrap up up to four attributes (all prefixed with that attachment's name,
67   -so you can have multiple attachments per model if you wish) and give the a
68   -friendly front end. The attributes are <attachment>_file_name,
69   -<attachment>_file_size, <attachment>_content_type, and <attachment>_updated_at.
70   -Only <attachment>_file_name is required for paperclip to operate. More
71   -information about the options to has_attached_file is available in the
72   -documentation of Paperclip::ClassMethods.
73   -
74   -Attachments can be validated with Paperclip's validation methods,
75   -validates_attachment_presence, validates_attachment_content_type, and
76   -validates_attachment_size.
77   -
78   -==Storage
79   -
80   -The files that are assigned as attachments are, by default, placed in the
81   -directory specified by the :path option to has_attached_file. By default, this
82   -location is ":rails_root/public/system/:attachment/:id/:style/:filename". This
83   -location was chosen because on standard Capistrano deployments, the
84   -public/system directory is symlinked to the app's shared directory, meaning it
85   -will survive between deployments. For example, using that :path, you may have a
86   -file at
87   -
88   - /data/myapp/releases/20081229172410/public/system/avatars/13/small/my_pic.png
89   -
90   -NOTE: This is a change from previous versions of Paperclip, but is overall a
91   -safer choice for the default file store.
92   -
93   -You may also choose to store your files using Amazon's S3 service. You can find
94   -more information about S3 storage at the description for
95   -Paperclip::Storage::S3.
96   -
97   -Files on the local filesystem (and in the Rails app's public directory) will be
98   -available to the internet at large. If you require access control, it's
99   -possible to place your files in a different location. You will need to change
100   -both the :path and :url options in order to make sure the files are unavailable
101   -to the public. Both :path and :url allow the same set of interpolated
102   -variables.
103   -
104   -==Post Processing
105   -
106   -Paperclip supports an extensible selection of post-processors. When you define
107   -a set of styles for an attachment, by default it is expected that those
108   -"styles" are actually "thumbnails". However, you can do much more than just
109   -thumbnail images. By defining a subclass of Paperclip::Processor, you can
110   -perform any processing you want on the files that are attached. Any file in
111   -your Rails app's lib/paperclip_processors directory is automatically loaded by
112   -paperclip, allowing you to easily define custom processors. You can specify a
113   -processor with the :processors option to has_attached_file:
114   -
115   - has_attached_file :scan, :styles => { :text => { :quality => :better } },
116   - :processors => [:ocr]
117   -
118   -This would load the hypothetical class Paperclip::Ocr, which would have the
119   -hash "{ :quality => :better }" passed to it along with the uploaded file. For
120   -more information about defining processors, see Paperclip::Processor.
121   -
122   -The default processor is Paperclip::Thumbnail. For backwards compatability
123   -reasons, you can pass a single geometry string or an array containing a
124   -geometry and a format, which the file will be converted to, like so:
125   -
126   - has_attached_file :avatar, :styles => { :thumb => ["32x32#", :png] }
127   -
128   -This will convert the "thumb" style to a 32x32 square in png format, regardless
129   -of what was uploaded. If the format is not specified, it is kept the same (i.e.
130   -jpgs will remain jpgs).
131   -
132   -Multiple processors can be specified, and they will be invoked in the order
133   -they are defined in the :processors array. Each successive processor will
134   -be given the result of the previous processor's execution. All processors will
135   -receive the same parameters, which are what you define in the :styles hash.
136   -For example, assuming we had this definition:
137   -
138   - has_attached_file :scan, :styles => { :text => { :quality => :better } },
139   - :processors => [:rotator, :ocr]
140   -
141   -then both the :rotator processor and the :ocr processor would receive the
142   -options "{ :quality => :better }". This parameter may not mean anything to one
143   -or more or the processors, and they are expected to ignore it.
144   -
145   -NOTE: Because processors operate by turning the original attachment into the
146   -styles, no processors will be run if there are no styles defined.
147   -
148   -==Events
149   -
150   -Before and after the Post Processing step, Paperclip calls back to the model
151   -with a few callbacks, allowing the model to change or cancel the processing
152   -step. The callbacks are "before_post_process" and "after_post_process" (which
153   -are called before and after the processing of each attachment), and the
154   -attachment-specific "before_<attachment>_post_process" and
155   -"after_<attachment>_post_process". The callbacks are intended to be as close to
156   -normal ActiveRecord callbacks as possible, so if you return false (specifically
157   -- returning nil is not the same) in a before_ filter, the post processing step
158   -will halt. Returning false in an after_ filter will not halt anything, but you
159   -can access the model and the attachment if necessary.
160   -
161   -NOTE: Post processing will not even *start* if the attachment is not valid
162   -according to the validations. Your callbacks and processors will *only* be
163   -called with valid attachments.
164   -
165   -==Contributing
166   -
167   -If you'd like to contribute a feature or bugfix: Thanks! To make sure your
168   -fix/feature has a high chance of being included, please read the following
169   -guidelines:
170   -
171   -1. Ask on the mailing list, or post a new GitHub Issue.
172   -2. Make sure there are tests! We will not accept any patch that is not tested.
173   - It's a rare time when explicit tests aren't needed. If you have questions
174   - about writing tests for paperclip, please ask the mailing list.
vendor/gems/thoughtbot-paperclip-2.2.9.2/Rakefile
... ... @@ -1,99 +0,0 @@
1   -require 'rake'
2   -require 'rake/testtask'
3   -require 'rake/rdoctask'
4   -
5   -$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
6   -require 'paperclip'
7   -
8   -desc 'Default: run unit tests.'
9   -task :default => [:clean, :test]
10   -
11   -desc 'Test the paperclip plugin.'
12   -Rake::TestTask.new(:test) do |t|
13   - t.libs << 'lib' << 'profile'
14   - t.pattern = 'test/**/*_test.rb'
15   - t.verbose = true
16   -end
17   -
18   -desc 'Start an IRB session with all necessary files required.'
19   -task :shell do |t|
20   - chdir File.dirname(__FILE__)
21   - exec 'irb -I lib/ -I lib/paperclip -r rubygems -r active_record -r tempfile -r init'
22   -end
23   -
24   -desc 'Generate documentation for the paperclip plugin.'
25   -Rake::RDocTask.new(:rdoc) do |rdoc|
26   - rdoc.rdoc_dir = 'doc'
27   - rdoc.title = 'Paperclip'
28   - rdoc.options << '--line-numbers' << '--inline-source'
29   - rdoc.rdoc_files.include('README*')
30   - rdoc.rdoc_files.include('lib/**/*.rb')
31   -end
32   -
33   -desc 'Update documentation on website'
34   -task :sync_docs => 'rdoc' do
35   - `rsync -ave ssh doc/ dev@dev.thoughtbot.com:/home/dev/www/dev.thoughtbot.com/paperclip`
36   -end
37   -
38   -desc 'Clean up files.'
39   -task :clean do |t|
40   - FileUtils.rm_rf "doc"
41   - FileUtils.rm_rf "tmp"
42   - FileUtils.rm_rf "pkg"
43   - FileUtils.rm "test/debug.log" rescue nil
44   - FileUtils.rm "test/paperclip.db" rescue nil
45   - Dir.glob("paperclip-*.gem").each{|f| FileUtils.rm f }
46   -end
47   -
48   -include_file_globs = ["README*",
49   - "LICENSE",
50   - "Rakefile",
51   - "init.rb",
52   - "{generators,lib,tasks,test,shoulda_macros}/**/*"]
53   -exclude_file_globs = ["test/s3.yml",
54   - "test/debug.log",
55   - "test/paperclip.db",
56   - "test/doc",
57   - "test/doc/*",
58   - "test/pkg",
59   - "test/pkg/*",
60   - "test/tmp",
61   - "test/tmp/*"]
62   -spec = Gem::Specification.new do |s|
63   - s.name = "paperclip"
64   - s.version = Paperclip::VERSION
65   - s.author = "Jon Yurek"
66   - s.email = "jyurek@thoughtbot.com"
67   - s.homepage = "http://www.thoughtbot.com/projects/paperclip"
68   - s.platform = Gem::Platform::RUBY
69   - s.summary = "File attachments as attributes for ActiveRecord"
70   - s.files = FileList[include_file_globs].to_a - FileList[exclude_file_globs].to_a
71   - s.require_path = "lib"
72   - s.test_files = FileList["test/**/test_*.rb"].to_a
73   - s.rubyforge_project = "paperclip"
74   - s.has_rdoc = true
75   - s.extra_rdoc_files = FileList["README*"].to_a
76   - s.rdoc_options << '--line-numbers' << '--inline-source'
77   - s.requirements << "ImageMagick"
78   - s.add_development_dependency 'thoughtbot-shoulda'
79   - s.add_development_dependency 'mocha'
80   -end
81   -
82   -desc "Print a list of the files to be put into the gem"
83   -task :manifest => :clean do
84   - spec.files.each do |file|
85   - puts file
86   - end
87   -end
88   -
89   -desc "Generate a gemspec file for GitHub"
90   -task :gemspec => :clean do
91   - File.open("#{spec.name}.gemspec", 'w') do |f|
92   - f.write spec.to_ruby
93   - end
94   -end
95   -
96   -desc "Build the gem into the current directory"
97   -task :gem => :gemspec do
98   - `gem build #{spec.name}.gemspec`
99   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/generators/paperclip/USAGE
... ... @@ -1,5 +0,0 @@
1   -Usage:
2   -
3   - script/generate paperclip Class attachment1 (attachment2 ...)
4   -
5   -This will create a migration that will add the proper columns to your class's table.
6 0 \ No newline at end of file
vendor/gems/thoughtbot-paperclip-2.2.9.2/generators/paperclip/paperclip_generator.rb
... ... @@ -1,27 +0,0 @@
1   -class PaperclipGenerator < Rails::Generator::NamedBase
2   - attr_accessor :attachments, :migration_name
3   -
4   - def initialize(args, options = {})
5   - super
6   - @class_name, @attachments = args[0], args[1..-1]
7   - end
8   -
9   - def manifest
10   - file_name = generate_file_name
11   - @migration_name = file_name.camelize
12   - record do |m|
13   - m.migration_template "paperclip_migration.rb.erb",
14   - File.join('db', 'migrate'),
15   - :migration_file_name => file_name
16   - end
17   - end
18   -
19   - private
20   -
21   - def generate_file_name
22   - names = attachments.map{|a| a.underscore }
23   - names = names[0..-2] + ["and", names[-1]] if names.length > 1
24   - "add_attachments_#{names.join("_")}_to_#{@class_name.underscore}"
25   - end
26   -
27   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/generators/paperclip/templates/paperclip_migration.rb.erb
... ... @@ -1,19 +0,0 @@
1   -class <%= migration_name %> < ActiveRecord::Migration
2   - def self.up
3   -<% attachments.each do |attachment| -%>
4   - add_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_file_name, :string
5   - add_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_content_type, :string
6   - add_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_file_size, :integer
7   - add_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_updated_at, :datetime
8   -<% end -%>
9   - end
10   -
11   - def self.down
12   -<% attachments.each do |attachment| -%>
13   - remove_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_file_name
14   - remove_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_content_type
15   - remove_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_file_size
16   - remove_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_updated_at
17   -<% end -%>
18   - end
19   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/init.rb
... ... @@ -1 +0,0 @@
1   -require File.join(File.dirname(__FILE__), "lib", "paperclip")
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip.rb
... ... @@ -1,350 +0,0 @@
1   -# Paperclip allows file attachments that are stored in the filesystem. All graphical
2   -# transformations are done using the Graphics/ImageMagick command line utilities and
3   -# are stored in Tempfiles until the record is saved. Paperclip does not require a
4   -# separate model for storing the attachment's information, instead adding a few simple
5   -# columns to your table.
6   -#
7   -# Author:: Jon Yurek
8   -# Copyright:: Copyright (c) 2008-2009 thoughtbot, inc.
9   -# License:: MIT License (http://www.opensource.org/licenses/mit-license.php)
10   -#
11   -# Paperclip defines an attachment as any file, though it makes special considerations
12   -# for image files. You can declare that a model has an attached file with the
13   -# +has_attached_file+ method:
14   -#
15   -# class User < ActiveRecord::Base
16   -# has_attached_file :avatar, :styles => { :thumb => "100x100" }
17   -# end
18   -#
19   -# user = User.new
20   -# user.avatar = params[:user][:avatar]
21   -# user.avatar.url
22   -# # => "/users/avatars/4/original_me.jpg"
23   -# user.avatar.url(:thumb)
24   -# # => "/users/avatars/4/thumb_me.jpg"
25   -#
26   -# See the +has_attached_file+ documentation for more details.
27   -
28   -require 'tempfile'
29   -require 'paperclip/upfile'
30   -require 'paperclip/iostream'
31   -require 'paperclip/geometry'
32   -require 'paperclip/processor'
33   -require 'paperclip/thumbnail'
34   -require 'paperclip/storage'
35   -require 'paperclip/interpolations'
36   -require 'paperclip/attachment'
37   -if defined? RAILS_ROOT
38   - Dir.glob(File.join(File.expand_path(RAILS_ROOT), "lib", "paperclip_processors", "*.rb")).each do |processor|
39   - require processor
40   - end
41   -end
42   -
43   -# The base module that gets included in ActiveRecord::Base. See the
44   -# documentation for Paperclip::ClassMethods for more useful information.
45   -module Paperclip
46   -
47   - VERSION = "2.2.9.2"
48   -
49   - class << self
50   - # Provides configurability to Paperclip. There are a number of options available, such as:
51   - # * whiny: Will raise an error if Paperclip cannot process thumbnails of
52   - # an uploaded image. Defaults to true.
53   - # * log: Logs progress to the Rails log. Uses ActiveRecord's logger, so honors
54   - # log levels, etc. Defaults to true.
55   - # * command_path: Defines the path at which to find the command line
56   - # programs if they are not visible to Rails the system's search path. Defaults to
57   - # nil, which uses the first executable found in the user's search path.
58   - # * image_magick_path: Deprecated alias of command_path.
59   - def options
60   - @options ||= {
61   - :whiny => true,
62   - :image_magick_path => nil,
63   - :command_path => nil,
64   - :log => true,
65   - :log_command => false,
66   - :swallow_stderr => true
67   - }
68   - end
69   -
70   - def path_for_command command #:nodoc:
71   - if options[:image_magick_path]
72   - warn("[DEPRECATION] :image_magick_path is deprecated and will be removed. Use :command_path instead")
73   - end
74   - path = [options[:command_path] || options[:image_magick_path], command].compact
75   - File.join(*path)
76   - end
77   -
78   - def interpolates key, &block
79   - Paperclip::Interpolations[key] = block
80   - end
81   -
82   - # The run method takes a command to execute and a string of parameters
83   - # that get passed to it. The command is prefixed with the :command_path
84   - # option from Paperclip.options. If you have many commands to run and
85   - # they are in different paths, the suggested course of action is to
86   - # symlink them so they are all in the same directory.
87   - #
88   - # If the command returns with a result code that is not one of the
89   - # expected_outcodes, a PaperclipCommandLineError will be raised. Generally
90   - # a code of 0 is expected, but a list of codes may be passed if necessary.
91   - #
92   - # This method can log the command being run when
93   - # Paperclip.options[:log_command] is set to true (defaults to false). This
94   - # will only log if logging in general is set to true as well.
95   - def run cmd, params = "", expected_outcodes = 0
96   - command = %Q<#{%Q[#{path_for_command(cmd)} #{params}].gsub(/\s+/, " ")}>
97   - command = "#{command} 2>#{bit_bucket}" if Paperclip.options[:swallow_stderr]
98   - Paperclip.log(command) if Paperclip.options[:log_command]
99   - output = `#{command}`
100   - unless [expected_outcodes].flatten.include?($?.exitstatus)
101   - raise PaperclipCommandLineError, "Error while running #{cmd}"
102   - end
103   - output
104   - end
105   -
106   - def bit_bucket #:nodoc:
107   - File.exists?("/dev/null") ? "/dev/null" : "NUL"
108   - end
109   -
110   - def included base #:nodoc:
111   - base.extend ClassMethods
112   - unless base.respond_to?(:define_callbacks)
113   - base.send(:include, Paperclip::CallbackCompatability)
114   - end
115   - end
116   -
117   - def processor name #:nodoc:
118   - name = name.to_s.camelize
119   - processor = Paperclip.const_get(name)
120   - unless processor.ancestors.include?(Paperclip::Processor)
121   - raise PaperclipError.new("Processor #{name} was not found")
122   - end
123   - processor
124   - end
125   -
126   - # Log a paperclip-specific line. Uses ActiveRecord::Base.logger
127   - # by default. Set Paperclip.options[:log] to false to turn off.
128   - def log message
129   - logger.info("[paperclip] #{message}") if logging?
130   - end
131   -
132   - def logger #:nodoc:
133   - ActiveRecord::Base.logger
134   - end
135   -
136   - def logging? #:nodoc:
137   - options[:log]
138   - end
139   - end
140   -
141   - class PaperclipError < StandardError #:nodoc:
142   - end
143   -
144   - class PaperclipCommandLineError < StandardError #:nodoc:
145   - end
146   -
147   - class NotIdentifiedByImageMagickError < PaperclipError #:nodoc:
148   - end
149   -
150   - class InfiniteInterpolationError < PaperclipError #:nodoc:
151   - end
152   -
153   - module ClassMethods
154   - # +has_attached_file+ gives the class it is called on an attribute that maps to a file. This
155   - # is typically a file stored somewhere on the filesystem and has been uploaded by a user.
156   - # The attribute returns a Paperclip::Attachment object which handles the management of
157   - # that file. The intent is to make the attachment as much like a normal attribute. The
158   - # thumbnails will be created when the new file is assigned, but they will *not* be saved
159   - # until +save+ is called on the record. Likewise, if the attribute is set to +nil+ is
160   - # called on it, the attachment will *not* be deleted until +save+ is called. See the
161   - # Paperclip::Attachment documentation for more specifics. There are a number of options
162   - # you can set to change the behavior of a Paperclip attachment:
163   - # * +url+: The full URL of where the attachment is publically accessible. This can just
164   - # as easily point to a directory served directly through Apache as it can to an action
165   - # that can control permissions. You can specify the full domain and path, but usually
166   - # just an absolute path is sufficient. The leading slash *must* be included manually for
167   - # absolute paths. The default value is
168   - # "/system/:attachment/:id/:style/:filename". See
169   - # Paperclip::Attachment#interpolate for more information on variable interpolaton.
170   - # :url => "/:class/:attachment/:id/:style_:filename"
171   - # :url => "http://some.other.host/stuff/:class/:id_:extension"
172   - # * +default_url+: The URL that will be returned if there is no attachment assigned.
173   - # This field is interpolated just as the url is. The default value is
174   - # "/:attachment/:style/missing.png"
175   - # has_attached_file :avatar, :default_url => "/images/default_:style_avatar.png"
176   - # User.new.avatar_url(:small) # => "/images/default_small_avatar.png"
177   - # * +styles+: A hash of thumbnail styles and their geometries. You can find more about
178   - # geometry strings at the ImageMagick website
179   - # (http://www.imagemagick.org/script/command-line-options.php#resize). Paperclip
180   - # also adds the "#" option (e.g. "50x50#"), which will resize the image to fit maximally
181   - # inside the dimensions and then crop the rest off (weighted at the center). The
182   - # default value is to generate no thumbnails.
183   - # * +default_style+: The thumbnail style that will be used by default URLs.
184   - # Defaults to +original+.
185   - # has_attached_file :avatar, :styles => { :normal => "100x100#" },
186   - # :default_style => :normal
187   - # user.avatar.url # => "/avatars/23/normal_me.png"
188   - # * +whiny+: Will raise an error if Paperclip cannot post_process an uploaded file due
189   - # to a command line error. This will override the global setting for this attachment.
190   - # Defaults to true. This option used to be called :whiny_thumbanils, but this is
191   - # deprecated.
192   - # * +convert_options+: When creating thumbnails, use this free-form options
193   - # field to pass in various convert command options. Typical options are "-strip" to
194   - # remove all Exif data from the image (save space for thumbnails and avatars) or
195   - # "-depth 8" to specify the bit depth of the resulting conversion. See ImageMagick
196   - # convert documentation for more options: (http://www.imagemagick.org/script/convert.php)
197   - # Note that this option takes a hash of options, each of which correspond to the style
198   - # of thumbnail being generated. You can also specify :all as a key, which will apply
199   - # to all of the thumbnails being generated. If you specify options for the :original,
200   - # it would be best if you did not specify destructive options, as the intent of keeping
201   - # the original around is to regenerate all the thumbnails when requirements change.
202   - # has_attached_file :avatar, :styles => { :large => "300x300", :negative => "100x100" }
203   - # :convert_options => {
204   - # :all => "-strip",
205   - # :negative => "-negate"
206   - # }
207   - # NOTE: While not deprecated yet, it is not recommended to specify options this way.
208   - # It is recommended that :convert_options option be included in the hash passed to each
209   - # :styles for compatability with future versions.
210   - # * +storage+: Chooses the storage backend where the files will be stored. The current
211   - # choices are :filesystem and :s3. The default is :filesystem. Make sure you read the
212   - # documentation for Paperclip::Storage::Filesystem and Paperclip::Storage::S3
213   - # for backend-specific options.
214   - def has_attached_file name, options = {}
215   - include InstanceMethods
216   -
217   - write_inheritable_attribute(:attachment_definitions, {}) if attachment_definitions.nil?
218   - attachment_definitions[name] = {:validations => []}.merge(options)
219   -
220   - after_save :save_attached_files
221   - before_destroy :destroy_attached_files
222   -
223   - define_callbacks :before_post_process, :after_post_process
224   - define_callbacks :"before_#{name}_post_process", :"after_#{name}_post_process"
225   -
226   - define_method name do |*args|
227   - a = attachment_for(name)
228   - (args.length > 0) ? a.to_s(args.first) : a
229   - end
230   -
231   - define_method "#{name}=" do |file|
232   - attachment_for(name).assign(file)
233   - end
234   -
235   - define_method "#{name}?" do
236   - attachment_for(name).file?
237   - end
238   -
239   - validates_each(name) do |record, attr, value|
240   - attachment = record.attachment_for(name)
241   - attachment.send(:flush_errors) unless attachment.valid?
242   - end
243   - end
244   -
245   - # Places ActiveRecord-style validations on the size of the file assigned. The
246   - # possible options are:
247   - # * +in+: a Range of bytes (i.e. +1..1.megabyte+),
248   - # * +less_than+: equivalent to :in => 0..options[:less_than]
249   - # * +greater_than+: equivalent to :in => options[:greater_than]..Infinity
250   - # * +message+: error message to display, use :min and :max as replacements
251   - # * +if+: A lambda or name of a method on the instance. Validation will only
252   - # be run is this lambda or method returns true.
253   - # * +unless+: Same as +if+ but validates if lambda or method returns false.
254   - def validates_attachment_size name, options = {}
255   - min = options[:greater_than] || (options[:in] && options[:in].first) || 0
256   - max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
257   - range = (min..max)
258   - message = options[:message] || "file size must be between :min and :max bytes."
259   -
260   - attachment_definitions[name][:validations] << [:size, {:range => range,
261   - :message => message,
262   - :if => options[:if],
263   - :unless => options[:unless]}]
264   - end
265   -
266   - # Adds errors if thumbnail creation fails. The same as specifying :whiny_thumbnails => true.
267   - def validates_attachment_thumbnails name, options = {}
268   - warn('[DEPRECATION] validates_attachment_thumbnail is deprecated. ' +
269   - 'This validation is on by default and will be removed from future versions. ' +
270   - 'If you wish to turn it off, supply :whiny => false in your definition.')
271   - attachment_definitions[name][:whiny_thumbnails] = true
272   - end
273   -
274   - # Places ActiveRecord-style validations on the presence of a file.
275   - # Options:
276   - # * +if+: A lambda or name of a method on the instance. Validation will only
277   - # be run is this lambda or method returns true.
278   - # * +unless+: Same as +if+ but validates if lambda or method returns false.
279   - def validates_attachment_presence name, options = {}
280   - message = options[:message] || "must be set."
281   - attachment_definitions[name][:validations] << [:presence, {:message => message,
282   - :if => options[:if],
283   - :unless => options[:unless]}]
284   - end
285   -
286   - # Places ActiveRecord-style validations on the content type of the file
287   - # assigned. The possible options are:
288   - # * +content_type+: Allowed content types. Can be a single content type
289   - # or an array. Each type can be a String or a Regexp. It should be
290   - # noted that Internet Explorer upload files with content_types that you
291   - # may not expect. For example, JPEG images are given image/pjpeg and
292   - # PNGs are image/x-png, so keep that in mind when determining how you
293   - # match. Allows all by default.
294   - # * +message+: The message to display when the uploaded file has an invalid
295   - # content type.
296   - # * +if+: A lambda or name of a method on the instance. Validation will only
297   - # be run is this lambda or method returns true.
298   - # * +unless+: Same as +if+ but validates if lambda or method returns false.
299   - # NOTE: If you do not specify an [attachment]_content_type field on your
300   - # model, content_type validation will work _ONLY upon assignment_ and
301   - # re-validation after the instance has been reloaded will always succeed.
302   - def validates_attachment_content_type name, options = {}
303   - attachment_definitions[name][:validations] << [:content_type, {:content_type => options[:content_type],
304   - :message => options[:message],
305   - :if => options[:if],
306   - :unless => options[:unless]}]
307   - end
308   -
309   - # Returns the attachment definitions defined by each call to
310   - # has_attached_file.
311   - def attachment_definitions
312   - read_inheritable_attribute(:attachment_definitions)
313   - end
314   - end
315   -
316   - module InstanceMethods #:nodoc:
317   - def attachment_for name
318   - @_paperclip_attachments ||= {}
319   - @_paperclip_attachments[name] ||= Attachment.new(name, self, self.class.attachment_definitions[name])
320   - end
321   -
322   - def each_attachment
323   - self.class.attachment_definitions.each do |name, definition|
324   - yield(name, attachment_for(name))
325   - end
326   - end
327   -
328   - def save_attached_files
329   - logger.info("[paperclip] Saving attachments.")
330   - each_attachment do |name, attachment|
331   - attachment.send(:save)
332   - end
333   - end
334   -
335   - def destroy_attached_files
336   - logger.info("[paperclip] Deleting attachments.")
337   - each_attachment do |name, attachment|
338   - attachment.send(:queue_existing_for_delete)
339   - attachment.send(:flush_deletes)
340   - end
341   - end
342   - end
343   -
344   -end
345   -
346   -# Set it all up.
347   -if Object.const_defined?("ActiveRecord")
348   - ActiveRecord::Base.send(:include, Paperclip)
349   - File.send(:include, Paperclip::Upfile)
350   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/attachment.rb
... ... @@ -1,413 +0,0 @@
1   -module Paperclip
2   - # The Attachment class manages the files for a given attachment. It saves
3   - # when the model saves, deletes when the model is destroyed, and processes
4   - # the file upon assignment.
5   - class Attachment
6   -
7   - def self.default_options
8   - @default_options ||= {
9   - :url => "/system/:attachment/:id/:style/:filename",
10   - :path => ":rails_root/public:url",
11   - :styles => {},
12   - :default_url => "/:attachment/:style/missing.png",
13   - :default_style => :original,
14   - :validations => [],
15   - :storage => :filesystem,
16   - :whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails]
17   - }
18   - end
19   -
20   - attr_reader :name, :instance, :styles, :default_style, :convert_options, :queued_for_write, :options
21   -
22   - # Creates an Attachment object. +name+ is the name of the attachment,
23   - # +instance+ is the ActiveRecord object instance it's attached to, and
24   - # +options+ is the same as the hash passed to +has_attached_file+.
25   - def initialize name, instance, options = {}
26   - @name = name
27   - @instance = instance
28   -
29   - options = self.class.default_options.merge(options)
30   -
31   - @url = options[:url]
32   - @url = @url.call(self) if @url.is_a?(Proc)
33   - @path = options[:path]
34   - @path = @path.call(self) if @path.is_a?(Proc)
35   - @styles = options[:styles]
36   - @styles = @styles.call(self) if @styles.is_a?(Proc)
37   - @default_url = options[:default_url]
38   - @validations = options[:validations]
39   - @default_style = options[:default_style]
40   - @storage = options[:storage]
41   - @whiny = options[:whiny_thumbnails] || options[:whiny]
42   - @convert_options = options[:convert_options] || {}
43   - @processors = options[:processors] || [:thumbnail]
44   - @options = options
45   - @queued_for_delete = []
46   - @queued_for_write = {}
47   - @errors = {}
48   - @validation_errors = nil
49   - @dirty = false
50   -
51   - normalize_style_definition
52   - initialize_storage
53   - end
54   -
55   - # What gets called when you call instance.attachment = File. It clears
56   - # errors, assigns attributes, processes the file, and runs validations. It
57   - # also queues up the previous file for deletion, to be flushed away on
58   - # #save of its host. In addition to form uploads, you can also assign
59   - # another Paperclip attachment:
60   - # new_user.avatar = old_user.avatar
61   - # If the file that is assigned is not valid, the processing (i.e.
62   - # thumbnailing, etc) will NOT be run.
63   - def assign uploaded_file
64   - ensure_required_accessors!
65   -
66   - if uploaded_file.is_a?(Paperclip::Attachment)
67   - uploaded_file = uploaded_file.to_file(:original)
68   - close_uploaded_file = uploaded_file.respond_to?(:close)
69   - end
70   -
71   - return nil unless valid_assignment?(uploaded_file)
72   -
73   - uploaded_file.binmode if uploaded_file.respond_to? :binmode
74   - self.clear
75   -
76   - return nil if uploaded_file.nil?
77   -
78   - @queued_for_write[:original] = uploaded_file.to_tempfile
79   - instance_write(:file_name, uploaded_file.original_filename.strip.gsub(/[^\w\d\.\-]+/, '_'))
80   - instance_write(:content_type, uploaded_file.content_type.to_s.strip)
81   - instance_write(:file_size, uploaded_file.size.to_i)
82   - instance_write(:updated_at, Time.now)
83   -
84   - @dirty = true
85   -
86   - post_process if valid?
87   -
88   - # Reset the file size if the original file was reprocessed.
89   - instance_write(:file_size, @queued_for_write[:original].size.to_i)
90   - ensure
91   - uploaded_file.close if close_uploaded_file
92   - validate
93   - end
94   -
95   - # Returns the public URL of the attachment, with a given style. Note that
96   - # this does not necessarily need to point to a file that your web server
97   - # can access and can point to an action in your app, if you need fine
98   - # grained security. This is not recommended if you don't need the
99   - # security, however, for performance reasons. set
100   - # include_updated_timestamp to false if you want to stop the attachment
101   - # update time appended to the url
102   - def url style = default_style, include_updated_timestamp = true
103   - url = original_filename.nil? ? interpolate(@default_url, style) : interpolate(@url, style)
104   - include_updated_timestamp && updated_at ? [url, updated_at].compact.join(url.include?("?") ? "&" : "?") : url
105   - end
106   -
107   - # Returns the path of the attachment as defined by the :path option. If the
108   - # file is stored in the filesystem the path refers to the path of the file
109   - # on disk. If the file is stored in S3, the path is the "key" part of the
110   - # URL, and the :bucket option refers to the S3 bucket.
111   - def path style = default_style
112   - original_filename.nil? ? nil : interpolate(@path, style)
113   - end
114   -
115   - # Alias to +url+
116   - def to_s style = nil
117   - url(style)
118   - end
119   -
120   - # Returns true if there are no errors on this attachment.
121   - def valid?
122   - validate
123   - errors.empty?
124   - end
125   -
126   - # Returns an array containing the errors on this attachment.
127   - def errors
128   - @errors
129   - end
130   -
131   - # Returns true if there are changes that need to be saved.
132   - def dirty?
133   - @dirty
134   - end
135   -
136   - # Saves the file, if there are no errors. If there are, it flushes them to
137   - # the instance's errors and returns false, cancelling the save.
138   - def save
139   - if valid?
140   - flush_deletes
141   - flush_writes
142   - @dirty = false
143   - true
144   - else
145   - flush_errors
146   - false
147   - end
148   - end
149   -
150   - # Clears out the attachment. Has the same effect as previously assigning
151   - # nil to the attachment. Does NOT save. If you wish to clear AND save,
152   - # use #destroy.
153   - def clear
154   - queue_existing_for_delete
155   - @errors = {}
156   - @validation_errors = nil
157   - end
158   -
159   - # Destroys the attachment. Has the same effect as previously assigning
160   - # nil to the attachment *and saving*. This is permanent. If you wish to
161   - # wipe out the existing attachment but not save, use #clear.
162   - def destroy
163   - clear
164   - save
165   - end
166   -
167   - # Returns the name of the file as originally assigned, and lives in the
168   - # <attachment>_file_name attribute of the model.
169   - def original_filename
170   - instance_read(:file_name)
171   - end
172   -
173   - # Returns the size of the file as originally assigned, and lives in the
174   - # <attachment>_file_size attribute of the model.
175   - def size
176   - instance_read(:file_size) || (@queued_for_write[:original] && @queued_for_write[:original].size)
177   - end
178   -
179   - # Returns the content_type of the file as originally assigned, and lives
180   - # in the <attachment>_content_type attribute of the model.
181   - def content_type
182   - instance_read(:content_type)
183   - end
184   -
185   - # Returns the last modified time of the file as originally assigned, and
186   - # lives in the <attachment>_updated_at attribute of the model.
187   - def updated_at
188   - time = instance_read(:updated_at)
189   - time && time.to_i
190   - end
191   -
192   - # Paths and URLs can have a number of variables interpolated into them
193   - # to vary the storage location based on name, id, style, class, etc.
194   - # This method is a deprecated access into supplying and retrieving these
195   - # interpolations. Future access should use either Paperclip.interpolates
196   - # or extend the Paperclip::Interpolations module directly.
197   - def self.interpolations
198   - warn('[DEPRECATION] Paperclip::Attachment.interpolations is deprecated ' +
199   - 'and will be removed from future versions. ' +
200   - 'Use Paperclip.interpolates instead')
201   - Paperclip::Interpolations
202   - end
203   -
204   - # This method really shouldn't be called that often. It's expected use is
205   - # in the paperclip:refresh rake task and that's it. It will regenerate all
206   - # thumbnails forcefully, by reobtaining the original file and going through
207   - # the post-process again.
208   - def reprocess!
209   - new_original = Tempfile.new("paperclip-reprocess")
210   - new_original.binmode
211   - if old_original = to_file(:original)
212   - new_original.write( old_original.read )
213   - new_original.rewind
214   -
215   - @queued_for_write = { :original => new_original }
216   - post_process
217   -
218   - old_original.close if old_original.respond_to?(:close)
219   -
220   - save
221   - else
222   - true
223   - end
224   - end
225   -
226   - # Returns true if a file has been assigned.
227   - def file?
228   - !original_filename.blank?
229   - end
230   -
231   - # Writes the attachment-specific attribute on the instance. For example,
232   - # instance_write(:file_name, "me.jpg") will write "me.jpg" to the instance's
233   - # "avatar_file_name" field (assuming the attachment is called avatar).
234   - def instance_write(attr, value)
235   - setter = :"#{name}_#{attr}="
236   - responds = instance.respond_to?(setter)
237   - self.instance_variable_set("@_#{setter.to_s.chop}", value)
238   - instance.send(setter, value) if responds || attr.to_s == "file_name"
239   - end
240   -
241   - # Reads the attachment-specific attribute on the instance. See instance_write
242   - # for more details.
243   - def instance_read(attr)
244   - getter = :"#{name}_#{attr}"
245   - responds = instance.respond_to?(getter)
246   - cached = self.instance_variable_get("@_#{getter}")
247   - return cached if cached
248   - instance.send(getter) if responds || attr.to_s == "file_name"
249   - end
250   -
251   - private
252   -
253   - def ensure_required_accessors! #:nodoc:
254   - %w(file_name).each do |field|
255   - unless @instance.respond_to?("#{name}_#{field}") && @instance.respond_to?("#{name}_#{field}=")
256   - raise PaperclipError.new("#{@instance.class} model missing required attr_accessor for '#{name}_#{field}'")
257   - end
258   - end
259   - end
260   -
261   - def log message #:nodoc:
262   - Paperclip.log(message)
263   - end
264   -
265   - def valid_assignment? file #:nodoc:
266   - file.nil? || (file.respond_to?(:original_filename) && file.respond_to?(:content_type))
267   - end
268   -
269   - def validate #:nodoc:
270   - unless @validation_errors
271   - @validation_errors = @validations.inject({}) do |errors, validation|
272   - name, options = validation
273   - errors[name] = send(:"validate_#{name}", options) if allow_validation?(options)
274   - errors
275   - end
276   - @validation_errors.reject!{|k,v| v == nil }
277   - @errors.merge!(@validation_errors)
278   - end
279   - @validation_errors
280   - end
281   -
282   - def allow_validation? options #:nodoc:
283   - (options[:if].nil? || check_guard(options[:if])) && (options[:unless].nil? || !check_guard(options[:unless]))
284   - end
285   -
286   - def check_guard guard #:nodoc:
287   - if guard.respond_to? :call
288   - guard.call(instance)
289   - elsif ! guard.blank?
290   - instance.send(guard.to_s)
291   - end
292   - end
293   -
294   - def validate_size options #:nodoc:
295   - if file? && !options[:range].include?(size.to_i)
296   - options[:message].gsub(/:min/, options[:min].to_s).gsub(/:max/, options[:max].to_s)
297   - end
298   - end
299   -
300   - def validate_presence options #:nodoc:
301   - options[:message] unless file?
302   - end
303   -
304   - def validate_content_type options #:nodoc:
305   - valid_types = [options[:content_type]].flatten
306   - unless original_filename.blank?
307   - unless valid_types.blank?
308   - content_type = instance_read(:content_type)
309   - unless valid_types.any?{|t| content_type.nil? || t === content_type }
310   - options[:message] || "is not one of the allowed file types."
311   - end
312   - end
313   - end
314   - end
315   -
316   - def normalize_style_definition #:nodoc:
317   - @styles.each do |name, args|
318   - unless args.is_a? Hash
319   - dimensions, format = [args, nil].flatten[0..1]
320   - format = nil if format.blank?
321   - @styles[name] = {
322   - :processors => @processors,
323   - :geometry => dimensions,
324   - :format => format,
325   - :whiny => @whiny,
326   - :convert_options => extra_options_for(name)
327   - }
328   - else
329   - @styles[name] = {
330   - :processors => @processors,
331   - :whiny => @whiny,
332   - :convert_options => extra_options_for(name)
333   - }.merge(@styles[name])
334   - end
335   - end
336   - end
337   -
338   - def solidify_style_definitions #:nodoc:
339   - @styles.each do |name, args|
340   - @styles[name][:geometry] = @styles[name][:geometry].call(instance) if @styles[name][:geometry].respond_to?(:call)
341   - @styles[name][:processors] = @styles[name][:processors].call(instance) if @styles[name][:processors].respond_to?(:call)
342   - end
343   - end
344   -
345   - def initialize_storage #:nodoc:
346   - @storage_module = Paperclip::Storage.const_get(@storage.to_s.capitalize)
347   - self.extend(@storage_module)
348   - end
349   -
350   - def extra_options_for(style) #:nodoc:
351   - all_options = convert_options[:all]
352   - all_options = all_options.call(instance) if all_options.respond_to?(:call)
353   - style_options = convert_options[style]
354   - style_options = style_options.call(instance) if style_options.respond_to?(:call)
355   -
356   - [ style_options, all_options ].compact.join(" ")
357   - end
358   -
359   - def post_process #:nodoc:
360   - return if @queued_for_write[:original].nil?
361   - solidify_style_definitions
362   - return if fire_events(:before)
363   - post_process_styles
364   - return if fire_events(:after)
365   - end
366   -
367   - def fire_events(which) #:nodoc:
368   - return true if callback(:"#{which}_post_process") == false
369   - return true if callback(:"#{which}_#{name}_post_process") == false
370   - end
371   -
372   - def callback which #:nodoc:
373   - instance.run_callbacks(which, @queued_for_write){|result, obj| result == false }
374   - end
375   -
376   - def post_process_styles #:nodoc:
377   - @styles.each do |name, args|
378   - begin
379   - raise RuntimeError.new("Style #{name} has no processors defined.") if args[:processors].blank?
380   - @queued_for_write[name] = args[:processors].inject(@queued_for_write[:original]) do |file, processor|
381   - Paperclip.processor(processor).make(file, args, self)
382   - end
383   - rescue PaperclipError => e
384   - log("An error was received while processing: #{e.inspect}")
385   - (@errors[:processing] ||= []) << e.message if @whiny
386   - end
387   - end
388   - end
389   -
390   - def interpolate pattern, style = default_style #:nodoc:
391   - Paperclip::Interpolations.interpolate(pattern, self, style)
392   - end
393   -
394   - def queue_existing_for_delete #:nodoc:
395   - return unless file?
396   - @queued_for_delete += [:original, *@styles.keys].uniq.map do |style|
397   - path(style) if exists?(style)
398   - end.compact
399   - instance_write(:file_name, nil)
400   - instance_write(:content_type, nil)
401   - instance_write(:file_size, nil)
402   - instance_write(:updated_at, nil)
403   - end
404   -
405   - def flush_errors #:nodoc:
406   - @errors.each do |error, message|
407   - [message].flatten.each {|m| instance.errors.add(name, m) }
408   - end
409   - end
410   -
411   - end
412   -end
413   -
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/callback_compatability.rb
... ... @@ -1,33 +0,0 @@
1   -module Paperclip
2   - # This module is intended as a compatability shim for the differences in
3   - # callbacks between Rails 2.0 and Rails 2.1.
4   - module CallbackCompatability
5   - def self.included(base)
6   - base.extend(ClassMethods)
7   - base.send(:include, InstanceMethods)
8   - end
9   -
10   - module ClassMethods
11   - # The implementation of this method is taken from the Rails 1.2.6 source,
12   - # from rails/activerecord/lib/active_record/callbacks.rb, line 192.
13   - def define_callbacks(*args)
14   - args.each do |method|
15   - self.class_eval <<-"end_eval"
16   - def self.#{method}(*callbacks, &block)
17   - callbacks << block if block_given?
18   - write_inheritable_array(#{method.to_sym.inspect}, callbacks)
19   - end
20   - end_eval
21   - end
22   - end
23   - end
24   -
25   - module InstanceMethods
26   - # The callbacks in < 2.1 don't worry about the extra options or the
27   - # block, so just run what we have available.
28   - def run_callbacks(meth, opts = nil, &blk)
29   - callback(meth)
30   - end
31   - end
32   - end
33   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/geometry.rb
... ... @@ -1,115 +0,0 @@
1   -module Paperclip
2   -
3   - # Defines the geometry of an image.
4   - class Geometry
5   - attr_accessor :height, :width, :modifier
6   -
7   - # Gives a Geometry representing the given height and width
8   - def initialize width = nil, height = nil, modifier = nil
9   - @height = height.to_f
10   - @width = width.to_f
11   - @modifier = modifier
12   - end
13   -
14   - # Uses ImageMagick to determing the dimensions of a file, passed in as either a
15   - # File or path.
16   - def self.from_file file
17   - file = file.path if file.respond_to? "path"
18   - geometry = begin
19   - Paperclip.run("identify", %Q[-format "%wx%h" "#{file}"[0]])
20   - rescue PaperclipCommandLineError
21   - ""
22   - end
23   - parse(geometry) ||
24   - raise(NotIdentifiedByImageMagickError.new("#{file} is not recognized by the 'identify' command."))
25   - end
26   -
27   - # Parses a "WxH" formatted string, where W is the width and H is the height.
28   - def self.parse string
29   - if match = (string && string.match(/\b(\d*)x?(\d*)\b([\>\<\#\@\%^!])?/i))
30   - Geometry.new(*match[1,3])
31   - end
32   - end
33   -
34   - # True if the dimensions represent a square
35   - def square?
36   - height == width
37   - end
38   -
39   - # True if the dimensions represent a horizontal rectangle
40   - def horizontal?
41   - height < width
42   - end
43   -
44   - # True if the dimensions represent a vertical rectangle
45   - def vertical?
46   - height > width
47   - end
48   -
49   - # The aspect ratio of the dimensions.
50   - def aspect
51   - width / height
52   - end
53   -
54   - # Returns the larger of the two dimensions
55   - def larger
56   - [height, width].max
57   - end
58   -
59   - # Returns the smaller of the two dimensions
60   - def smaller
61   - [height, width].min
62   - end
63   -
64   - # Returns the width and height in a format suitable to be passed to Geometry.parse
65   - def to_s
66   - s = ""
67   - s << width.to_i.to_s if width > 0
68   - s << "x#{height.to_i}" if height > 0
69   - s << modifier.to_s
70   - s
71   - end
72   -
73   - # Same as to_s
74   - def inspect
75   - to_s
76   - end
77   -
78   - # Returns the scaling and cropping geometries (in string-based ImageMagick format)
79   - # neccessary to transform this Geometry into the Geometry given. If crop is true,
80   - # then it is assumed the destination Geometry will be the exact final resolution.
81   - # In this case, the source Geometry is scaled so that an image containing the
82   - # destination Geometry would be completely filled by the source image, and any
83   - # overhanging image would be cropped. Useful for square thumbnail images. The cropping
84   - # is weighted at the center of the Geometry.
85   - def transformation_to dst, crop = false
86   - if crop
87   - ratio = Geometry.new( dst.width / self.width, dst.height / self.height )
88   - scale_geometry, scale = scaling(dst, ratio)
89   - crop_geometry = cropping(dst, ratio, scale)
90   - else
91   - scale_geometry = dst.to_s
92   - end
93   -
94   - [ scale_geometry, crop_geometry ]
95   - end
96   -
97   - private
98   -
99   - def scaling dst, ratio
100   - if ratio.horizontal? || ratio.square?
101   - [ "%dx" % dst.width, ratio.width ]
102   - else
103   - [ "x%d" % dst.height, ratio.height ]
104   - end
105   - end
106   -
107   - def cropping dst, ratio, scale
108   - if ratio.horizontal? || ratio.square?
109   - "%dx%d+%d+%d" % [ dst.width, dst.height, 0, (self.height * scale - dst.height) / 2 ]
110   - else
111   - "%dx%d+%d+%d" % [ dst.width, dst.height, (self.width * scale - dst.width) / 2, 0 ]
112   - end
113   - end
114   - end
115   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/interpolations.rb
... ... @@ -1,105 +0,0 @@
1   -module Paperclip
2   - # This module contains all the methods that are available for interpolation
3   - # in paths and urls. To add your own (or override an existing one), you
4   - # can either open this module and define it, or call the
5   - # Paperclip.interpolates method.
6   - module Interpolations
7   - extend self
8   -
9   - # Hash assignment of interpolations. Included only for compatability,
10   - # and is not intended for normal use.
11   - def self.[]= name, block
12   - define_method(name, &block)
13   - end
14   -
15   - # Hash access of interpolations. Included only for compatability,
16   - # and is not intended for normal use.
17   - def self.[] name
18   - method(name)
19   - end
20   -
21   - # Returns a sorted list of all interpolations.
22   - def self.all
23   - self.instance_methods(false).sort
24   - end
25   -
26   - # Perform the actual interpolation. Takes the pattern to interpolate
27   - # and the arguments to pass, which are the attachment and style name.
28   - def self.interpolate pattern, *args
29   - all.reverse.inject( pattern.dup ) do |result, tag|
30   - result.gsub(/:#{tag}/) do |match|
31   - send( tag, *args )
32   - end
33   - end
34   - end
35   -
36   - # Returns the filename, the same way as ":basename.:extension" would.
37   - def filename attachment, style
38   - "#{basename(attachment, style)}.#{extension(attachment, style)}"
39   - end
40   -
41   - # Returns the interpolated URL. Will raise an error if the url itself
42   - # contains ":url" to prevent infinite recursion. This interpolation
43   - # is used in the default :path to ease default specifications.
44   - def url attachment, style
45   - raise InfiniteInterpolationError if attachment.options[:url].include?(":url")
46   - attachment.url(style, false)
47   - end
48   -
49   - # Returns the timestamp as defined by the <attachment>_updated_at field
50   - def timestamp attachment, style
51   - attachment.instance_read(:updated_at).to_s
52   - end
53   -
54   - # Returns the RAILS_ROOT constant.
55   - def rails_root attachment, style
56   - RAILS_ROOT
57   - end
58   -
59   - # Returns the RAILS_ENV constant.
60   - def rails_env attachment, style
61   - RAILS_ENV
62   - end
63   -
64   - # Returns the underscored, pluralized version of the class name.
65   - # e.g. "users" for the User class.
66   - def class attachment, style
67   - attachment.instance.class.to_s.underscore.pluralize
68   - end
69   -
70   - # Returns the basename of the file. e.g. "file" for "file.jpg"
71   - def basename attachment, style
72   - attachment.original_filename.gsub(/#{File.extname(attachment.original_filename)}$/, "")
73   - end
74   -
75   - # Returns the extension of the file. e.g. "jpg" for "file.jpg"
76   - # If the style has a format defined, it will return the format instead
77   - # of the actual extension.
78   - def extension attachment, style
79   - ((style = attachment.styles[style]) && style[:format]) ||
80   - File.extname(attachment.original_filename).gsub(/^\.+/, "")
81   - end
82   -
83   - # Returns the id of the instance.
84   - def id attachment, style
85   - attachment.instance.id
86   - end
87   -
88   - # Returns the id of the instance in a split path form. e.g. returns
89   - # 000/001/234 for an id of 1234.
90   - def id_partition attachment, style
91   - ("%09d" % attachment.instance.id).scan(/\d{3}/).join("/")
92   - end
93   -
94   - # Returns the pluralized form of the attachment name. e.g.
95   - # "avatars" for an attachment of :avatar
96   - def attachment attachment, style
97   - attachment.name.to_s.downcase.pluralize
98   - end
99   -
100   - # Returns the style, or the default style if nil is supplied.
101   - def style attachment, style
102   - style || attachment.default_style
103   - end
104   - end
105   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/iostream.rb
... ... @@ -1,58 +0,0 @@
1   -# Provides method that can be included on File-type objects (IO, StringIO, Tempfile, etc) to allow stream copying
2   -# and Tempfile conversion.
3   -module IOStream
4   -
5   - # Returns a Tempfile containing the contents of the readable object.
6   - def to_tempfile
7   - tempfile = Tempfile.new("stream")
8   - tempfile.binmode
9   - self.stream_to(tempfile)
10   - end
11   -
12   - # Copies one read-able object from one place to another in blocks, obviating the need to load
13   - # the whole thing into memory. Defaults to 8k blocks. If this module is included in both
14   - # StringIO and Tempfile, then either can have its data copied anywhere else without typing
15   - # worries or memory overhead worries. Returns a File if a String is passed in as the destination
16   - # and returns the IO or Tempfile as passed in if one is sent as the destination.
17   - def stream_to path_or_file, in_blocks_of = 8192
18   - dstio = case path_or_file
19   - when String then File.new(path_or_file, "wb+")
20   - when IO then path_or_file
21   - when Tempfile then path_or_file
22   - end
23   - buffer = ""
24   - self.rewind
25   - while self.read(in_blocks_of, buffer) do
26   - dstio.write(buffer)
27   - end
28   - dstio.rewind
29   - dstio
30   - end
31   -end
32   -
33   -class IO #:nodoc:
34   - include IOStream
35   -end
36   -
37   -%w( Tempfile StringIO ).each do |klass|
38   - if Object.const_defined? klass
39   - Object.const_get(klass).class_eval do
40   - include IOStream
41   - end
42   - end
43   -end
44   -
45   -# Corrects a bug in Windows when asking for Tempfile size.
46   -if defined? Tempfile
47   - class Tempfile
48   - def size
49   - if @tmpfile
50   - @tmpfile.fsync
51   - @tmpfile.flush
52   - @tmpfile.stat.size
53   - else
54   - 0
55   - end
56   - end
57   - end
58   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/matchers.rb
... ... @@ -1,4 +0,0 @@
1   -require 'paperclip/matchers/have_attached_file_matcher'
2   -require 'paperclip/matchers/validate_attachment_presence_matcher'
3   -require 'paperclip/matchers/validate_attachment_content_type_matcher'
4   -require 'paperclip/matchers/validate_attachment_size_matcher'
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/matchers/have_attached_file_matcher.rb
... ... @@ -1,49 +0,0 @@
1   -module Paperclip
2   - module Shoulda
3   - module Matchers
4   - def have_attached_file name
5   - HaveAttachedFileMatcher.new(name)
6   - end
7   -
8   - class HaveAttachedFileMatcher
9   - def initialize attachment_name
10   - @attachment_name = attachment_name
11   - end
12   -
13   - def matches? subject
14   - @subject = subject
15   - responds? && has_column? && included?
16   - end
17   -
18   - def failure_message
19   - "Should have an attachment named #{@attachment_name}"
20   - end
21   -
22   - def negative_failure_message
23   - "Should not have an attachment named #{@attachment_name}"
24   - end
25   -
26   - def description
27   - "have an attachment named #{@attachment_name}"
28   - end
29   -
30   - protected
31   -
32   - def responds?
33   - methods = @subject.instance_methods
34   - methods.include?("#{@attachment_name}") &&
35   - methods.include?("#{@attachment_name}=") &&
36   - methods.include?("#{@attachment_name}?")
37   - end
38   -
39   - def has_column?
40   - @subject.column_names.include?("#{@attachment_name}_file_name")
41   - end
42   -
43   - def included?
44   - @subject.ancestors.include?(Paperclip::InstanceMethods)
45   - end
46   - end
47   - end
48   - end
49   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb
... ... @@ -1,66 +0,0 @@
1   -module Paperclip
2   - module Shoulda
3   - module Matchers
4   - def validate_attachment_content_type name
5   - ValidateAttachmentContentTypeMatcher.new(name)
6   - end
7   -
8   - class ValidateAttachmentContentTypeMatcher
9   - def initialize attachment_name
10   - @attachment_name = attachment_name
11   - end
12   -
13   - def allowing *types
14   - @allowed_types = types.flatten
15   - self
16   - end
17   -
18   - def rejecting *types
19   - @rejected_types = types.flatten
20   - self
21   - end
22   -
23   - def matches? subject
24   - @subject = subject
25   - @allowed_types && @rejected_types &&
26   - allowed_types_allowed? && rejected_types_rejected?
27   - end
28   -
29   - def failure_message
30   - "Content types #{@allowed_types.join(", ")} should be accepted" +
31   - " and #{@rejected_types.join(", ")} rejected by #{@attachment_name}"
32   - end
33   -
34   - def negative_failure_message
35   - "Content types #{@allowed_types.join(", ")} should be rejected" +
36   - " and #{@rejected_types.join(", ")} accepted by #{@attachment_name}"
37   - end
38   -
39   - def description
40   - "validate the content types allowed on attachment #{@attachment_name}"
41   - end
42   -
43   - protected
44   -
45   - def allow_types?(types)
46   - types.all? do |type|
47   - file = StringIO.new(".")
48   - file.content_type = type
49   - attachment = @subject.new.attachment_for(@attachment_name)
50   - attachment.assign(file)
51   - attachment.errors[:content_type].nil?
52   - end
53   - end
54   -
55   - def allowed_types_allowed?
56   - allow_types?(@allowed_types)
57   - end
58   -
59   - def rejected_types_rejected?
60   - not allow_types?(@rejected_types)
61   - end
62   - end
63   - end
64   - end
65   -end
66   -
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/matchers/validate_attachment_presence_matcher.rb
... ... @@ -1,48 +0,0 @@
1   -module Paperclip
2   - module Shoulda
3   - module Matchers
4   - def validate_attachment_presence name
5   - ValidateAttachmentPresenceMatcher.new(name)
6   - end
7   -
8   - class ValidateAttachmentPresenceMatcher
9   - def initialize attachment_name
10   - @attachment_name = attachment_name
11   - end
12   -
13   - def matches? subject
14   - @subject = subject
15   - error_when_not_valid? && no_error_when_valid?
16   - end
17   -
18   - def failure_message
19   - "Attachment #{@attachment_name} should be required"
20   - end
21   -
22   - def negative_failure_message
23   - "Attachment #{@attachment_name} should not be required"
24   - end
25   -
26   - def description
27   - "require presence of attachment #{@attachment_name}"
28   - end
29   -
30   - protected
31   -
32   - def error_when_not_valid?
33   - @attachment = @subject.new.send(@attachment_name)
34   - @attachment.assign(nil)
35   - not @attachment.errors[:presence].nil?
36   - end
37   -
38   - def no_error_when_valid?
39   - @file = StringIO.new(".")
40   - @attachment = @subject.new.send(@attachment_name)
41   - @attachment.assign(@file)
42   - @attachment.errors[:presence].nil?
43   - end
44   - end
45   - end
46   - end
47   -end
48   -
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/matchers/validate_attachment_size_matcher.rb
... ... @@ -1,83 +0,0 @@
1   -module Paperclip
2   - module Shoulda
3   - module Matchers
4   - def validate_attachment_size name
5   - ValidateAttachmentSizeMatcher.new(name)
6   - end
7   -
8   - class ValidateAttachmentSizeMatcher
9   - def initialize attachment_name
10   - @attachment_name = attachment_name
11   - @low, @high = 0, (1.0/0)
12   - end
13   -
14   - def less_than size
15   - @high = size
16   - self
17   - end
18   -
19   - def greater_than size
20   - @low = size
21   - self
22   - end
23   -
24   - def in range
25   - @low, @high = range.first, range.last
26   - self
27   - end
28   -
29   - def matches? subject
30   - @subject = subject
31   - lower_than_low? && higher_than_low? && lower_than_high? && higher_than_high?
32   - end
33   -
34   - def failure_message
35   - "Attachment #{@attachment_name} must be between #{@low} and #{@high} bytes"
36   - end
37   -
38   - def negative_failure_message
39   - "Attachment #{@attachment_name} cannot be between #{@low} and #{@high} bytes"
40   - end
41   -
42   - def description
43   - "validate the size of attachment #{@attachment_name}"
44   - end
45   -
46   - protected
47   -
48   - def override_method object, method, &replacement
49   - (class << object; self; end).class_eval do
50   - define_method(method, &replacement)
51   - end
52   - end
53   -
54   - def passes_validation_with_size(new_size)
55   - file = StringIO.new(".")
56   - override_method(file, :size){ new_size }
57   - attachment = @subject.new.attachment_for(@attachment_name)
58   - attachment.assign(file)
59   - attachment.errors[:size].nil?
60   - end
61   -
62   - def lower_than_low?
63   - not passes_validation_with_size(@low - 1)
64   - end
65   -
66   - def higher_than_low?
67   - passes_validation_with_size(@low + 1)
68   - end
69   -
70   - def lower_than_high?
71   - return true if @high == (1.0/0)
72   - passes_validation_with_size(@high - 1)
73   - end
74   -
75   - def higher_than_high?
76   - return true if @high == (1.0/0)
77   - not passes_validation_with_size(@high + 1)
78   - end
79   - end
80   - end
81   - end
82   -end
83   -
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/processor.rb
... ... @@ -1,49 +0,0 @@
1   -module Paperclip
2   - # Paperclip processors allow you to modify attached files when they are
3   - # attached in any way you are able. Paperclip itself uses command-line
4   - # programs for its included Thumbnail processor, but custom processors
5   - # are not required to follow suit.
6   - #
7   - # Processors are required to be defined inside the Paperclip module and
8   - # are also required to be a subclass of Paperclip::Processor. There is
9   - # only one method you *must* implement to properly be a subclass:
10   - # #make, but #initialize may also be of use. Both methods accept 3
11   - # arguments: the file that will be operated on (which is an instance of
12   - # File), a hash of options that were defined in has_attached_file's
13   - # style hash, and the Paperclip::Attachment itself.
14   - #
15   - # All #make needs to return is an instance of File (Tempfile is
16   - # acceptable) which contains the results of the processing.
17   - #
18   - # See Paperclip.run for more information about using command-line
19   - # utilities from within Processors.
20   - class Processor
21   - attr_accessor :file, :options, :attachment
22   -
23   - def initialize file, options = {}, attachment = nil
24   - @file = file
25   - @options = options
26   - @attachment = attachment
27   - end
28   -
29   - def make
30   - end
31   -
32   - def self.make file, options = {}, attachment = nil
33   - new(file, options, attachment).make
34   - end
35   - end
36   -
37   - # Due to how ImageMagick handles its image format conversion and how Tempfile
38   - # handles its naming scheme, it is necessary to override how Tempfile makes
39   - # its names so as to allow for file extensions. Idea taken from the comments
40   - # on this blog post:
41   - # http://marsorange.com/archives/of-mogrify-ruby-tempfile-dynamic-class-definitions
42   - class Tempfile < ::Tempfile
43   - # Replaces Tempfile's +make_tmpname+ with one that honors file extensions.
44   - def make_tmpname(basename, n)
45   - extension = File.extname(basename)
46   - sprintf("%s,%d,%d%s", File.basename(basename, extension), $$, n, extension)
47   - end
48   - end
49   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/storage.rb
... ... @@ -1,236 +0,0 @@
1   -module Paperclip
2   - module Storage
3   -
4   - # The default place to store attachments is in the filesystem. Files on the local
5   - # filesystem can be very easily served by Apache without requiring a hit to your app.
6   - # They also can be processed more easily after they've been saved, as they're just
7   - # normal files. There is one Filesystem-specific option for has_attached_file.
8   - # * +path+: The location of the repository of attachments on disk. This can (and, in
9   - # almost all cases, should) be coordinated with the value of the +url+ option to
10   - # allow files to be saved into a place where Apache can serve them without
11   - # hitting your app. Defaults to
12   - # ":rails_root/public/:attachment/:id/:style/:basename.:extension"
13   - # By default this places the files in the app's public directory which can be served
14   - # directly. If you are using capistrano for deployment, a good idea would be to
15   - # make a symlink to the capistrano-created system directory from inside your app's
16   - # public directory.
17   - # See Paperclip::Attachment#interpolate for more information on variable interpolaton.
18   - # :path => "/var/app/attachments/:class/:id/:style/:basename.:extension"
19   - module Filesystem
20   - def self.extended base
21   - end
22   -
23   - def exists?(style = default_style)
24   - if original_filename
25   - File.exist?(path(style))
26   - else
27   - false
28   - end
29   - end
30   -
31   - # Returns representation of the data of the file assigned to the given
32   - # style, in the format most representative of the current storage.
33   - def to_file style = default_style
34   - @queued_for_write[style] || (File.new(path(style), 'rb') if exists?(style))
35   - end
36   - alias_method :to_io, :to_file
37   -
38   - def flush_writes #:nodoc:
39   - @queued_for_write.each do |style, file|
40   - file.close
41   - FileUtils.mkdir_p(File.dirname(path(style)))
42   - log("saving #{path(style)}")
43   - FileUtils.mv(file.path, path(style))
44   - FileUtils.chmod(0644, path(style))
45   - end
46   - @queued_for_write = {}
47   - end
48   -
49   - def flush_deletes #:nodoc:
50   - @queued_for_delete.each do |path|
51   - begin
52   - log("deleting #{path}")
53   - FileUtils.rm(path) if File.exist?(path)
54   - rescue Errno::ENOENT => e
55   - # ignore file-not-found, let everything else pass
56   - end
57   - begin
58   - while(true)
59   - path = File.dirname(path)
60   - FileUtils.rmdir(path)
61   - end
62   - rescue Errno::EEXIST, Errno::ENOTEMPTY, Errno::ENOENT, Errno::EINVAL, Errno::ENOTDIR
63   - # Stop trying to remove parent directories
64   - rescue SystemCallError => e
65   - log("There was an unexpected error while deleting directories: #{e.class}")
66   - # Ignore it
67   - end
68   - end
69   - @queued_for_delete = []
70   - end
71   - end
72   -
73   - # Amazon's S3 file hosting service is a scalable, easy place to store files for
74   - # distribution. You can find out more about it at http://aws.amazon.com/s3
75   - # There are a few S3-specific options for has_attached_file:
76   - # * +s3_credentials+: Takes a path, a File, or a Hash. The path (or File) must point
77   - # to a YAML file containing the +access_key_id+ and +secret_access_key+ that Amazon
78   - # gives you. You can 'environment-space' this just like you do to your
79   - # database.yml file, so different environments can use different accounts:
80   - # development:
81   - # access_key_id: 123...
82   - # secret_access_key: 123...
83   - # test:
84   - # access_key_id: abc...
85   - # secret_access_key: abc...
86   - # production:
87   - # access_key_id: 456...
88   - # secret_access_key: 456...
89   - # This is not required, however, and the file may simply look like this:
90   - # access_key_id: 456...
91   - # secret_access_key: 456...
92   - # In which case, those access keys will be used in all environments. You can also
93   - # put your bucket name in this file, instead of adding it to the code directly.
94   - # This is useful when you want the same account but a different bucket for
95   - # development versus production.
96   - # * +s3_permissions+: This is a String that should be one of the "canned" access
97   - # policies that S3 provides (more information can be found here:
98   - # http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html#RESTCannedAccessPolicies)
99   - # The default for Paperclip is "public-read".
100   - # * +s3_protocol+: The protocol for the URLs generated to your S3 assets. Can be either
101   - # 'http' or 'https'. Defaults to 'http' when your :s3_permissions are 'public-read' (the
102   - # default), and 'https' when your :s3_permissions are anything else.
103   - # * +s3_headers+: A hash of headers such as {'Expires' => 1.year.from_now.httpdate}
104   - # * +bucket+: This is the name of the S3 bucket that will store your files. Remember
105   - # that the bucket must be unique across all of Amazon S3. If the bucket does not exist
106   - # Paperclip will attempt to create it. The bucket name will not be interpolated.
107   - # You can define the bucket as a Proc if you want to determine it's name at runtime.
108   - # Paperclip will call that Proc with attachment as the only argument.
109   - # * +s3_host_alias+: The fully-qualified domain name (FQDN) that is the alias to the
110   - # S3 domain of your bucket. Used with the :s3_alias_url url interpolation. See the
111   - # link in the +url+ entry for more information about S3 domains and buckets.
112   - # * +url+: There are three options for the S3 url. You can choose to have the bucket's name
113   - # placed domain-style (bucket.s3.amazonaws.com) or path-style (s3.amazonaws.com/bucket).
114   - # Lastly, you can specify a CNAME (which requires the CNAME to be specified as
115   - # :s3_alias_url. You can read more about CNAMEs and S3 at
116   - # http://docs.amazonwebservices.com/AmazonS3/latest/index.html?VirtualHosting.html
117   - # Normally, this won't matter in the slightest and you can leave the default (which is
118   - # path-style, or :s3_path_url). But in some cases paths don't work and you need to use
119   - # the domain-style (:s3_domain_url). Anything else here will be treated like path-style.
120   - # NOTE: If you use a CNAME for use with CloudFront, you can NOT specify https as your
121   - # :s3_protocol; This is *not supported* by S3/CloudFront. Finally, when using the host
122   - # alias, the :bucket parameter is ignored, as the hostname is used as the bucket name
123   - # by S3.
124   - # * +path+: This is the key under the bucket in which the file will be stored. The
125   - # URL will be constructed from the bucket and the path. This is what you will want
126   - # to interpolate. Keys should be unique, like filenames, and despite the fact that
127   - # S3 (strictly speaking) does not support directories, you can still use a / to
128   - # separate parts of your file name.
129   - module S3
130   - def self.extended base
131   - require 'right_aws'
132   - base.instance_eval do
133   - @s3_credentials = parse_credentials(@options[:s3_credentials])
134   - @bucket = @options[:bucket] || @s3_credentials[:bucket]
135   - @bucket = @bucket.call(self) if @bucket.is_a?(Proc)
136   - @s3_options = @options[:s3_options] || {}
137   - @s3_permissions = @options[:s3_permissions] || 'public-read'
138   - @s3_protocol = @options[:s3_protocol] || (@s3_permissions == 'public-read' ? 'http' : 'https')
139   - @s3_headers = @options[:s3_headers] || {}
140   - @s3_host_alias = @options[:s3_host_alias]
141   - @url = ":s3_path_url" unless @url.to_s.match(/^:s3.*url$/)
142   - end
143   - Paperclip.interpolates(:s3_alias_url) do |attachment, style|
144   - "#{attachment.s3_protocol}://#{attachment.s3_host_alias}/#{attachment.path(style).gsub(%r{^/}, "")}"
145   - end
146   - Paperclip.interpolates(:s3_path_url) do |attachment, style|
147   - "#{attachment.s3_protocol}://s3.amazonaws.com/#{attachment.bucket_name}/#{attachment.path(style).gsub(%r{^/}, "")}"
148   - end
149   - Paperclip.interpolates(:s3_domain_url) do |attachment, style|
150   - "#{attachment.s3_protocol}://#{attachment.bucket_name}.s3.amazonaws.com/#{attachment.path(style).gsub(%r{^/}, "")}"
151   - end
152   - end
153   -
154   - def s3
155   - @s3 ||= RightAws::S3.new(@s3_credentials[:access_key_id],
156   - @s3_credentials[:secret_access_key],
157   - @s3_options)
158   - end
159   -
160   - def s3_bucket
161   - @s3_bucket ||= s3.bucket(@bucket, true, @s3_permissions)
162   - end
163   -
164   - def bucket_name
165   - @bucket
166   - end
167   -
168   - def s3_host_alias
169   - @s3_host_alias
170   - end
171   -
172   - def parse_credentials creds
173   - creds = find_credentials(creds).stringify_keys
174   - (creds[RAILS_ENV] || creds).symbolize_keys
175   - end
176   -
177   - def exists?(style = default_style)
178   - s3_bucket.key(path(style)) ? true : false
179   - end
180   -
181   - def s3_protocol
182   - @s3_protocol
183   - end
184   -
185   - # Returns representation of the data of the file assigned to the given
186   - # style, in the format most representative of the current storage.
187   - def to_file style = default_style
188   - @queued_for_write[style] || s3_bucket.key(path(style))
189   - end
190   - alias_method :to_io, :to_file
191   -
192   - def flush_writes #:nodoc:
193   - @queued_for_write.each do |style, file|
194   - begin
195   - log("saving #{path(style)}")
196   - key = s3_bucket.key(path(style))
197   - key.data = file
198   - key.put(nil, @s3_permissions, {'Content-type' => instance_read(:content_type)}.merge(@s3_headers))
199   - rescue RightAws::AwsError => e
200   - raise
201   - end
202   - end
203   - @queued_for_write = {}
204   - end
205   -
206   - def flush_deletes #:nodoc:
207   - @queued_for_delete.each do |path|
208   - begin
209   - log("deleting #{path}")
210   - if file = s3_bucket.key(path)
211   - file.delete
212   - end
213   - rescue RightAws::AwsError
214   - # Ignore this.
215   - end
216   - end
217   - @queued_for_delete = []
218   - end
219   -
220   - def find_credentials creds
221   - case creds
222   - when File
223   - YAML.load_file(creds.path)
224   - when String
225   - YAML.load_file(creds)
226   - when Hash
227   - creds
228   - else
229   - raise ArgumentError, "Credentials are not a path, file, or hash."
230   - end
231   - end
232   - private :find_credentials
233   -
234   - end
235   - end
236   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/thumbnail.rb
... ... @@ -1,70 +0,0 @@
1   -module Paperclip
2   - # Handles thumbnailing images that are uploaded.
3   - class Thumbnail < Processor
4   -
5   - attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options
6   -
7   - # Creates a Thumbnail object set to work on the +file+ given. It
8   - # will attempt to transform the image into one defined by +target_geometry+
9   - # which is a "WxH"-style string. +format+ will be inferred from the +file+
10   - # unless specified. Thumbnail creation will raise no errors unless
11   - # +whiny+ is true (which it is, by default. If +convert_options+ is
12   - # set, the options will be appended to the convert command upon image conversion
13   - def initialize file, options = {}, attachment = nil
14   - super
15   - geometry = options[:geometry]
16   - @file = file
17   - @crop = geometry[-1,1] == '#'
18   - @target_geometry = Geometry.parse geometry
19   - @current_geometry = Geometry.from_file @file
20   - @convert_options = options[:convert_options]
21   - @whiny = options[:whiny].nil? ? true : options[:whiny]
22   - @format = options[:format]
23   -
24   - @current_format = File.extname(@file.path)
25   - @basename = File.basename(@file.path, @current_format)
26   - end
27   -
28   - # Returns true if the +target_geometry+ is meant to crop.
29   - def crop?
30   - @crop
31   - end
32   -
33   - # Returns true if the image is meant to make use of additional convert options.
34   - def convert_options?
35   - not @convert_options.blank?
36   - end
37   -
38   - # Performs the conversion of the +file+ into a thumbnail. Returns the Tempfile
39   - # that contains the new image.
40   - def make
41   - src = @file
42   - dst = Tempfile.new([@basename, @format].compact.join("."))
43   - dst.binmode
44   -
45   - command = <<-end_command
46   - "#{ File.expand_path(src.path) }[0]"
47   - #{ transformation_command }
48   - "#{ File.expand_path(dst.path) }"
49   - end_command
50   -
51   - begin
52   - success = Paperclip.run("convert", command.gsub(/\s+/, " "))
53   - rescue PaperclipCommandLineError
54   - raise PaperclipError, "There was an error processing the thumbnail for #{@basename}" if @whiny
55   - end
56   -
57   - dst
58   - end
59   -
60   - # Returns the command ImageMagick's +convert+ needs to transform the image
61   - # into the thumbnail.
62   - def transformation_command
63   - scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
64   - trans = "-resize \"#{scale}\""
65   - trans << " -crop \"#{crop}\" +repage" if crop
66   - trans << " #{convert_options}" if convert_options?
67   - trans
68   - end
69   - end
70   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/lib/paperclip/upfile.rb
... ... @@ -1,48 +0,0 @@
1   -module Paperclip
2   - # The Upfile module is a convenience module for adding uploaded-file-type methods
3   - # to the +File+ class. Useful for testing.
4   - # user.avatar = File.new("test/test_avatar.jpg")
5   - module Upfile
6   -
7   - # Infer the MIME-type of the file from the extension.
8   - def content_type
9   - type = (self.path.match(/\.(\w+)$/)[1] rescue "octet-stream").downcase
10   - case type
11   - when %r"jpe?g" then "image/jpeg"
12   - when %r"tiff?" then "image/tiff"
13   - when %r"png", "gif", "bmp" then "image/#{type}"
14   - when "txt" then "text/plain"
15   - when %r"html?" then "text/html"
16   - when "csv", "xml", "css", "js" then "text/#{type}"
17   - else "application/x-#{type}"
18   - end
19   - end
20   -
21   - # Returns the file's normal name.
22   - def original_filename
23   - File.basename(self.path)
24   - end
25   -
26   - # Returns the size of the file.
27   - def size
28   - File.size(self)
29   - end
30   - end
31   -end
32   -
33   -if defined? StringIO
34   - class StringIO
35   - attr_accessor :original_filename, :content_type
36   - def original_filename
37   - @original_filename ||= "stringio.txt"
38   - end
39   - def content_type
40   - @content_type ||= "text/plain"
41   - end
42   - end
43   -end
44   -
45   -class File #:nodoc:
46   - include Paperclip::Upfile
47   -end
48   -
vendor/gems/thoughtbot-paperclip-2.2.9.2/shoulda_macros/paperclip.rb
... ... @@ -1,68 +0,0 @@
1   -require 'paperclip/matchers'
2   -
3   -module Paperclip
4   - # =Paperclip Shoulda Macros
5   - #
6   - # These macros are intended for use with shoulda, and will be included into
7   - # your tests automatically. All of the macros use the standard shoulda
8   - # assumption that the name of the test is based on the name of the model
9   - # you're testing (that is, UserTest is the test for the User model), and
10   - # will load that class for testing purposes.
11   - module Shoulda
12   - include Matchers
13   - # This will test whether you have defined your attachment correctly by
14   - # checking for all the required fields exist after the definition of the
15   - # attachment.
16   - def should_have_attached_file name
17   - klass = self.name.gsub(/Test$/, '').constantize
18   - matcher = have_attached_file name
19   - should matcher.description do
20   - assert_accepts(matcher, klass)
21   - end
22   - end
23   -
24   - # Tests for validations on the presence of the attachment.
25   - def should_validate_attachment_presence name
26   - klass = self.name.gsub(/Test$/, '').constantize
27   - matcher = validate_attachment_presence name
28   - should matcher.description do
29   - assert_accepts(matcher, klass)
30   - end
31   - end
32   -
33   - # Tests that you have content_type validations specified. There are two
34   - # options, :valid and :invalid. Both accept an array of strings. The
35   - # strings should be a list of content types which will pass and fail
36   - # validation, respectively.
37   - def should_validate_attachment_content_type name, options = {}
38   - klass = self.name.gsub(/Test$/, '').constantize
39   - valid = [options[:valid]].flatten
40   - invalid = [options[:invalid]].flatten
41   - matcher = validate_attachment_content_type(name).allowing(valid).rejecting(invalid)
42   - should matcher.description do
43   - assert_accepts(matcher, klass)
44   - end
45   - end
46   -
47   - # Tests to ensure that you have file size validations turned on. You
48   - # can pass the same options to this that you can to
49   - # validate_attachment_file_size - :less_than, :greater_than, and :in.
50   - # :less_than checks that a file is less than a certain size, :greater_than
51   - # checks that a file is more than a certain size, and :in takes a Range or
52   - # Array which specifies the lower and upper limits of the file size.
53   - def should_validate_attachment_size name, options = {}
54   - klass = self.name.gsub(/Test$/, '').constantize
55   - min = options[:greater_than] || (options[:in] && options[:in].first) || 0
56   - max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
57   - range = (min..max)
58   - matcher = validate_attachment_size(name).in(range)
59   - should matcher.description do
60   - assert_accepts(matcher, klass)
61   - end
62   - end
63   - end
64   -end
65   -
66   -class Test::Unit::TestCase #:nodoc:
67   - extend Paperclip::Shoulda
68   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/tasks/paperclip_tasks.rake
... ... @@ -1,79 +0,0 @@
1   -def obtain_class
2   - class_name = ENV['CLASS'] || ENV['class']
3   - raise "Must specify CLASS" unless class_name
4   - @klass = Object.const_get(class_name)
5   -end
6   -
7   -def obtain_attachments
8   - name = ENV['ATTACHMENT'] || ENV['attachment']
9   - raise "Class #{@klass.name} has no attachments specified" unless @klass.respond_to?(:attachment_definitions)
10   - if !name.blank? && @klass.attachment_definitions.keys.include?(name)
11   - [ name ]
12   - else
13   - @klass.attachment_definitions.keys
14   - end
15   -end
16   -
17   -def for_all_attachments
18   - klass = obtain_class
19   - names = obtain_attachments
20   - ids = klass.connection.select_values(klass.send(:construct_finder_sql, :select => 'id'))
21   -
22   - ids.each do |id|
23   - instance = klass.find(id)
24   - names.each do |name|
25   - result = if instance.send("#{ name }?")
26   - yield(instance, name)
27   - else
28   - true
29   - end
30   - print result ? "." : "x"; $stdout.flush
31   - end
32   - end
33   - puts " Done."
34   -end
35   -
36   -namespace :paperclip do
37   - desc "Refreshes both metadata and thumbnails."
38   - task :refresh => ["paperclip:refresh:metadata", "paperclip:refresh:thumbnails"]
39   -
40   - namespace :refresh do
41   - desc "Regenerates thumbnails for a given CLASS (and optional ATTACHMENT)."
42   - task :thumbnails => :environment do
43   - errors = []
44   - for_all_attachments do |instance, name|
45   - result = instance.send(name).reprocess!
46   - errors << [instance.id, instance.errors] unless instance.errors.blank?
47   - result
48   - end
49   - errors.each{|e| puts "#{e.first}: #{e.last.full_messages.inspect}" }
50   - end
51   -
52   - desc "Regenerates content_type/size metadata for a given CLASS (and optional ATTACHMENT)."
53   - task :metadata => :environment do
54   - for_all_attachments do |instance, name|
55   - if file = instance.send(name).to_file
56   - instance.send("#{name}_file_name=", instance.send("#{name}_file_name").strip)
57   - instance.send("#{name}_content_type=", file.content_type.strip)
58   - instance.send("#{name}_file_size=", file.size) if instance.respond_to?("#{name}_file_size")
59   - instance.save(false)
60   - else
61   - true
62   - end
63   - end
64   - end
65   - end
66   -
67   - desc "Cleans out invalid attachments. Useful after you've added new validations."
68   - task :clean => :environment do
69   - for_all_attachments do |instance, name|
70   - instance.send(name).send(:validate)
71   - if instance.send(name).valid?
72   - true
73   - else
74   - instance.send("#{name}=", nil)
75   - instance.save
76   - end
77   - end
78   - end
79   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/attachment_test.rb
... ... @@ -1,768 +0,0 @@
1   -require 'test/helper'
2   -
3   -class Dummy
4   - # This is a dummy class
5   -end
6   -
7   -class AttachmentTest < Test::Unit::TestCase
8   - should "return the path based on the url by default" do
9   - @attachment = attachment :url => "/:class/:id/:basename"
10   - @model = @attachment.instance
11   - @model.id = 1234
12   - @model.avatar_file_name = "fake.jpg"
13   - assert_equal "#{RAILS_ROOT}/public/fake_models/1234/fake", @attachment.path
14   - end
15   -
16   - context "Attachment default_options" do
17   - setup do
18   - rebuild_model
19   - @old_default_options = Paperclip::Attachment.default_options.dup
20   - @new_default_options = @old_default_options.merge({
21   - :path => "argle/bargle",
22   - :url => "fooferon",
23   - :default_url => "not here.png"
24   - })
25   - end
26   -
27   - teardown do
28   - Paperclip::Attachment.default_options.merge! @old_default_options
29   - end
30   -
31   - should "be overrideable" do
32   - Paperclip::Attachment.default_options.merge!(@new_default_options)
33   - @new_default_options.keys.each do |key|
34   - assert_equal @new_default_options[key],
35   - Paperclip::Attachment.default_options[key]
36   - end
37   - end
38   -
39   - context "without an Attachment" do
40   - setup do
41   - @dummy = Dummy.new
42   - end
43   -
44   - should "return false when asked exists?" do
45   - assert !@dummy.avatar.exists?
46   - end
47   - end
48   -
49   - context "on an Attachment" do
50   - setup do
51   - @dummy = Dummy.new
52   - @attachment = @dummy.avatar
53   - end
54   -
55   - Paperclip::Attachment.default_options.keys.each do |key|
56   - should "be the default_options for #{key}" do
57   - assert_equal @old_default_options[key],
58   - @attachment.instance_variable_get("@#{key}"),
59   - key
60   - end
61   - end
62   -
63   - context "when redefined" do
64   - setup do
65   - Paperclip::Attachment.default_options.merge!(@new_default_options)
66   - @dummy = Dummy.new
67   - @attachment = @dummy.avatar
68   - end
69   -
70   - Paperclip::Attachment.default_options.keys.each do |key|
71   - should "be the new default_options for #{key}" do
72   - assert_equal @new_default_options[key],
73   - @attachment.instance_variable_get("@#{key}"),
74   - key
75   - end
76   - end
77   - end
78   - end
79   - end
80   -
81   - context "An attachment with similarly named interpolations" do
82   - setup do
83   - rebuild_model :path => ":id.omg/:id-bbq/:idwhat/:id_partition.wtf"
84   - @dummy = Dummy.new
85   - @dummy.stubs(:id).returns(1024)
86   - @file = File.new(File.join(File.dirname(__FILE__),
87   - "fixtures",
88   - "5k.png"), 'rb')
89   - @dummy.avatar = @file
90   - end
91   -
92   - teardown { @file.close }
93   -
94   - should "make sure that they are interpolated correctly" do
95   - assert_equal "1024.omg/1024-bbq/1024what/000/001/024.wtf", @dummy.avatar.path
96   - end
97   - end
98   -
99   - context "An attachment with a :rails_env interpolation" do
100   - setup do
101   - @rails_env = "blah"
102   - @id = 1024
103   - rebuild_model :path => ":rails_env/:id.png"
104   - @dummy = Dummy.new
105   - @dummy.stubs(:id).returns(@id)
106   - @file = StringIO.new(".")
107   - @dummy.avatar = @file
108   - end
109   -
110   - should "return the proper path" do
111   - temporary_rails_env(@rails_env) {
112   - assert_equal "#{@rails_env}/#{@id}.png", @dummy.avatar.path
113   - }
114   - end
115   - end
116   -
117   - context "An attachment with a default style and an extension interpolation" do
118   - setup do
119   - @attachment = attachment :path => ":basename.:extension",
120   - :styles => { :default => ["100x100", :png] },
121   - :default_style => :default
122   - @file = StringIO.new("...")
123   - @file.expects(:original_filename).returns("file.jpg")
124   - end
125   - should "return the right extension for the path" do
126   - @attachment.assign(@file)
127   - assert_equal "file.png", @attachment.path
128   - end
129   - end
130   -
131   - context "An attachment with :convert_options" do
132   - setup do
133   - rebuild_model :styles => {
134   - :thumb => "100x100",
135   - :large => "400x400"
136   - },
137   - :convert_options => {
138   - :all => "-do_stuff",
139   - :thumb => "-thumbnailize"
140   - }
141   - @dummy = Dummy.new
142   - @dummy.avatar
143   - end
144   -
145   - should "report the correct options when sent #extra_options_for(:thumb)" do
146   - assert_equal "-thumbnailize -do_stuff", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
147   - end
148   -
149   - should "report the correct options when sent #extra_options_for(:large)" do
150   - assert_equal "-do_stuff", @dummy.avatar.send(:extra_options_for, :large)
151   - end
152   -
153   - before_should "call extra_options_for(:thumb/:large)" do
154   - Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
155   - Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
156   - end
157   - end
158   -
159   - context "An attachment with :convert_options that is a proc" do
160   - setup do
161   - rebuild_model :styles => {
162   - :thumb => "100x100",
163   - :large => "400x400"
164   - },
165   - :convert_options => {
166   - :all => lambda{|i| i.all },
167   - :thumb => lambda{|i| i.thumb }
168   - }
169   - Dummy.class_eval do
170   - def all; "-all"; end
171   - def thumb; "-thumb"; end
172   - end
173   - @dummy = Dummy.new
174   - @dummy.avatar
175   - end
176   -
177   - should "report the correct options when sent #extra_options_for(:thumb)" do
178   - assert_equal "-thumb -all", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
179   - end
180   -
181   - should "report the correct options when sent #extra_options_for(:large)" do
182   - assert_equal "-all", @dummy.avatar.send(:extra_options_for, :large)
183   - end
184   -
185   - before_should "call extra_options_for(:thumb/:large)" do
186   - Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
187   - Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
188   - end
189   - end
190   -
191   - context "An attachment with :path that is a proc" do
192   - setup do
193   - rebuild_model :path => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
194   -
195   - @file = File.new(File.join(File.dirname(__FILE__),
196   - "fixtures",
197   - "5k.png"), 'rb')
198   - @dummyA = Dummy.new(:other => 'a')
199   - @dummyA.avatar = @file
200   - @dummyB = Dummy.new(:other => 'b')
201   - @dummyB.avatar = @file
202   - end
203   -
204   - teardown { @file.close }
205   -
206   - should "return correct path" do
207   - assert_equal "path/a.png", @dummyA.avatar.path
208   - assert_equal "path/b.png", @dummyB.avatar.path
209   - end
210   - end
211   -
212   - context "An attachment with :styles that is a proc" do
213   - setup do
214   - rebuild_model :styles => lambda{ |attachment| {:thumb => "50x50#", :large => "400x400"} }
215   -
216   - @attachment = Dummy.new.avatar
217   - end
218   -
219   - should "have the correct geometry" do
220   - assert_equal "50x50#", @attachment.styles[:thumb][:geometry]
221   - end
222   - end
223   -
224   - context "An attachment with :url that is a proc" do
225   - setup do
226   - rebuild_model :url => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
227   -
228   - @file = File.new(File.join(File.dirname(__FILE__),
229   - "fixtures",
230   - "5k.png"), 'rb')
231   - @dummyA = Dummy.new(:other => 'a')
232   - @dummyA.avatar = @file
233   - @dummyB = Dummy.new(:other => 'b')
234   - @dummyB.avatar = @file
235   - end
236   -
237   - teardown { @file.close }
238   -
239   - should "return correct url" do
240   - assert_equal "path/a.png", @dummyA.avatar.url(:original, false)
241   - assert_equal "path/b.png", @dummyB.avatar.url(:original, false)
242   - end
243   - end
244   -
245   - geometry_specs = [
246   - [ lambda{|z| "50x50#" }, :png ],
247   - lambda{|z| "50x50#" },
248   - { :geometry => lambda{|z| "50x50#" } }
249   - ]
250   - geometry_specs.each do |geometry_spec|
251   - context "An attachment geometry like #{geometry_spec}" do
252   - setup do
253   - rebuild_model :styles => { :normal => geometry_spec }
254   - @attachment = Dummy.new.avatar
255   - end
256   -
257   - should "not run the procs immediately" do
258   - assert_kind_of Proc, @attachment.styles[:normal][:geometry]
259   - end
260   -
261   - context "when assigned" do
262   - setup do
263   - @file = StringIO.new(".")
264   - @attachment.assign(@file)
265   - end
266   -
267   - should "have the correct geometry" do
268   - assert_equal "50x50#", @attachment.styles[:normal][:geometry]
269   - end
270   - end
271   - end
272   - end
273   -
274   - context "An attachment with both 'normal' and hash-style styles" do
275   - setup do
276   - rebuild_model :styles => {
277   - :normal => ["50x50#", :png],
278   - :hash => { :geometry => "50x50#", :format => :png }
279   - }
280   - @dummy = Dummy.new
281   - @attachment = @dummy.avatar
282   - end
283   -
284   - [:processors, :whiny, :convert_options, :geometry, :format].each do |field|
285   - should "have the same #{field} field" do
286   - assert_equal @attachment.styles[:normal][field], @attachment.styles[:hash][field]
287   - end
288   - end
289   - end
290   -
291   - context "An attachment with :processors that is a proc" do
292   - setup do
293   - rebuild_model :styles => { :normal => '' }, :processors => lambda { |a| [ :test ] }
294   - @attachment = Dummy.new.avatar
295   - end
296   -
297   - should "not run the proc immediately" do
298   - assert_kind_of Proc, @attachment.styles[:normal][:processors]
299   - end
300   -
301   - context "when assigned" do
302   - setup do
303   - @attachment.assign(StringIO.new("."))
304   - end
305   -
306   - should "have the correct processors" do
307   - assert_equal [ :test ], @attachment.styles[:normal][:processors]
308   - end
309   - end
310   - end
311   -
312   - context "An attachment with erroring processor" do
313   - setup do
314   - rebuild_model :processor => [:thumbnail], :styles => { :small => '' }, :whiny_thumbnails => true
315   - @dummy = Dummy.new
316   - Paperclip::Thumbnail.expects(:make).raises(Paperclip::PaperclipError, "cannot be processed.")
317   - @file = StringIO.new("...")
318   - @file.stubs(:to_tempfile).returns(@file)
319   - @dummy.avatar = @file
320   - end
321   -
322   - should "correctly forward processing error message to the instance" do
323   - @dummy.valid?
324   - assert_contains @dummy.errors.full_messages, "Avatar cannot be processed."
325   - end
326   - end
327   -
328   - context "An attachment with multiple processors" do
329   - setup do
330   - class Paperclip::Test < Paperclip::Processor; end
331   - @style_params = { :once => {:one => 1, :two => 2} }
332   - rebuild_model :processors => [:thumbnail, :test], :styles => @style_params
333   - @dummy = Dummy.new
334   - @file = StringIO.new("...")
335   - @file.stubs(:to_tempfile).returns(@file)
336   - Paperclip::Test.stubs(:make).returns(@file)
337   - Paperclip::Thumbnail.stubs(:make).returns(@file)
338   - end
339   -
340   - context "when assigned" do
341   - setup { @dummy.avatar = @file }
342   -
343   - before_should "call #make on all specified processors" do
344   - expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
345   - Paperclip::Thumbnail.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
346   - Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
347   - end
348   -
349   - before_should "call #make with attachment passed as third argument" do
350   - expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
351   - Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
352   - end
353   - end
354   - end
355   -
356   - context "An attachment with no processors defined" do
357   - setup do
358   - rebuild_model :processors => [], :styles => {:something => 1}
359   - @dummy = Dummy.new
360   - @file = StringIO.new("...")
361   - end
362   - should "raise when assigned to" do
363   - assert_raises(RuntimeError){ @dummy.avatar = @file }
364   - end
365   - end
366   -
367   - context "Assigning an attachment with post_process hooks" do
368   - setup do
369   - rebuild_model :styles => { :something => "100x100#" }
370   - Dummy.class_eval do
371   - before_avatar_post_process :do_before_avatar
372   - after_avatar_post_process :do_after_avatar
373   - before_post_process :do_before_all
374   - after_post_process :do_after_all
375   - def do_before_avatar; end
376   - def do_after_avatar; end
377   - def do_before_all; end
378   - def do_after_all; end
379   - end
380   - @file = StringIO.new(".")
381   - @file.stubs(:to_tempfile).returns(@file)
382   - @dummy = Dummy.new
383   - Paperclip::Thumbnail.stubs(:make).returns(@file)
384   - @attachment = @dummy.avatar
385   - end
386   -
387   - should "call the defined callbacks when assigned" do
388   - @dummy.expects(:do_before_avatar).with()
389   - @dummy.expects(:do_after_avatar).with()
390   - @dummy.expects(:do_before_all).with()
391   - @dummy.expects(:do_after_all).with()
392   - Paperclip::Thumbnail.expects(:make).returns(@file)
393   - @dummy.avatar = @file
394   - end
395   -
396   - should "not cancel the processing if a before_post_process returns nil" do
397   - @dummy.expects(:do_before_avatar).with().returns(nil)
398   - @dummy.expects(:do_after_avatar).with()
399   - @dummy.expects(:do_before_all).with().returns(nil)
400   - @dummy.expects(:do_after_all).with()
401   - Paperclip::Thumbnail.expects(:make).returns(@file)
402   - @dummy.avatar = @file
403   - end
404   -
405   - should "cancel the processing if a before_post_process returns false" do
406   - @dummy.expects(:do_before_avatar).never
407   - @dummy.expects(:do_after_avatar).never
408   - @dummy.expects(:do_before_all).with().returns(false)
409   - @dummy.expects(:do_after_all).never
410   - Paperclip::Thumbnail.expects(:make).never
411   - @dummy.avatar = @file
412   - end
413   -
414   - should "cancel the processing if a before_avatar_post_process returns false" do
415   - @dummy.expects(:do_before_avatar).with().returns(false)
416   - @dummy.expects(:do_after_avatar).never
417   - @dummy.expects(:do_before_all).with().returns(true)
418   - @dummy.expects(:do_after_all).never
419   - Paperclip::Thumbnail.expects(:make).never
420   - @dummy.avatar = @file
421   - end
422   - end
423   -
424   - context "Assigning an attachment" do
425   - setup do
426   - rebuild_model :styles => { :something => "100x100#" }
427   - @file = StringIO.new(".")
428   - @file.expects(:original_filename).returns("5k.png\n\n")
429   - @file.expects(:content_type).returns("image/png\n\n")
430   - @file.stubs(:to_tempfile).returns(@file)
431   - @dummy = Dummy.new
432   - Paperclip::Thumbnail.expects(:make).returns(@file)
433   - @dummy.expects(:run_callbacks).with(:before_avatar_post_process, {:original => @file})
434   - @dummy.expects(:run_callbacks).with(:before_post_process, {:original => @file})
435   - @dummy.expects(:run_callbacks).with(:after_avatar_post_process, {:original => @file, :something => @file})
436   - @dummy.expects(:run_callbacks).with(:after_post_process, {:original => @file, :something => @file})
437   - @attachment = @dummy.avatar
438   - @dummy.avatar = @file
439   - end
440   -
441   - should "strip whitespace from original_filename field" do
442   - assert_equal "5k.png", @dummy.avatar.original_filename
443   - end
444   -
445   - should "strip whitespace from content_type field" do
446   - assert_equal "image/png", @dummy.avatar.instance.avatar_content_type
447   - end
448   - end
449   -
450   - context "Attachment with strange letters" do
451   - setup do
452   - rebuild_model
453   -
454   - @not_file = mock
455   - @tempfile = mock
456   - @not_file.stubs(:nil?).returns(false)
457   - @not_file.expects(:size).returns(10)
458   - @tempfile.expects(:size).returns(10)
459   - @not_file.expects(:to_tempfile).returns(@tempfile)
460   - @not_file.expects(:original_filename).returns("sheep_say_bæ.png\r\n")
461   - @not_file.expects(:content_type).returns("image/png\r\n")
462   -
463   - @dummy = Dummy.new
464   - @attachment = @dummy.avatar
465   - @attachment.expects(:valid_assignment?).with(@not_file).returns(true)
466   - @attachment.expects(:queue_existing_for_delete)
467   - @attachment.expects(:post_process)
468   - @attachment.expects(:valid?).returns(true)
469   - @attachment.expects(:validate)
470   - @dummy.avatar = @not_file
471   - end
472   -
473   - should "remove strange letters and replace with underscore (_)" do
474   - assert_equal "sheep_say_b_.png", @dummy.avatar.original_filename
475   - end
476   -
477   - end
478   -
479   - context "An attachment" do
480   - setup do
481   - @old_defaults = Paperclip::Attachment.default_options.dup
482   - Paperclip::Attachment.default_options.merge!({
483   - :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
484   - })
485   - FileUtils.rm_rf("tmp")
486   - rebuild_model
487   - @instance = Dummy.new
488   - @attachment = Paperclip::Attachment.new(:avatar, @instance)
489   - @file = File.new(File.join(File.dirname(__FILE__),
490   - "fixtures",
491   - "5k.png"), 'rb')
492   - end
493   -
494   - teardown do
495   - @file.close
496   - Paperclip::Attachment.default_options.merge!(@old_defaults)
497   - end
498   -
499   - should "raise if there are not the correct columns when you try to assign" do
500   - @other_attachment = Paperclip::Attachment.new(:not_here, @instance)
501   - assert_raises(Paperclip::PaperclipError) do
502   - @other_attachment.assign(@file)
503   - end
504   - end
505   -
506   - should "return its default_url when no file assigned" do
507   - assert @attachment.to_file.nil?
508   - assert_equal "/avatars/original/missing.png", @attachment.url
509   - assert_equal "/avatars/blah/missing.png", @attachment.url(:blah)
510   - end
511   -
512   - should "return nil as path when no file assigned" do
513   - assert @attachment.to_file.nil?
514   - assert_equal nil, @attachment.path
515   - assert_equal nil, @attachment.path(:blah)
516   - end
517   -
518   - context "with a file assigned in the database" do
519   - setup do
520   - @attachment.stubs(:instance_read).with(:file_name).returns("5k.png")
521   - @attachment.stubs(:instance_read).with(:content_type).returns("image/png")
522   - @attachment.stubs(:instance_read).with(:file_size).returns(12345)
523   - now = Time.now
524   - Time.stubs(:now).returns(now)
525   - @attachment.stubs(:instance_read).with(:updated_at).returns(Time.now)
526   - end
527   -
528   - should "return a correct url even if the file does not exist" do
529   - assert_nil @attachment.to_file
530   - assert_match %r{^/system/avatars/#{@instance.id}/blah/5k\.png}, @attachment.url(:blah)
531   - end
532   -
533   - should "make sure the updated_at mtime is in the url if it is defined" do
534   - assert_match %r{#{Time.now.to_i}$}, @attachment.url(:blah)
535   - end
536   -
537   - should "make sure the updated_at mtime is NOT in the url if false is passed to the url method" do
538   - assert_no_match %r{#{Time.now.to_i}$}, @attachment.url(:blah, false)
539   - end
540   -
541   - context "with the updated_at field removed" do
542   - setup do
543   - @attachment.stubs(:instance_read).with(:updated_at).returns(nil)
544   - end
545   -
546   - should "only return the url without the updated_at when sent #url" do
547   - assert_match "/avatars/#{@instance.id}/blah/5k.png", @attachment.url(:blah)
548   - end
549   - end
550   -
551   - should "return the proper path when filename has a single .'s" do
552   - assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.png", @attachment.path
553   - end
554   -
555   - should "return the proper path when filename has multiple .'s" do
556   - @attachment.stubs(:instance_read).with(:file_name).returns("5k.old.png")
557   - assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.old.png", @attachment.path
558   - end
559   -
560   - context "when expecting three styles" do
561   - setup do
562   - styles = {:styles => { :large => ["400x400", :png],
563   - :medium => ["100x100", :gif],
564   - :small => ["32x32#", :jpg]}}
565   - @attachment = Paperclip::Attachment.new(:avatar,
566   - @instance,
567   - styles)
568   - end
569   -
570   - context "and assigned a file" do
571   - setup do
572   - now = Time.now
573   - Time.stubs(:now).returns(now)
574   - @attachment.assign(@file)
575   - end
576   -
577   - should "be dirty" do
578   - assert @attachment.dirty?
579   - end
580   -
581   - context "and saved" do
582   - setup do
583   - @attachment.save
584   - end
585   -
586   - should "return the real url" do
587   - file = @attachment.to_file
588   - assert file
589   - assert_match %r{^/system/avatars/#{@instance.id}/original/5k\.png}, @attachment.url
590   - assert_match %r{^/system/avatars/#{@instance.id}/small/5k\.jpg}, @attachment.url(:small)
591   - file.close
592   - end
593   -
594   - should "commit the files to disk" do
595   - [:large, :medium, :small].each do |style|
596   - io = @attachment.to_io(style)
597   - assert File.exists?(io)
598   - assert ! io.is_a?(::Tempfile)
599   - io.close
600   - end
601   - end
602   -
603   - should "save the files as the right formats and sizes" do
604   - [[:large, 400, 61, "PNG"],
605   - [:medium, 100, 15, "GIF"],
606   - [:small, 32, 32, "JPEG"]].each do |style|
607   - cmd = %Q[identify -format "%w %h %b %m" "#{@attachment.path(style.first)}"]
608   - out = `#{cmd}`
609   - width, height, size, format = out.split(" ")
610   - assert_equal style[1].to_s, width.to_s
611   - assert_equal style[2].to_s, height.to_s
612   - assert_equal style[3].to_s, format.to_s
613   - end
614   - end
615   -
616   - should "still have its #file attribute not be nil" do
617   - assert ! (file = @attachment.to_file).nil?
618   - file.close
619   - end
620   -
621   - context "and trying to delete" do
622   - setup do
623   - @existing_names = @attachment.styles.keys.collect do |style|
624   - @attachment.path(style)
625   - end
626   - end
627   -
628   - should "delete the files after assigning nil" do
629   - @attachment.expects(:instance_write).with(:file_name, nil)
630   - @attachment.expects(:instance_write).with(:content_type, nil)
631   - @attachment.expects(:instance_write).with(:file_size, nil)
632   - @attachment.expects(:instance_write).with(:updated_at, nil)
633   - @attachment.assign nil
634   - @attachment.save
635   - @existing_names.each{|f| assert ! File.exists?(f) }
636   - end
637   -
638   - should "delete the files when you call #clear and #save" do
639   - @attachment.expects(:instance_write).with(:file_name, nil)
640   - @attachment.expects(:instance_write).with(:content_type, nil)
641   - @attachment.expects(:instance_write).with(:file_size, nil)
642   - @attachment.expects(:instance_write).with(:updated_at, nil)
643   - @attachment.clear
644   - @attachment.save
645   - @existing_names.each{|f| assert ! File.exists?(f) }
646   - end
647   -
648   - should "delete the files when you call #delete" do
649   - @attachment.expects(:instance_write).with(:file_name, nil)
650   - @attachment.expects(:instance_write).with(:content_type, nil)
651   - @attachment.expects(:instance_write).with(:file_size, nil)
652   - @attachment.expects(:instance_write).with(:updated_at, nil)
653   - @attachment.destroy
654   - @existing_names.each{|f| assert ! File.exists?(f) }
655   - end
656   - end
657   - end
658   - end
659   - end
660   -
661   - end
662   -
663   - context "when trying a nonexistant storage type" do
664   - setup do
665   - rebuild_model :storage => :not_here
666   - end
667   -
668   - should "not be able to find the module" do
669   - assert_raise(NameError){ Dummy.new.avatar }
670   - end
671   - end
672   - end
673   -
674   - context "An attachment with only a avatar_file_name column" do
675   - setup do
676   - ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
677   - table.column :avatar_file_name, :string
678   - end
679   - rebuild_class
680   - @dummy = Dummy.new
681   - @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
682   - end
683   -
684   - teardown { @file.close }
685   -
686   - should "not error when assigned an attachment" do
687   - assert_nothing_raised { @dummy.avatar = @file }
688   - end
689   -
690   - should "return the time when sent #avatar_updated_at" do
691   - now = Time.now
692   - Time.stubs(:now).returns(now)
693   - @dummy.avatar = @file
694   - assert now, @dummy.avatar.updated_at
695   - end
696   -
697   - should "return nil when reloaded and sent #avatar_updated_at" do
698   - @dummy.save
699   - @dummy.reload
700   - assert_nil @dummy.avatar.updated_at
701   - end
702   -
703   - should "return the right value when sent #avatar_file_size" do
704   - @dummy.avatar = @file
705   - assert_equal @file.size, @dummy.avatar.size
706   - end
707   -
708   - context "and avatar_updated_at column" do
709   - setup do
710   - ActiveRecord::Base.connection.add_column :dummies, :avatar_updated_at, :timestamp
711   - rebuild_class
712   - @dummy = Dummy.new
713   - end
714   -
715   - should "not error when assigned an attachment" do
716   - assert_nothing_raised { @dummy.avatar = @file }
717   - end
718   -
719   - should "return the right value when sent #avatar_updated_at" do
720   - now = Time.now
721   - Time.stubs(:now).returns(now)
722   - @dummy.avatar = @file
723   - assert_equal now.to_i, @dummy.avatar.updated_at
724   - end
725   - end
726   -
727   - context "and avatar_content_type column" do
728   - setup do
729   - ActiveRecord::Base.connection.add_column :dummies, :avatar_content_type, :string
730   - rebuild_class
731   - @dummy = Dummy.new
732   - end
733   -
734   - should "not error when assigned an attachment" do
735   - assert_nothing_raised { @dummy.avatar = @file }
736   - end
737   -
738   - should "return the right value when sent #avatar_content_type" do
739   - @dummy.avatar = @file
740   - assert_equal "image/png", @dummy.avatar.content_type
741   - end
742   - end
743   -
744   - context "and avatar_file_size column" do
745   - setup do
746   - ActiveRecord::Base.connection.add_column :dummies, :avatar_file_size, :integer
747   - rebuild_class
748   - @dummy = Dummy.new
749   - end
750   -
751   - should "not error when assigned an attachment" do
752   - assert_nothing_raised { @dummy.avatar = @file }
753   - end
754   -
755   - should "return the right value when sent #avatar_file_size" do
756   - @dummy.avatar = @file
757   - assert_equal @file.size, @dummy.avatar.size
758   - end
759   -
760   - should "return the right value when saved, reloaded, and sent #avatar_file_size" do
761   - @dummy.avatar = @file
762   - @dummy.save
763   - @dummy = Dummy.find(@dummy.id)
764   - assert_equal @file.size, @dummy.avatar.size
765   - end
766   - end
767   - end
768   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/database.yml
... ... @@ -1,4 +0,0 @@
1   -test:
2   - adapter: sqlite3
3   - database: ":memory:"
4   -
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/fixtures/12k.png

11.8 KB

vendor/gems/thoughtbot-paperclip-2.2.9.2/test/fixtures/50x50.png

1.58 KB

vendor/gems/thoughtbot-paperclip-2.2.9.2/test/fixtures/5k.png

4.35 KB

vendor/gems/thoughtbot-paperclip-2.2.9.2/test/fixtures/bad.png
... ... @@ -1 +0,0 @@
1   -This is not an image.
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/fixtures/s3.yml
... ... @@ -1,4 +0,0 @@
1   -development:
2   - key: 54321
3   -production:
4   - key: 12345
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/fixtures/text.txt
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/fixtures/twopage.pdf
No preview for this file type
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/geometry_test.rb
... ... @@ -1,177 +0,0 @@
1   -require 'test/helper'
2   -
3   -class GeometryTest < Test::Unit::TestCase
4   - context "Paperclip::Geometry" do
5   - should "correctly report its given dimensions" do
6   - assert @geo = Paperclip::Geometry.new(1024, 768)
7   - assert_equal 1024, @geo.width
8   - assert_equal 768, @geo.height
9   - end
10   -
11   - should "set height to 0 if height dimension is missing" do
12   - assert @geo = Paperclip::Geometry.new(1024)
13   - assert_equal 1024, @geo.width
14   - assert_equal 0, @geo.height
15   - end
16   -
17   - should "set width to 0 if width dimension is missing" do
18   - assert @geo = Paperclip::Geometry.new(nil, 768)
19   - assert_equal 0, @geo.width
20   - assert_equal 768, @geo.height
21   - end
22   -
23   - should "be generated from a WxH-formatted string" do
24   - assert @geo = Paperclip::Geometry.parse("800x600")
25   - assert_equal 800, @geo.width
26   - assert_equal 600, @geo.height
27   - end
28   -
29   - should "be generated from a xH-formatted string" do
30   - assert @geo = Paperclip::Geometry.parse("x600")
31   - assert_equal 0, @geo.width
32   - assert_equal 600, @geo.height
33   - end
34   -
35   - should "be generated from a Wx-formatted string" do
36   - assert @geo = Paperclip::Geometry.parse("800x")
37   - assert_equal 800, @geo.width
38   - assert_equal 0, @geo.height
39   - end
40   -
41   - should "be generated from a W-formatted string" do
42   - assert @geo = Paperclip::Geometry.parse("800")
43   - assert_equal 800, @geo.width
44   - assert_equal 0, @geo.height
45   - end
46   -
47   - should "ensure the modifier is nil if not present" do
48   - assert @geo = Paperclip::Geometry.parse("123x456")
49   - assert_nil @geo.modifier
50   - end
51   -
52   - should "treat x and X the same in geometries" do
53   - @lower = Paperclip::Geometry.parse("123x456")
54   - @upper = Paperclip::Geometry.parse("123X456")
55   - assert_equal 123, @lower.width
56   - assert_equal 123, @upper.width
57   - assert_equal 456, @lower.height
58   - assert_equal 456, @upper.height
59   - end
60   -
61   - ['>', '<', '#', '@', '%', '^', '!', nil].each do |mod|
62   - should "ensure the modifier #{mod.inspect} is preserved" do
63   - assert @geo = Paperclip::Geometry.parse("123x456#{mod}")
64   - assert_equal mod, @geo.modifier
65   - assert_equal "123x456#{mod}", @geo.to_s
66   - end
67   - end
68   -
69   - ['>', '<', '#', '@', '%', '^', '!', nil].each do |mod|
70   - should "ensure the modifier #{mod.inspect} is preserved with no height" do
71   - assert @geo = Paperclip::Geometry.parse("123x#{mod}")
72   - assert_equal mod, @geo.modifier
73   - assert_equal "123#{mod}", @geo.to_s
74   - end
75   - end
76   -
77   - should "make sure the modifier gets passed during transformation_to" do
78   - assert @src = Paperclip::Geometry.parse("123x456")
79   - assert @dst = Paperclip::Geometry.parse("123x456>")
80   - assert_equal "123x456>", @src.transformation_to(@dst).to_s
81   - end
82   -
83   - should "generate correct ImageMagick formatting string for W-formatted string" do
84   - assert @geo = Paperclip::Geometry.parse("800")
85   - assert_equal "800", @geo.to_s
86   - end
87   -
88   - should "generate correct ImageMagick formatting string for Wx-formatted string" do
89   - assert @geo = Paperclip::Geometry.parse("800x")
90   - assert_equal "800", @geo.to_s
91   - end
92   -
93   - should "generate correct ImageMagick formatting string for xH-formatted string" do
94   - assert @geo = Paperclip::Geometry.parse("x600")
95   - assert_equal "x600", @geo.to_s
96   - end
97   -
98   - should "generate correct ImageMagick formatting string for WxH-formatted string" do
99   - assert @geo = Paperclip::Geometry.parse("800x600")
100   - assert_equal "800x600", @geo.to_s
101   - end
102   -
103   - should "be generated from a file" do
104   - file = File.join(File.dirname(__FILE__), "fixtures", "5k.png")
105   - file = File.new(file, 'rb')
106   - assert_nothing_raised{ @geo = Paperclip::Geometry.from_file(file) }
107   - assert @geo.height > 0
108   - assert @geo.width > 0
109   - end
110   -
111   - should "be generated from a file path" do
112   - file = File.join(File.dirname(__FILE__), "fixtures", "5k.png")
113   - assert_nothing_raised{ @geo = Paperclip::Geometry.from_file(file) }
114   - assert @geo.height > 0
115   - assert @geo.width > 0
116   - end
117   -
118   - should "not generate from a bad file" do
119   - file = "/home/This File Does Not Exist.omg"
120   - assert_raise(Paperclip::NotIdentifiedByImageMagickError){ @geo = Paperclip::Geometry.from_file(file) }
121   - end
122   -
123   - [['vertical', 900, 1440, true, false, false, 1440, 900, 0.625],
124   - ['horizontal', 1024, 768, false, true, false, 1024, 768, 1.3333],
125   - ['square', 100, 100, false, false, true, 100, 100, 1]].each do |args|
126   - context "performing calculations on a #{args[0]} viewport" do
127   - setup do
128   - @geo = Paperclip::Geometry.new(args[1], args[2])
129   - end
130   -
131   - should "#{args[3] ? "" : "not"} be vertical" do
132   - assert_equal args[3], @geo.vertical?
133   - end
134   -
135   - should "#{args[4] ? "" : "not"} be horizontal" do
136   - assert_equal args[4], @geo.horizontal?
137   - end
138   -
139   - should "#{args[5] ? "" : "not"} be square" do
140   - assert_equal args[5], @geo.square?
141   - end
142   -
143   - should "report that #{args[6]} is the larger dimension" do
144   - assert_equal args[6], @geo.larger
145   - end
146   -
147   - should "report that #{args[7]} is the smaller dimension" do
148   - assert_equal args[7], @geo.smaller
149   - end
150   -
151   - should "have an aspect ratio of #{args[8]}" do
152   - assert_in_delta args[8], @geo.aspect, 0.0001
153   - end
154   - end
155   - end
156   -
157   - [[ [1000, 100], [64, 64], "x64", "64x64+288+0" ],
158   - [ [100, 1000], [50, 950], "x950", "50x950+22+0" ],
159   - [ [100, 1000], [50, 25], "50x", "50x25+0+237" ]]. each do |args|
160   - context "of #{args[0].inspect} and given a Geometry #{args[1].inspect} and sent transform_to" do
161   - setup do
162   - @geo = Paperclip::Geometry.new(*args[0])
163   - @dst = Paperclip::Geometry.new(*args[1])
164   - @scale, @crop = @geo.transformation_to @dst, true
165   - end
166   -
167   - should "be able to return the correct scaling transformation geometry #{args[2]}" do
168   - assert_equal args[2], @scale
169   - end
170   -
171   - should "be able to return the correct crop transformation geometry #{args[3]}" do
172   - assert_equal args[3], @crop
173   - end
174   - end
175   - end
176   - end
177   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/helper.rb
... ... @@ -1,100 +0,0 @@
1   -require 'rubygems'
2   -require 'test/unit'
3   -gem 'thoughtbot-shoulda', ">= 2.9.0"
4   -require 'shoulda'
5   -require 'mocha'
6   -require 'tempfile'
7   -
8   -gem 'sqlite3-ruby'
9   -
10   -require 'active_record'
11   -require 'active_support'
12   -begin
13   - require 'ruby-debug'
14   -rescue LoadError
15   - puts "ruby-debug not loaded"
16   -end
17   -
18   -ROOT = File.join(File.dirname(__FILE__), '..')
19   -RAILS_ROOT = ROOT
20   -RAILS_ENV = "test"
21   -
22   -$LOAD_PATH << File.join(ROOT, 'lib')
23   -$LOAD_PATH << File.join(ROOT, 'lib', 'paperclip')
24   -
25   -require File.join(ROOT, 'lib', 'paperclip.rb')
26   -
27   -require 'shoulda_macros/paperclip'
28   -
29   -FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
30   -config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
31   -ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
32   -ActiveRecord::Base.establish_connection(config['test'])
33   -
34   -def reset_class class_name
35   - ActiveRecord::Base.send(:include, Paperclip)
36   - Object.send(:remove_const, class_name) rescue nil
37   - klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
38   - klass.class_eval{ include Paperclip }
39   - klass
40   -end
41   -
42   -def reset_table table_name, &block
43   - block ||= lambda{ true }
44   - ActiveRecord::Base.connection.create_table :dummies, {:force => true}, &block
45   -end
46   -
47   -def modify_table table_name, &block
48   - ActiveRecord::Base.connection.change_table :dummies, &block
49   -end
50   -
51   -def rebuild_model options = {}
52   - ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
53   - table.column :other, :string
54   - table.column :avatar_file_name, :string
55   - table.column :avatar_content_type, :string
56   - table.column :avatar_file_size, :integer
57   - table.column :avatar_updated_at, :datetime
58   - end
59   - rebuild_class options
60   -end
61   -
62   -def rebuild_class options = {}
63   - ActiveRecord::Base.send(:include, Paperclip)
64   - Object.send(:remove_const, "Dummy") rescue nil
65   - Object.const_set("Dummy", Class.new(ActiveRecord::Base))
66   - Dummy.class_eval do
67   - include Paperclip
68   - has_attached_file :avatar, options
69   - end
70   -end
71   -
72   -def temporary_rails_env(new_env)
73   - old_env = Object.const_defined?("RAILS_ENV") ? RAILS_ENV : nil
74   - silence_warnings do
75   - Object.const_set("RAILS_ENV", new_env)
76   - end
77   - yield
78   - silence_warnings do
79   - Object.const_set("RAILS_ENV", old_env)
80   - end
81   -end
82   -
83   -class FakeModel
84   - attr_accessor :avatar_file_name,
85   - :avatar_file_size,
86   - :avatar_last_updated,
87   - :avatar_content_type,
88   - :id
89   -
90   - def errors
91   - @errors ||= []
92   - end
93   -
94   - def run_callbacks name, *args
95   - end
96   -end
97   -
98   -def attachment options
99   - Paperclip::Attachment.new(:avatar, FakeModel.new, options)
100   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/integration_test.rb
... ... @@ -1,481 +0,0 @@
1   -require 'test/helper'
2   -
3   -class IntegrationTest < Test::Unit::TestCase
4   - context "Many models at once" do
5   - setup do
6   - rebuild_model
7   - @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
8   - 300.times do |i|
9   - Dummy.create! :avatar => @file
10   - end
11   - end
12   -
13   - should "not exceed the open file limit" do
14   - assert_nothing_raised do
15   - dummies = Dummy.find(:all)
16   - dummies.each { |dummy| dummy.avatar }
17   - end
18   - end
19   - end
20   -
21   - context "An attachment" do
22   - setup do
23   - rebuild_model :styles => { :thumb => "50x50#" }
24   - @dummy = Dummy.new
25   - @file = File.new(File.join(File.dirname(__FILE__),
26   - "fixtures",
27   - "5k.png"), 'rb')
28   - @dummy.avatar = @file
29   - assert @dummy.save
30   - end
31   -
32   - teardown { @file.close }
33   -
34   - should "create its thumbnails properly" do
35   - assert_match /\b50x50\b/, `identify "#{@dummy.avatar.path(:thumb)}"`
36   - end
37   -
38   - context "redefining its attachment styles" do
39   - setup do
40   - Dummy.class_eval do
41   - has_attached_file :avatar, :styles => { :thumb => "150x25#" }
42   - has_attached_file :avatar, :styles => { :thumb => "150x25#", :dynamic => lambda { |a| '50x50#' } }
43   - end
44   - @d2 = Dummy.find(@dummy.id)
45   - @d2.avatar.reprocess!
46   - @d2.save
47   - end
48   -
49   - should "create its thumbnails properly" do
50   - assert_match /\b150x25\b/, `identify "#{@dummy.avatar.path(:thumb)}"`
51   - assert_match /\b50x50\b/, `identify "#{@dummy.avatar.path(:dynamic)}"`
52   - end
53   - end
54   - end
55   -
56   - context "A model that modifies its original" do
57   - setup do
58   - rebuild_model :styles => { :original => "2x2#" }
59   - @dummy = Dummy.new
60   - @file = File.new(File.join(File.dirname(__FILE__),
61   - "fixtures",
62   - "5k.png"), 'rb')
63   - @dummy.avatar = @file
64   - end
65   -
66   - should "report the file size of the processed file and not the original" do
67   - assert_not_equal @file.size, @dummy.avatar.size
68   - end
69   -
70   - teardown { @file.close }
71   - end
72   -
73   - context "A model with attachments scoped under an id" do
74   - setup do
75   - rebuild_model :styles => { :large => "100x100",
76   - :medium => "50x50" },
77   - :path => ":rails_root/tmp/:id/:attachments/:style.:extension"
78   - @dummy = Dummy.new
79   - @file = File.new(File.join(File.dirname(__FILE__),
80   - "fixtures",
81   - "5k.png"), 'rb')
82   - @dummy.avatar = @file
83   - end
84   -
85   - teardown { @file.close }
86   -
87   - context "when saved" do
88   - setup do
89   - @dummy.save
90   - @saved_path = @dummy.avatar.path(:large)
91   - end
92   -
93   - should "have a large file in the right place" do
94   - assert File.exists?(@dummy.avatar.path(:large))
95   - end
96   -
97   - context "and deleted" do
98   - setup do
99   - @dummy.avatar.clear
100   - @dummy.save
101   - end
102   -
103   - should "not have a large file in the right place anymore" do
104   - assert ! File.exists?(@saved_path)
105   - end
106   -
107   - should "not have its next two parent directories" do
108   - assert ! File.exists?(File.dirname(@saved_path))
109   - assert ! File.exists?(File.dirname(File.dirname(@saved_path)))
110   - end
111   -
112   - before_should "not die if an unexpected SystemCallError happens" do
113   - FileUtils.stubs(:rmdir).raises(Errno::EPIPE)
114   - end
115   - end
116   - end
117   - end
118   -
119   - context "A model with no attachment validation" do
120   - setup do
121   - rebuild_model :styles => { :large => "300x300>",
122   - :medium => "100x100",
123   - :thumb => ["32x32#", :gif] },
124   - :default_style => :medium,
125   - :url => "/:attachment/:class/:style/:id/:basename.:extension",
126   - :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
127   - @dummy = Dummy.new
128   - end
129   -
130   - should "have its definition return false when asked about whiny_thumbnails" do
131   - assert ! Dummy.attachment_definitions[:avatar][:whiny_thumbnails]
132   - end
133   -
134   - context "when validates_attachment_thumbnails is called" do
135   - setup do
136   - Dummy.validates_attachment_thumbnails :avatar
137   - end
138   -
139   - should "have its definition return true when asked about whiny_thumbnails" do
140   - assert_equal true, Dummy.attachment_definitions[:avatar][:whiny_thumbnails]
141   - end
142   - end
143   -
144   - context "redefined to have attachment validations" do
145   - setup do
146   - rebuild_model :styles => { :large => "300x300>",
147   - :medium => "100x100",
148   - :thumb => ["32x32#", :gif] },
149   - :whiny_thumbnails => true,
150   - :default_style => :medium,
151   - :url => "/:attachment/:class/:style/:id/:basename.:extension",
152   - :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
153   - end
154   -
155   - should "have its definition return true when asked about whiny_thumbnails" do
156   - assert_equal true, Dummy.attachment_definitions[:avatar][:whiny_thumbnails]
157   - end
158   - end
159   - end
160   -
161   - context "A model with no convert_options setting" do
162   - setup do
163   - rebuild_model :styles => { :large => "300x300>",
164   - :medium => "100x100",
165   - :thumb => ["32x32#", :gif] },
166   - :default_style => :medium,
167   - :url => "/:attachment/:class/:style/:id/:basename.:extension",
168   - :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
169   - @dummy = Dummy.new
170   - end
171   -
172   - should "have its definition return nil when asked about convert_options" do
173   - assert ! Dummy.attachment_definitions[:avatar][:convert_options]
174   - end
175   -
176   - context "redefined to have convert_options setting" do
177   - setup do
178   - rebuild_model :styles => { :large => "300x300>",
179   - :medium => "100x100",
180   - :thumb => ["32x32#", :gif] },
181   - :convert_options => "-strip -depth 8",
182   - :default_style => :medium,
183   - :url => "/:attachment/:class/:style/:id/:basename.:extension",
184   - :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
185   - end
186   -
187   - should "have its definition return convert_options value when asked about convert_options" do
188   - assert_equal "-strip -depth 8", Dummy.attachment_definitions[:avatar][:convert_options]
189   - end
190   - end
191   - end
192   -
193   - context "A model with a filesystem attachment" do
194   - setup do
195   - rebuild_model :styles => { :large => "300x300>",
196   - :medium => "100x100",
197   - :thumb => ["32x32#", :gif] },
198   - :whiny_thumbnails => true,
199   - :default_style => :medium,
200   - :url => "/:attachment/:class/:style/:id/:basename.:extension",
201   - :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
202   - @dummy = Dummy.new
203   - @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
204   - @bad_file = File.new(File.join(FIXTURES_DIR, "bad.png"), 'rb')
205   -
206   - assert @dummy.avatar = @file
207   - assert @dummy.valid?
208   - assert @dummy.save
209   - end
210   -
211   - should "write and delete its files" do
212   - [["434x66", :original],
213   - ["300x46", :large],
214   - ["100x15", :medium],
215   - ["32x32", :thumb]].each do |geo, style|
216   - cmd = %Q[identify -format "%wx%h" "#{@dummy.avatar.path(style)}"]
217   - assert_equal geo, `#{cmd}`.chomp, cmd
218   - end
219   -
220   - saved_paths = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.path(s) }
221   -
222   - @d2 = Dummy.find(@dummy.id)
223   - assert_equal "100x15", `identify -format "%wx%h" "#{@d2.avatar.path}"`.chomp
224   - assert_equal "434x66", `identify -format "%wx%h" "#{@d2.avatar.path(:original)}"`.chomp
225   - assert_equal "300x46", `identify -format "%wx%h" "#{@d2.avatar.path(:large)}"`.chomp
226   - assert_equal "100x15", `identify -format "%wx%h" "#{@d2.avatar.path(:medium)}"`.chomp
227   - assert_equal "32x32", `identify -format "%wx%h" "#{@d2.avatar.path(:thumb)}"`.chomp
228   -
229   - @dummy.avatar = "not a valid file but not nil"
230   - assert_equal File.basename(@file.path), @dummy.avatar_file_name
231   - assert @dummy.valid?
232   - assert @dummy.save
233   -
234   - saved_paths.each do |p|
235   - assert File.exists?(p)
236   - end
237   -
238   - @dummy.avatar.clear
239   - assert_nil @dummy.avatar_file_name
240   - assert @dummy.valid?
241   - assert @dummy.save
242   -
243   - saved_paths.each do |p|
244   - assert ! File.exists?(p)
245   - end
246   -
247   - @d2 = Dummy.find(@dummy.id)
248   - assert_nil @d2.avatar_file_name
249   - end
250   -
251   - should "work exactly the same when new as when reloaded" do
252   - @d2 = Dummy.find(@dummy.id)
253   -
254   - assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
255   - [:thumb, :medium, :large, :original].each do |style|
256   - assert_equal @dummy.avatar.path(style), @d2.avatar.path(style)
257   - end
258   -
259   - saved_paths = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.path(s) }
260   -
261   - @d2.avatar.clear
262   - assert @d2.save
263   -
264   - saved_paths.each do |p|
265   - assert ! File.exists?(p)
266   - end
267   - end
268   -
269   - should "know the difference between good files, bad files, and not files" do
270   - expected = @dummy.avatar.to_file
271   - @dummy.avatar = "not a file"
272   - assert @dummy.valid?
273   - assert_equal expected.path, @dummy.avatar.path
274   - expected.close
275   -
276   - @dummy.avatar = @bad_file
277   - assert ! @dummy.valid?
278   - end
279   -
280   - should "know the difference between good files, bad files, and not files when validating" do
281   - Dummy.validates_attachment_presence :avatar
282   - @d2 = Dummy.find(@dummy.id)
283   - @d2.avatar = @file
284   - assert @d2.valid?, @d2.errors.full_messages.inspect
285   - @d2.avatar = @bad_file
286   - assert ! @d2.valid?
287   - end
288   -
289   - should "be able to reload without saving and not have the file disappear" do
290   - @dummy.avatar = @file
291   - assert @dummy.save
292   - @dummy.avatar.clear
293   - assert_nil @dummy.avatar_file_name
294   - @dummy.reload
295   - assert_equal "5k.png", @dummy.avatar_file_name
296   - end
297   -
298   - context "that is assigned its file from another Paperclip attachment" do
299   - setup do
300   - @dummy2 = Dummy.new
301   - @file2 = File.new(File.join(FIXTURES_DIR, "12k.png"), 'rb')
302   - assert @dummy2.avatar = @file2
303   - @dummy2.save
304   - end
305   -
306   - should "work when assigned a file" do
307   - assert_not_equal `identify -format "%wx%h" "#{@dummy.avatar.path(:original)}"`,
308   - `identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
309   -
310   - assert @dummy.avatar = @dummy2.avatar
311   - @dummy.save
312   - assert_equal `identify -format "%wx%h" "#{@dummy.avatar.path(:original)}"`,
313   - `identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
314   - end
315   - end
316   -
317   - end
318   -
319   - context "A model with an attachments association and a Paperclip attachment" do
320   - setup do
321   - Dummy.class_eval do
322   - has_many :attachments, :class_name => 'Dummy'
323   - end
324   -
325   - @dummy = Dummy.new
326   - @dummy.avatar = File.new(File.join(File.dirname(__FILE__),
327   - "fixtures",
328   - "5k.png"), 'rb')
329   - end
330   -
331   - should "should not error when saving" do
332   - assert_nothing_raised do
333   - @dummy.save!
334   - end
335   - end
336   - end
337   -
338   - if ENV['S3_TEST_BUCKET']
339   - def s3_files_for attachment
340   - [:thumb, :medium, :large, :original].inject({}) do |files, style|
341   - data = `curl "#{attachment.url(style)}" 2>/dev/null`.chomp
342   - t = Tempfile.new("paperclip-test")
343   - t.binmode
344   - t.write(data)
345   - t.rewind
346   - files[style] = t
347   - files
348   - end
349   - end
350   -
351   - def s3_headers_for attachment, style
352   - `curl --head "#{attachment.url(style)}" 2>/dev/null`.split("\n").inject({}) do |h,head|
353   - split_head = head.chomp.split(/\s*:\s*/, 2)
354   - h[split_head.first.downcase] = split_head.last unless split_head.empty?
355   - h
356   - end
357   - end
358   -
359   - context "A model with an S3 attachment" do
360   - setup do
361   - rebuild_model :styles => { :large => "300x300>",
362   - :medium => "100x100",
363   - :thumb => ["32x32#", :gif] },
364   - :storage => :s3,
365   - :whiny_thumbnails => true,
366   - # :s3_options => {:logger => Logger.new(StringIO.new)},
367   - :s3_credentials => File.new(File.join(File.dirname(__FILE__), "s3.yml")),
368   - :default_style => :medium,
369   - :bucket => ENV['S3_TEST_BUCKET'],
370   - :path => ":class/:attachment/:id/:style/:basename.:extension"
371   - @dummy = Dummy.new
372   - @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
373   - @bad_file = File.new(File.join(FIXTURES_DIR, "bad.png"), 'rb')
374   -
375   - assert @dummy.avatar = @file
376   - assert @dummy.valid?
377   - assert @dummy.save
378   -
379   - @files_on_s3 = s3_files_for @dummy.avatar
380   - end
381   -
382   - should "write and delete its files" do
383   - [["434x66", :original],
384   - ["300x46", :large],
385   - ["100x15", :medium],
386   - ["32x32", :thumb]].each do |geo, style|
387   - cmd = %Q[identify -format "%wx%h" "#{@files_on_s3[style].path}"]
388   - assert_equal geo, `#{cmd}`.chomp, cmd
389   - end
390   -
391   - @d2 = Dummy.find(@dummy.id)
392   - @d2_files = s3_files_for @d2.avatar
393   - [["434x66", :original],
394   - ["300x46", :large],
395   - ["100x15", :medium],
396   - ["32x32", :thumb]].each do |geo, style|
397   - cmd = %Q[identify -format "%wx%h" "#{@d2_files[style].path}"]
398   - assert_equal geo, `#{cmd}`.chomp, cmd
399   - end
400   -
401   - @dummy.avatar = "not a valid file but not nil"
402   - assert_equal File.basename(@file.path), @dummy.avatar_file_name
403   - assert @dummy.valid?
404   - assert @dummy.save
405   -
406   - saved_keys = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s) }
407   -
408   - saved_keys.each do |key|
409   - assert key.exists?
410   - end
411   -
412   - @dummy.avatar.clear
413   - assert_nil @dummy.avatar_file_name
414   - assert @dummy.valid?
415   - assert @dummy.save
416   -
417   - saved_keys.each do |key|
418   - assert ! key.exists?
419   - end
420   -
421   - @d2 = Dummy.find(@dummy.id)
422   - assert_nil @d2.avatar_file_name
423   - end
424   -
425   - should "work exactly the same when new as when reloaded" do
426   - @d2 = Dummy.find(@dummy.id)
427   -
428   - assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
429   - [:thumb, :medium, :large, :original].each do |style|
430   - assert_equal @dummy.avatar.to_file(style).to_s, @d2.avatar.to_file(style).to_s
431   - end
432   -
433   - saved_keys = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s) }
434   -
435   - @d2.avatar.clear
436   - assert @d2.save
437   -
438   - saved_keys.each do |key|
439   - assert ! key.exists?
440   - end
441   - end
442   -
443   - should "know the difference between good files, bad files, not files, and nil" do
444   - expected = @dummy.avatar.to_file
445   - @dummy.avatar = "not a file"
446   - assert @dummy.valid?
447   - assert_equal expected.full_name, @dummy.avatar.to_file.full_name
448   -
449   - @dummy.avatar = @bad_file
450   - assert ! @dummy.valid?
451   - @dummy.avatar = nil
452   - assert @dummy.valid?
453   -
454   - Dummy.validates_attachment_presence :avatar
455   - @d2 = Dummy.find(@dummy.id)
456   - @d2.avatar = @file
457   - assert @d2.valid?
458   - @d2.avatar = @bad_file
459   - assert ! @d2.valid?
460   - @d2.avatar = nil
461   - assert ! @d2.valid?
462   - end
463   -
464   - should "be able to reload without saving and not have the file disappear" do
465   - @dummy.avatar = @file
466   - assert @dummy.save
467   - @dummy.avatar = nil
468   - assert_nil @dummy.avatar_file_name
469   - @dummy.reload
470   - assert_equal "5k.png", @dummy.avatar_file_name
471   - end
472   -
473   - should "have the right content type" do
474   - headers = s3_headers_for(@dummy.avatar, :original)
475   - p headers
476   - assert_equal 'image/png', headers['content-type']
477   - end
478   - end
479   - end
480   -end
481   -
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/interpolations_test.rb
... ... @@ -1,120 +0,0 @@
1   -require 'test/helper'
2   -
3   -class InterpolationsTest < Test::Unit::TestCase
4   - should "return all methods but the infrastructure when sent #all" do
5   - methods = Paperclip::Interpolations.all
6   - assert ! methods.include?(:[])
7   - assert ! methods.include?(:[]=)
8   - assert ! methods.include?(:all)
9   - methods.each do |m|
10   - assert Paperclip::Interpolations.respond_to? m
11   - end
12   - end
13   -
14   - should "return the RAILS_ROOT" do
15   - assert_equal RAILS_ROOT, Paperclip::Interpolations.rails_root(:attachment, :style)
16   - end
17   -
18   - should "return the RAILS_ENV" do
19   - assert_equal RAILS_ENV, Paperclip::Interpolations.rails_env(:attachment, :style)
20   - end
21   -
22   - should "return the class of the instance" do
23   - attachment = mock
24   - attachment.expects(:instance).returns(attachment)
25   - attachment.expects(:class).returns("Thing")
26   - assert_equal "things", Paperclip::Interpolations.class(attachment, :style)
27   - end
28   -
29   - should "return the basename of the file" do
30   - attachment = mock
31   - attachment.expects(:original_filename).returns("one.jpg").times(2)
32   - assert_equal "one", Paperclip::Interpolations.basename(attachment, :style)
33   - end
34   -
35   - should "return the extension of the file" do
36   - attachment = mock
37   - attachment.expects(:original_filename).returns("one.jpg")
38   - attachment.expects(:styles).returns({})
39   - assert_equal "jpg", Paperclip::Interpolations.extension(attachment, :style)
40   - end
41   -
42   - should "return the extension of the file as the format if defined in the style" do
43   - attachment = mock
44   - attachment.expects(:original_filename).never
45   - attachment.expects(:styles).returns({:style => {:format => "png"}})
46   - assert_equal "png", Paperclip::Interpolations.extension(attachment, :style)
47   - end
48   -
49   - should "return the id of the attachment" do
50   - attachment = mock
51   - attachment.expects(:id).returns(23)
52   - attachment.expects(:instance).returns(attachment)
53   - assert_equal 23, Paperclip::Interpolations.id(attachment, :style)
54   - end
55   -
56   - should "return the partitioned id of the attachment" do
57   - attachment = mock
58   - attachment.expects(:id).returns(23)
59   - attachment.expects(:instance).returns(attachment)
60   - assert_equal "000/000/023", Paperclip::Interpolations.id_partition(attachment, :style)
61   - end
62   -
63   - should "return the name of the attachment" do
64   - attachment = mock
65   - attachment.expects(:name).returns("file")
66   - assert_equal "files", Paperclip::Interpolations.attachment(attachment, :style)
67   - end
68   -
69   - should "return the style" do
70   - assert_equal :style, Paperclip::Interpolations.style(:attachment, :style)
71   - end
72   -
73   - should "return the default style" do
74   - attachment = mock
75   - attachment.expects(:default_style).returns(:default_style)
76   - assert_equal :default_style, Paperclip::Interpolations.style(attachment, nil)
77   - end
78   -
79   - should "reinterpolate :url" do
80   - attachment = mock
81   - attachment.expects(:options).returns({:url => ":id"})
82   - attachment.expects(:url).with(:style, false).returns("1234")
83   - assert_equal "1234", Paperclip::Interpolations.url(attachment, :style)
84   - end
85   -
86   - should "raise if infinite loop detcted reinterpolating :url" do
87   - attachment = mock
88   - attachment.expects(:options).returns({:url => ":url"})
89   - assert_raises(Paperclip::InfiniteInterpolationError){ Paperclip::Interpolations.url(attachment, :style) }
90   - end
91   -
92   - should "return the filename as basename.extension" do
93   - attachment = mock
94   - attachment.expects(:styles).returns({})
95   - attachment.expects(:original_filename).returns("one.jpg").times(3)
96   - assert_equal "one.jpg", Paperclip::Interpolations.filename(attachment, :style)
97   - end
98   -
99   - should "return the filename as basename.extension when format supplied" do
100   - attachment = mock
101   - attachment.expects(:styles).returns({:style => {:format => :png}})
102   - attachment.expects(:original_filename).returns("one.jpg").times(2)
103   - assert_equal "one.png", Paperclip::Interpolations.filename(attachment, :style)
104   - end
105   -
106   - should "return the timestamp" do
107   - now = Time.now
108   - attachment = mock
109   - attachment.expects(:instance_read).with(:updated_at).returns(now)
110   - assert_equal now.to_s, Paperclip::Interpolations.timestamp(attachment, :style)
111   - end
112   -
113   - should "call all expected interpolations with the given arguments" do
114   - Paperclip::Interpolations.expects(:id).with(:attachment, :style).returns(1234)
115   - Paperclip::Interpolations.expects(:attachment).with(:attachment, :style).returns("attachments")
116   - Paperclip::Interpolations.expects(:notreal).never
117   - value = Paperclip::Interpolations.interpolate(":notreal/:id/:attachment", :attachment, :style)
118   - assert_equal ":notreal/1234/attachments", value
119   - end
120   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/iostream_test.rb
... ... @@ -1,71 +0,0 @@
1   -require 'test/helper'
2   -
3   -class IOStreamTest < Test::Unit::TestCase
4   - context "IOStream" do
5   - should "be included in IO, File, Tempfile, and StringIO" do
6   - [IO, File, Tempfile, StringIO].each do |klass|
7   - assert klass.included_modules.include?(IOStream), "Not in #{klass}"
8   - end
9   - end
10   - end
11   -
12   - context "A file" do
13   - setup do
14   - @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
15   - end
16   -
17   - teardown { @file.close }
18   -
19   - context "that is sent #stream_to" do
20   -
21   - context "and given a String" do
22   - setup do
23   - FileUtils.mkdir_p(File.join(ROOT, 'tmp'))
24   - assert @result = @file.stream_to(File.join(ROOT, 'tmp', 'iostream.string.test'))
25   - end
26   -
27   - should "return a File" do
28   - assert @result.is_a?(File)
29   - end
30   -
31   - should "contain the same data as the original file" do
32   - @file.rewind; @result.rewind
33   - assert_equal @file.read, @result.read
34   - end
35   - end
36   -
37   - context "and given a Tempfile" do
38   - setup do
39   - tempfile = Tempfile.new('iostream.test')
40   - tempfile.binmode
41   - assert @result = @file.stream_to(tempfile)
42   - end
43   -
44   - should "return a Tempfile" do
45   - assert @result.is_a?(Tempfile)
46   - end
47   -
48   - should "contain the same data as the original file" do
49   - @file.rewind; @result.rewind
50   - assert_equal @file.read, @result.read
51   - end
52   - end
53   -
54   - end
55   -
56   - context "that is sent #to_tempfile" do
57   - setup do
58   - assert @tempfile = @file.to_tempfile
59   - end
60   -
61   - should "convert it to a Tempfile" do
62   - assert @tempfile.is_a?(Tempfile)
63   - end
64   -
65   - should "have the Tempfile contain the same data as the file" do
66   - @file.rewind; @tempfile.rewind
67   - assert_equal @file.read, @tempfile.read
68   - end
69   - end
70   - end
71   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/matchers/have_attached_file_matcher_test.rb
... ... @@ -1,21 +0,0 @@
1   -require 'test/helper'
2   -
3   -class HaveAttachedFileMatcherTest < Test::Unit::TestCase
4   - context "have_attached_file" do
5   - setup do
6   - @dummy_class = reset_class "Dummy"
7   - reset_table "dummies"
8   - @matcher = self.class.have_attached_file(:avatar)
9   - end
10   -
11   - should "reject a class with no attachment" do
12   - assert_rejects @matcher, @dummy_class
13   - end
14   -
15   - should "accept a class with an attachment" do
16   - modify_table("dummies"){|d| d.string :avatar_file_name }
17   - @dummy_class.has_attached_file :avatar
18   - assert_accepts @matcher, @dummy_class
19   - end
20   - end
21   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/matchers/validate_attachment_content_type_matcher_test.rb
... ... @@ -1,30 +0,0 @@
1   -require 'test/helper'
2   -
3   -class ValidateAttachmentContentTypeMatcherTest < Test::Unit::TestCase
4   - context "validate_attachment_content_type" do
5   - setup do
6   - reset_table("dummies") do |d|
7   - d.string :avatar_file_name
8   - end
9   - @dummy_class = reset_class "Dummy"
10   - @dummy_class.has_attached_file :avatar
11   - @matcher = self.class.validate_attachment_content_type(:avatar).
12   - allowing(%w(image/png image/jpeg)).
13   - rejecting(%w(audio/mp3 application/octet-stream))
14   - end
15   -
16   - should "reject a class with no validation" do
17   - assert_rejects @matcher, @dummy_class
18   - end
19   -
20   - should "reject a class with a validation that doesn't match" do
21   - @dummy_class.validates_attachment_content_type :avatar, :content_type => %r{audio/.*}
22   - assert_rejects @matcher, @dummy_class
23   - end
24   -
25   - should "accept a class with a validation" do
26   - @dummy_class.validates_attachment_content_type :avatar, :content_type => %r{image/.*}
27   - assert_accepts @matcher, @dummy_class
28   - end
29   - end
30   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/matchers/validate_attachment_presence_matcher_test.rb
... ... @@ -1,21 +0,0 @@
1   -require 'test/helper'
2   -
3   -class ValidateAttachmentPresenceMatcherTest < Test::Unit::TestCase
4   - context "validate_attachment_presence" do
5   - setup do
6   - reset_table("dummies"){|d| d.string :avatar_file_name }
7   - @dummy_class = reset_class "Dummy"
8   - @dummy_class.has_attached_file :avatar
9   - @matcher = self.class.validate_attachment_presence(:avatar)
10   - end
11   -
12   - should "reject a class with no validation" do
13   - assert_rejects @matcher, @dummy_class
14   - end
15   -
16   - should "accept a class with a validation" do
17   - @dummy_class.validates_attachment_presence :avatar
18   - assert_accepts @matcher, @dummy_class
19   - end
20   - end
21   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/matchers/validate_attachment_size_matcher_test.rb
... ... @@ -1,50 +0,0 @@
1   -require 'test/helper'
2   -
3   -class ValidateAttachmentSizeMatcherTest < Test::Unit::TestCase
4   - context "validate_attachment_size" do
5   - setup do
6   - reset_table("dummies") do |d|
7   - d.string :avatar_file_name
8   - end
9   - @dummy_class = reset_class "Dummy"
10   - @dummy_class.has_attached_file :avatar
11   - end
12   -
13   - context "of limited size" do
14   - setup{ @matcher = self.class.validate_attachment_size(:avatar).in(256..1024) }
15   -
16   - should "reject a class with no validation" do
17   - assert_rejects @matcher, @dummy_class
18   - end
19   -
20   - should "reject a class with a validation that's too high" do
21   - @dummy_class.validates_attachment_size :avatar, :in => 256..2048
22   - assert_rejects @matcher, @dummy_class
23   - end
24   -
25   - should "reject a class with a validation that's too low" do
26   - @dummy_class.validates_attachment_size :avatar, :in => 0..1024
27   - assert_rejects @matcher, @dummy_class
28   - end
29   -
30   - should "accept a class with a validation that matches" do
31   - @dummy_class.validates_attachment_size :avatar, :in => 256..1024
32   - assert_accepts @matcher, @dummy_class
33   - end
34   - end
35   -
36   - context "validates_attachment_size with infinite range" do
37   - setup{ @matcher = self.class.validate_attachment_size(:avatar) }
38   -
39   - should "accept a class with an upper limit" do
40   - @dummy_class.validates_attachment_size :avatar, :less_than => 1
41   - assert_accepts @matcher, @dummy_class
42   - end
43   -
44   - should "accept a class with no upper limit" do
45   - @dummy_class.validates_attachment_size :avatar, :greater_than => 1
46   - assert_accepts @matcher, @dummy_class
47   - end
48   - end
49   - end
50   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/paperclip_test.rb
... ... @@ -1,291 +0,0 @@
1   -require 'test/helper'
2   -
3   -class PaperclipTest < Test::Unit::TestCase
4   - [:image_magick_path, :convert_path].each do |path|
5   - context "Calling Paperclip.run with an #{path} specified" do
6   - setup do
7   - Paperclip.options[:image_magick_path] = nil
8   - Paperclip.options[:convert_path] = nil
9   - Paperclip.options[path] = "/usr/bin"
10   - end
11   -
12   - should "execute the right command" do
13   - Paperclip.expects(:path_for_command).with("convert").returns("/usr/bin/convert")
14   - Paperclip.expects(:bit_bucket).returns("/dev/null")
15   - Paperclip.expects(:"`").with("/usr/bin/convert one.jpg two.jpg 2>/dev/null")
16   - Paperclip.run("convert", "one.jpg two.jpg")
17   - end
18   - end
19   - end
20   -
21   - context "Calling Paperclip.run with no path specified" do
22   - setup do
23   - Paperclip.options[:image_magick_path] = nil
24   - Paperclip.options[:convert_path] = nil
25   - end
26   -
27   - should "execute the right command" do
28   - Paperclip.expects(:path_for_command).with("convert").returns("convert")
29   - Paperclip.expects(:bit_bucket).returns("/dev/null")
30   - Paperclip.expects(:"`").with("convert one.jpg two.jpg 2>/dev/null")
31   - Paperclip.run("convert", "one.jpg two.jpg")
32   - end
33   -
34   - should "log the command when :log_command is set" do
35   - Paperclip.options[:log_command] = true
36   - Paperclip.expects(:bit_bucket).returns("/dev/null")
37   - Paperclip.expects(:log).with("this is the command 2>/dev/null")
38   - Paperclip.expects(:"`").with("this is the command 2>/dev/null")
39   - Paperclip.run("this","is the command")
40   - end
41   - end
42   -
43   - should "raise when sent #processor and the name of a class that exists but isn't a subclass of Processor" do
44   - assert_raises(Paperclip::PaperclipError){ Paperclip.processor(:attachment) }
45   - end
46   -
47   - should "raise when sent #processor and the name of a class that doesn't exist" do
48   - assert_raises(NameError){ Paperclip.processor(:boogey_man) }
49   - end
50   -
51   - should "return a class when sent #processor and the name of a class under Paperclip" do
52   - assert_equal ::Paperclip::Thumbnail, Paperclip.processor(:thumbnail)
53   - end
54   -
55   - should "call a proc sent to check_guard" do
56   - @dummy = Dummy.new
57   - @dummy.expects(:one).returns(:one)
58   - assert_equal :one, @dummy.avatar.send(:check_guard, lambda{|x| x.one })
59   - end
60   -
61   - should "call a method name sent to check_guard" do
62   - @dummy = Dummy.new
63   - @dummy.expects(:one).returns(:one)
64   - assert_equal :one, @dummy.avatar.send(:check_guard, :one)
65   - end
66   -
67   - context "Paperclip.bit_bucket" do
68   - context "on systems without /dev/null" do
69   - setup do
70   - File.expects(:exists?).with("/dev/null").returns(false)
71   - end
72   -
73   - should "return 'NUL'" do
74   - assert_equal "NUL", Paperclip.bit_bucket
75   - end
76   - end
77   -
78   - context "on systems with /dev/null" do
79   - setup do
80   - File.expects(:exists?).with("/dev/null").returns(true)
81   - end
82   -
83   - should "return '/dev/null'" do
84   - assert_equal "/dev/null", Paperclip.bit_bucket
85   - end
86   - end
87   - end
88   -
89   - context "An ActiveRecord model with an 'avatar' attachment" do
90   - setup do
91   - rebuild_model :path => "tmp/:class/omg/:style.:extension"
92   - @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
93   - end
94   -
95   - teardown { @file.close }
96   -
97   - should "not error when trying to also create a 'blah' attachment" do
98   - assert_nothing_raised do
99   - Dummy.class_eval do
100   - has_attached_file :blah
101   - end
102   - end
103   - end
104   -
105   - context "that is attr_protected" do
106   - setup do
107   - Dummy.class_eval do
108   - attr_protected :avatar
109   - end
110   - @dummy = Dummy.new
111   - end
112   -
113   - should "not assign the avatar on mass-set" do
114   - @dummy.attributes = { :other => "I'm set!",
115   - :avatar => @file }
116   -
117   - assert_equal "I'm set!", @dummy.other
118   - assert ! @dummy.avatar?
119   - end
120   -
121   - should "still allow assigment on normal set" do
122   - @dummy.other = "I'm set!"
123   - @dummy.avatar = @file
124   -
125   - assert_equal "I'm set!", @dummy.other
126   - assert @dummy.avatar?
127   - end
128   - end
129   -
130   - context "with a subclass" do
131   - setup do
132   - class ::SubDummy < Dummy; end
133   - end
134   -
135   - should "be able to use the attachment from the subclass" do
136   - assert_nothing_raised do
137   - @subdummy = SubDummy.create(:avatar => @file)
138   - end
139   - end
140   -
141   - should "be able to see the attachment definition from the subclass's class" do
142   - assert_equal "tmp/:class/omg/:style.:extension", SubDummy.attachment_definitions[:avatar][:path]
143   - end
144   -
145   - teardown do
146   - Object.send(:remove_const, "SubDummy") rescue nil
147   - end
148   - end
149   -
150   - should "have an #avatar method" do
151   - assert Dummy.new.respond_to?(:avatar)
152   - end
153   -
154   - should "have an #avatar= method" do
155   - assert Dummy.new.respond_to?(:avatar=)
156   - end
157   -
158   - context "that is valid" do
159   - setup do
160   - @dummy = Dummy.new
161   - @dummy.avatar = @file
162   - end
163   -
164   - should "be valid" do
165   - assert @dummy.valid?
166   - end
167   -
168   - context "then has a validation added that makes it invalid" do
169   - setup do
170   - assert @dummy.save
171   - Dummy.class_eval do
172   - validates_attachment_content_type :avatar, :content_type => ["text/plain"]
173   - end
174   - @dummy2 = Dummy.find(@dummy.id)
175   - end
176   -
177   - should "be invalid when reloaded" do
178   - assert ! @dummy2.valid?, @dummy2.errors.inspect
179   - end
180   -
181   - should "be able to call #valid? twice without having duplicate errors" do
182   - @dummy2.avatar.valid?
183   - first_errors = @dummy2.avatar.errors
184   - @dummy2.avatar.valid?
185   - assert_equal first_errors, @dummy2.avatar.errors
186   - end
187   - end
188   - end
189   -
190   - context "a validation with an if guard clause" do
191   - setup do
192   - Dummy.send(:"validates_attachment_presence", :avatar, :if => lambda{|i| i.foo })
193   - @dummy = Dummy.new
194   - end
195   -
196   - should "attempt validation if the guard returns true" do
197   - @dummy.expects(:foo).returns(true)
198   - @dummy.avatar.expects(:validate_presence).returns(nil)
199   - @dummy.valid?
200   - end
201   -
202   - should "not attempt validation if the guard returns false" do
203   - @dummy.expects(:foo).returns(false)
204   - @dummy.avatar.expects(:validate_presence).never
205   - @dummy.valid?
206   - end
207   - end
208   -
209   - context "a validation with an unless guard clause" do
210   - setup do
211   - Dummy.send(:"validates_attachment_presence", :avatar, :unless => lambda{|i| i.foo })
212   - @dummy = Dummy.new
213   - end
214   -
215   - should "attempt validation if the guard returns true" do
216   - @dummy.expects(:foo).returns(false)
217   - @dummy.avatar.expects(:validate_presence).returns(nil)
218   - @dummy.valid?
219   - end
220   -
221   - should "not attempt validation if the guard returns false" do
222   - @dummy.expects(:foo).returns(true)
223   - @dummy.avatar.expects(:validate_presence).never
224   - @dummy.valid?
225   - end
226   - end
227   -
228   - def self.should_validate validation, options, valid_file, invalid_file
229   - context "with #{validation} validation and #{options.inspect} options" do
230   - setup do
231   - Dummy.send(:"validates_attachment_#{validation}", :avatar, options)
232   - @dummy = Dummy.new
233   - end
234   - context "and assigning nil" do
235   - setup do
236   - @dummy.avatar = nil
237   - @dummy.valid?
238   - end
239   - if validation == :presence
240   - should "have an error on the attachment" do
241   - assert @dummy.errors.on(:avatar)
242   - end
243   - else
244   - should "not have an error on the attachment" do
245   - assert_nil @dummy.errors.on(:avatar)
246   - end
247   - end
248   - end
249   - context "and assigned a valid file" do
250   - setup do
251   - @dummy.avatar = valid_file
252   - @dummy.valid?
253   - end
254   - should "not have an error when assigned a valid file" do
255   - assert ! @dummy.avatar.errors.key?(validation)
256   - end
257   - should "not have an error on the attachment" do
258   - assert_nil @dummy.errors.on(:avatar)
259   - end
260   - end
261   - context "and assigned an invalid file" do
262   - setup do
263   - @dummy.avatar = invalid_file
264   - @dummy.valid?
265   - end
266   - should "have an error when assigned a valid file" do
267   - assert_not_nil @dummy.avatar.errors[validation]
268   - end
269   - should "have an error on the attachment" do
270   - assert @dummy.errors.on(:avatar)
271   - end
272   - end
273   - end
274   - end
275   -
276   - [[:presence, {}, "5k.png", nil],
277   - [:size, {:in => 1..10240}, nil, "12k.png"],
278   - [:size, {:less_than => 10240}, "5k.png", "12k.png"],
279   - [:size, {:greater_than => 8096}, "12k.png", "5k.png"],
280   - [:content_type, {:content_type => "image/png"}, "5k.png", "text.txt"],
281   - [:content_type, {:content_type => "text/plain"}, "text.txt", "5k.png"],
282   - [:content_type, {:content_type => %r{image/.*}}, "5k.png", "text.txt"]].each do |args|
283   - validation, options, valid_file, invalid_file = args
284   - valid_file &&= File.open(File.join(FIXTURES_DIR, valid_file), "rb")
285   - invalid_file &&= File.open(File.join(FIXTURES_DIR, invalid_file), "rb")
286   -
287   - should_validate validation, options, valid_file, invalid_file
288   - end
289   -
290   - end
291   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/processor_test.rb
... ... @@ -1,10 +0,0 @@
1   -require 'test/helper'
2   -
3   -class ProcessorTest < Test::Unit::TestCase
4   - should "instantiate and call #make when sent #make to the class" do
5   - processor = mock
6   - processor.expects(:make).with()
7   - Paperclip::Processor.expects(:new).with(:one, :two, :three).returns(processor)
8   - Paperclip::Processor.make(:one, :two, :three)
9   - end
10   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/storage_test.rb
... ... @@ -1,282 +0,0 @@
1   -require 'test/helper'
2   -
3   -class StorageTest < Test::Unit::TestCase
4   - context "Parsing S3 credentials" do
5   - setup do
6   - rebuild_model :storage => :s3,
7   - :bucket => "testing",
8   - :s3_credentials => {:not => :important}
9   -
10   - @dummy = Dummy.new
11   - @avatar = @dummy.avatar
12   -
13   - @current_env = RAILS_ENV
14   - end
15   -
16   - teardown do
17   - Object.const_set("RAILS_ENV", @current_env)
18   - end
19   -
20   - should "get the correct credentials when RAILS_ENV is production" do
21   - Object.const_set('RAILS_ENV', "production")
22   - assert_equal({:key => "12345"},
23   - @avatar.parse_credentials('production' => {:key => '12345'},
24   - :development => {:key => "54321"}))
25   - end
26   -
27   - should "get the correct credentials when RAILS_ENV is development" do
28   - Object.const_set('RAILS_ENV', "development")
29   - assert_equal({:key => "54321"},
30   - @avatar.parse_credentials('production' => {:key => '12345'},
31   - :development => {:key => "54321"}))
32   - end
33   -
34   - should "return the argument if the key does not exist" do
35   - Object.const_set('RAILS_ENV', "not really an env")
36   - assert_equal({:test => "12345"}, @avatar.parse_credentials(:test => "12345"))
37   - end
38   - end
39   -
40   - context "" do
41   - setup do
42   - rebuild_model :storage => :s3,
43   - :s3_credentials => {},
44   - :bucket => "bucket",
45   - :path => ":attachment/:basename.:extension",
46   - :url => ":s3_path_url"
47   - @dummy = Dummy.new
48   - @dummy.avatar = StringIO.new(".")
49   - end
50   -
51   - should "return a url based on an S3 path" do
52   - assert_match %r{^http://s3.amazonaws.com/bucket/avatars/stringio.txt}, @dummy.avatar.url
53   - end
54   - end
55   - context "" do
56   - setup do
57   - rebuild_model :storage => :s3,
58   - :s3_credentials => {},
59   - :bucket => "bucket",
60   - :path => ":attachment/:basename.:extension",
61   - :url => ":s3_domain_url"
62   - @dummy = Dummy.new
63   - @dummy.avatar = StringIO.new(".")
64   - end
65   -
66   - should "return a url based on an S3 subdomain" do
67   - assert_match %r{^http://bucket.s3.amazonaws.com/avatars/stringio.txt}, @dummy.avatar.url
68   - end
69   - end
70   - context "" do
71   - setup do
72   - rebuild_model :storage => :s3,
73   - :s3_credentials => {
74   - :production => { :bucket => "prod_bucket" },
75   - :development => { :bucket => "dev_bucket" }
76   - },
77   - :s3_host_alias => "something.something.com",
78   - :path => ":attachment/:basename.:extension",
79   - :url => ":s3_alias_url"
80   - @dummy = Dummy.new
81   - @dummy.avatar = StringIO.new(".")
82   - end
83   -
84   - should "return a url based on the host_alias" do
85   - assert_match %r{^http://something.something.com/avatars/stringio.txt}, @dummy.avatar.url
86   - end
87   - end
88   -
89   - context "Parsing S3 credentials with a bucket in them" do
90   - setup do
91   - rebuild_model :storage => :s3,
92   - :s3_credentials => {
93   - :production => { :bucket => "prod_bucket" },
94   - :development => { :bucket => "dev_bucket" }
95   - }
96   - @dummy = Dummy.new
97   - @old_env = RAILS_ENV
98   - end
99   -
100   - teardown{ Object.const_set("RAILS_ENV", @old_env) }
101   -
102   - should "get the right bucket in production" do
103   - Object.const_set("RAILS_ENV", "production")
104   - assert_equal "prod_bucket", @dummy.avatar.bucket_name
105   - end
106   -
107   - should "get the right bucket in development" do
108   - Object.const_set("RAILS_ENV", "development")
109   - assert_equal "dev_bucket", @dummy.avatar.bucket_name
110   - end
111   - end
112   -
113   - context "An attachment with S3 storage" do
114   - setup do
115   - rebuild_model :storage => :s3,
116   - :bucket => "testing",
117   - :path => ":attachment/:style/:basename.:extension",
118   - :s3_credentials => {
119   - 'access_key_id' => "12345",
120   - 'secret_access_key' => "54321"
121   - }
122   - end
123   -
124   - should "be extended by the S3 module" do
125   - assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
126   - end
127   -
128   - should "not be extended by the Filesystem module" do
129   - assert ! Dummy.new.avatar.is_a?(Paperclip::Storage::Filesystem)
130   - end
131   -
132   - context "when assigned" do
133   - setup do
134   - @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
135   - @dummy = Dummy.new
136   - @dummy.avatar = @file
137   - end
138   -
139   - teardown { @file.close }
140   -
141   - should "not get a bucket to get a URL" do
142   - @dummy.avatar.expects(:s3).never
143   - @dummy.avatar.expects(:s3_bucket).never
144   - assert_match %r{^http://s3\.amazonaws\.com/testing/avatars/original/5k\.png}, @dummy.avatar.url
145   - end
146   -
147   - context "and saved" do
148   - setup do
149   - @s3_mock = stub
150   - @bucket_mock = stub
151   - RightAws::S3.expects(:new).with("12345", "54321", {}).returns(@s3_mock)
152   - @s3_mock.expects(:bucket).with("testing", true, "public-read").returns(@bucket_mock)
153   - @key_mock = stub
154   - @bucket_mock.expects(:key).returns(@key_mock)
155   - @key_mock.expects(:data=)
156   - @key_mock.expects(:put).with(nil, 'public-read', 'Content-type' => 'image/png')
157   - @dummy.save
158   - end
159   -
160   - should "succeed" do
161   - assert true
162   - end
163   - end
164   -
165   - context "and remove" do
166   - setup do
167   - @s3_mock = stub
168   - @bucket_mock = stub
169   - RightAws::S3.expects(:new).with("12345", "54321", {}).returns(@s3_mock)
170   - @s3_mock.expects(:bucket).with("testing", true, "public-read").returns(@bucket_mock)
171   - @key_mock = stub
172   - @bucket_mock.expects(:key).at_least(2).returns(@key_mock)
173   - @key_mock.expects(:delete)
174   - @dummy.destroy_attached_files
175   - end
176   -
177   - should "succeed" do
178   - assert true
179   - end
180   - end
181   - end
182   - end
183   -
184   - context "An attachment with S3 storage and bucket defined as a Proc" do
185   - setup do
186   - rebuild_model :storage => :s3,
187   - :bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
188   - :s3_credentials => {:not => :important}
189   - end
190   -
191   - should "get the right bucket name" do
192   - assert "bucket_a", Dummy.new(:other => 'a').avatar.bucket_name
193   - assert "bucket_b", Dummy.new(:other => 'b').avatar.bucket_name
194   - end
195   - end
196   -
197   - context "An attachment with S3 storage and specific s3 headers set" do
198   - setup do
199   - rebuild_model :storage => :s3,
200   - :bucket => "testing",
201   - :path => ":attachment/:style/:basename.:extension",
202   - :s3_credentials => {
203   - 'access_key_id' => "12345",
204   - 'secret_access_key' => "54321"
205   - },
206   - :s3_headers => {'Cache-Control' => 'max-age=31557600'}
207   - end
208   -
209   - context "when assigned" do
210   - setup do
211   - @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
212   - @dummy = Dummy.new
213   - @dummy.avatar = @file
214   - end
215   -
216   - teardown { @file.close }
217   -
218   - context "and saved" do
219   - setup do
220   - @s3_mock = stub
221   - @bucket_mock = stub
222   - RightAws::S3.expects(:new).with("12345", "54321", {}).returns(@s3_mock)
223   - @s3_mock.expects(:bucket).with("testing", true, "public-read").returns(@bucket_mock)
224   - @key_mock = stub
225   - @bucket_mock.expects(:key).returns(@key_mock)
226   - @key_mock.expects(:data=)
227   - @key_mock.expects(:put).with(nil,
228   - 'public-read',
229   - 'Content-type' => 'image/png',
230   - 'Cache-Control' => 'max-age=31557600')
231   - @dummy.save
232   - end
233   -
234   - should "succeed" do
235   - assert true
236   - end
237   - end
238   - end
239   - end
240   -
241   - unless ENV["S3_TEST_BUCKET"].blank?
242   - context "Using S3 for real, an attachment with S3 storage" do
243   - setup do
244   - rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
245   - :storage => :s3,
246   - :bucket => ENV["S3_TEST_BUCKET"],
247   - :path => ":class/:attachment/:id/:style.:extension",
248   - :s3_credentials => File.new(File.join(File.dirname(__FILE__), "s3.yml"))
249   -
250   - Dummy.delete_all
251   - @dummy = Dummy.new
252   - end
253   -
254   - should "be extended by the S3 module" do
255   - assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
256   - end
257   -
258   - context "when assigned" do
259   - setup do
260   - @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
261   - @dummy.avatar = @file
262   - end
263   -
264   - teardown { @file.close }
265   -
266   - should "still return a Tempfile when sent #to_io" do
267   - assert_equal Tempfile, @dummy.avatar.to_io.class
268   - end
269   -
270   - context "and saved" do
271   - setup do
272   - @dummy.save
273   - end
274   -
275   - should "be on S3" do
276   - assert true
277   - end
278   - end
279   - end
280   - end
281   - end
282   -end
vendor/gems/thoughtbot-paperclip-2.2.9.2/test/thumbnail_test.rb
... ... @@ -1,177 +0,0 @@
1   -require 'test/helper'
2   -
3   -class ThumbnailTest < Test::Unit::TestCase
4   -
5   - context "A Paperclip Tempfile" do
6   - setup do
7   - @tempfile = Paperclip::Tempfile.new("file.jpg")
8   - end
9   -
10   - should "have its path contain a real extension" do
11   - assert_equal ".jpg", File.extname(@tempfile.path)
12   - end
13   -
14   - should "be a real Tempfile" do
15   - assert @tempfile.is_a?(::Tempfile)
16   - end
17   - end
18   -
19   - context "Another Paperclip Tempfile" do
20   - setup do
21   - @tempfile = Paperclip::Tempfile.new("file")
22   - end
23   -
24   - should "not have an extension if not given one" do
25   - assert_equal "", File.extname(@tempfile.path)
26   - end
27   -
28   - should "still be a real Tempfile" do
29   - assert @tempfile.is_a?(::Tempfile)
30   - end
31   - end
32   -
33   - context "An image" do
34   - setup do
35   - @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
36   - end
37   -
38   - teardown { @file.close }
39   -
40   - [["600x600>", "434x66"],
41   - ["400x400>", "400x61"],
42   - ["32x32<", "434x66"]
43   - ].each do |args|
44   - context "being thumbnailed with a geometry of #{args[0]}" do
45   - setup do
46   - @thumb = Paperclip::Thumbnail.new(@file, :geometry => args[0])
47   - end
48   -
49   - should "start with dimensions of 434x66" do
50   - cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
51   - assert_equal "434x66", `#{cmd}`.chomp
52   - end
53   -
54   - should "report the correct target geometry" do
55   - assert_equal args[0], @thumb.target_geometry.to_s
56   - end
57   -
58   - context "when made" do
59   - setup do
60   - @thumb_result = @thumb.make
61   - end
62   -
63   - should "be the size we expect it to be" do
64   - cmd = %Q[identify -format "%wx%h" "#{@thumb_result.path}"]
65   - assert_equal args[1], `#{cmd}`.chomp
66   - end
67   - end
68   - end
69   - end
70   -
71   - context "being thumbnailed at 100x50 with cropping" do
72   - setup do
73   - @thumb = Paperclip::Thumbnail.new(@file, :geometry => "100x50#")
74   - end
75   -
76   - should "report its correct current and target geometries" do
77   - assert_equal "100x50#", @thumb.target_geometry.to_s
78   - assert_equal "434x66", @thumb.current_geometry.to_s
79   - end
80   -
81   - should "report its correct format" do
82   - assert_nil @thumb.format
83   - end
84   -
85   - should "have whiny turned on by default" do
86   - assert @thumb.whiny
87   - end
88   -
89   - should "have convert_options set to nil by default" do
90   - assert_equal nil, @thumb.convert_options
91   - end
92   -
93   - should "send the right command to convert when sent #make" do
94   - Paperclip.expects(:"`").with do |arg|
95   - arg.match %r{convert\s+"#{File.expand_path(@thumb.file.path)}\[0\]"\s+-resize\s+\"x50\"\s+-crop\s+\"100x50\+114\+0\"\s+\+repage\s+".*?"}
96   - end
97   - @thumb.make
98   - end
99   -
100   - should "create the thumbnail when sent #make" do
101   - dst = @thumb.make
102   - assert_match /100x50/, `identify "#{dst.path}"`
103   - end
104   - end
105   -
106   - context "being thumbnailed with convert options set" do
107   - setup do
108   - @thumb = Paperclip::Thumbnail.new(@file,
109   - :geometry => "100x50#",
110   - :convert_options => "-strip -depth 8")
111   - end
112   -
113   - should "have convert_options value set" do
114   - assert_equal "-strip -depth 8", @thumb.convert_options
115   - end
116   -
117   - should "send the right command to convert when sent #make" do
118   - Paperclip.expects(:"`").with do |arg|
119   - arg.match %r{convert\s+"#{File.expand_path(@thumb.file.path)}\[0\]"\s+-resize\s+"x50"\s+-crop\s+"100x50\+114\+0"\s+\+repage\s+-strip\s+-depth\s+8\s+".*?"}
120   - end
121   - @thumb.make
122   - end
123   -
124   - should "create the thumbnail when sent #make" do
125   - dst = @thumb.make
126   - assert_match /100x50/, `identify "#{dst.path}"`
127   - end
128   -
129   - context "redefined to have bad convert_options setting" do
130   - setup do
131   - @thumb = Paperclip::Thumbnail.new(@file,
132   - :geometry => "100x50#",
133   - :convert_options => "-this-aint-no-option")
134   - end
135   -
136   - should "error when trying to create the thumbnail" do
137   - assert_raises(Paperclip::PaperclipError) do
138   - @thumb.make
139   - end
140   - end
141   - end
142   - end
143   - end
144   -
145   - context "A multipage PDF" do
146   - setup do
147   - @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "twopage.pdf"), 'rb')
148   - end
149   -
150   - teardown { @file.close }
151   -
152   - should "start with two pages with dimensions 612x792" do
153   - cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
154   - assert_equal "612x792"*2, `#{cmd}`.chomp
155   - end
156   -
157   - context "being thumbnailed at 100x100 with cropping" do
158   - setup do
159   - @thumb = Paperclip::Thumbnail.new(@file, :geometry => "100x100#", :format => :png)
160   - end
161   -
162   - should "report its correct current and target geometries" do
163   - assert_equal "100x100#", @thumb.target_geometry.to_s
164   - assert_equal "612x792", @thumb.current_geometry.to_s
165   - end
166   -
167   - should "report its correct format" do
168   - assert_equal :png, @thumb.format
169   - end
170   -
171   - should "create the thumbnail when sent #make" do
172   - dst = @thumb.make
173   - assert_match /100x100/, `identify "#{dst.path}"`
174   - end
175   - end
176   - end
177   -end
vendor/gems/tristandunn-paperclip-2.3.1/.specification 0 → 100644
... ... @@ -0,0 +1,126 @@
  1 +--- !ruby/object:Gem::Specification
  2 +name: tristandunn-paperclip
  3 +version: !ruby/object:Gem::Version
  4 + version: 2.3.1
  5 +platform: ruby
  6 +authors:
  7 +- Jon Yurek
  8 +autorequire:
  9 +bindir: bin
  10 +cert_chain: []
  11 +
  12 +date: 2009-08-06 00:00:00 -04:00
  13 +default_executable:
  14 +dependencies:
  15 +- !ruby/object:Gem::Dependency
  16 + name: thoughtbot-shoulda
  17 + type: :development
  18 + version_requirement:
  19 + version_requirements: !ruby/object:Gem::Requirement
  20 + requirements:
  21 + - - ">="
  22 + - !ruby/object:Gem::Version
  23 + version: "0"
  24 + version:
  25 +- !ruby/object:Gem::Dependency
  26 + name: mocha
  27 + type: :development
  28 + version_requirement:
  29 + version_requirements: !ruby/object:Gem::Requirement
  30 + requirements:
  31 + - - ">="
  32 + - !ruby/object:Gem::Version
  33 + version: "0"
  34 + version:
  35 +description:
  36 +email: jyurek@thoughtbot.com
  37 +executables: []
  38 +
  39 +extensions: []
  40 +
  41 +extra_rdoc_files:
  42 +- README.rdoc
  43 +files:
  44 +- README.rdoc
  45 +- LICENSE
  46 +- Rakefile
  47 +- init.rb
  48 +- generators/paperclip
  49 +- generators/paperclip/paperclip_generator.rb
  50 +- generators/paperclip/templates
  51 +- generators/paperclip/templates/paperclip_migration.rb.erb
  52 +- generators/paperclip/USAGE
  53 +- lib/paperclip
  54 +- lib/paperclip/attachment.rb
  55 +- lib/paperclip/callback_compatability.rb
  56 +- lib/paperclip/geometry.rb
  57 +- lib/paperclip/interpolations.rb
  58 +- lib/paperclip/iostream.rb
  59 +- lib/paperclip/matchers
  60 +- lib/paperclip/matchers/have_attached_file_matcher.rb
  61 +- lib/paperclip/matchers/validate_attachment_content_type_matcher.rb
  62 +- lib/paperclip/matchers/validate_attachment_presence_matcher.rb
  63 +- lib/paperclip/matchers/validate_attachment_size_matcher.rb
  64 +- lib/paperclip/matchers.rb
  65 +- lib/paperclip/processor.rb
  66 +- lib/paperclip/storage.rb
  67 +- lib/paperclip/thumbnail.rb
  68 +- lib/paperclip/upfile.rb
  69 +- lib/paperclip.rb
  70 +- tasks/paperclip_tasks.rake
  71 +- test/attachment_test.rb
  72 +- test/database.yml
  73 +- test/fixtures
  74 +- test/fixtures/12k.png
  75 +- test/fixtures/50x50.png
  76 +- test/fixtures/5k.png
  77 +- test/fixtures/bad.png
  78 +- test/fixtures/s3.yml
  79 +- test/fixtures/text.txt
  80 +- test/fixtures/twopage.pdf
  81 +- test/geometry_test.rb
  82 +- test/helper.rb
  83 +- test/integration_test.rb
  84 +- test/interpolations_test.rb
  85 +- test/iostream_test.rb
  86 +- test/matchers
  87 +- test/matchers/have_attached_file_matcher_test.rb
  88 +- test/matchers/validate_attachment_content_type_matcher_test.rb
  89 +- test/matchers/validate_attachment_presence_matcher_test.rb
  90 +- test/matchers/validate_attachment_size_matcher_test.rb
  91 +- test/paperclip_test.rb
  92 +- test/processor_test.rb
  93 +- test/storage_test.rb
  94 +- test/thumbnail_test.rb
  95 +- shoulda_macros/paperclip.rb
  96 +has_rdoc: true
  97 +homepage: http://www.thoughtbot.com/projects/paperclip
  98 +licenses: []
  99 +
  100 +post_install_message:
  101 +rdoc_options:
  102 +- --line-numbers
  103 +- --inline-source
  104 +require_paths:
  105 +- lib
  106 +required_ruby_version: !ruby/object:Gem::Requirement
  107 + requirements:
  108 + - - ">="
  109 + - !ruby/object:Gem::Version
  110 + version: "0"
  111 + version:
  112 +required_rubygems_version: !ruby/object:Gem::Requirement
  113 + requirements:
  114 + - - ">="
  115 + - !ruby/object:Gem::Version
  116 + version: "0"
  117 + version:
  118 +requirements:
  119 +- ImageMagick
  120 +rubyforge_project: paperclip
  121 +rubygems_version: 1.3.4
  122 +signing_key:
  123 +specification_version: 3
  124 +summary: File attachments as attributes for ActiveRecord
  125 +test_files: []
  126 +
... ...
vendor/gems/tristandunn-paperclip-2.3.1/LICENSE 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +
  2 +LICENSE
  3 +
  4 +The MIT License
  5 +
  6 +Copyright (c) 2008 Jon Yurek and thoughtbot, inc.
  7 +
  8 +Permission is hereby granted, free of charge, to any person obtaining a copy
  9 +of this software and associated documentation files (the "Software"), to deal
  10 +in the Software without restriction, including without limitation the rights
  11 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12 +copies of the Software, and to permit persons to whom the Software is
  13 +furnished to do so, subject to the following conditions:
  14 +
  15 +The above copyright notice and this permission notice shall be included in
  16 +all copies or substantial portions of the Software.
  17 +
  18 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24 +THE SOFTWARE.
  25 +
  26 +
... ...
vendor/gems/tristandunn-paperclip-2.3.1/README.rdoc 0 → 100644
... ... @@ -0,0 +1,174 @@
  1 +=Paperclip
  2 +
  3 +Paperclip is intended as an easy file attachment library for ActiveRecord. The
  4 +intent behind it was to keep setup as easy as possible and to treat files as
  5 +much like other attributes as possible. This means they aren't saved to their
  6 +final locations on disk, nor are they deleted if set to nil, until
  7 +ActiveRecord::Base#save is called. It manages validations based on size and
  8 +presence, if required. It can transform its assigned image into thumbnails if
  9 +needed, and the prerequisites are as simple as installing ImageMagick (which,
  10 +for most modern Unix-based systems, is as easy as installing the right
  11 +packages). Attached files are saved to the filesystem and referenced in the
  12 +browser by an easily understandable specification, which has sensible and
  13 +useful defaults.
  14 +
  15 +See the documentation for +has_attached_file+ in Paperclip::ClassMethods for
  16 +more detailed options.
  17 +
  18 +==Quick Start
  19 +
  20 +In your model:
  21 +
  22 + class User < ActiveRecord::Base
  23 + has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }
  24 + end
  25 +
  26 +In your migrations:
  27 +
  28 + class AddAvatarColumnsToUser < ActiveRecord::Migration
  29 + def self.up
  30 + add_column :users, :avatar_file_name, :string
  31 + add_column :users, :avatar_content_type, :string
  32 + add_column :users, :avatar_file_size, :integer
  33 + add_column :users, :avatar_updated_at, :datetime
  34 + end
  35 +
  36 + def self.down
  37 + remove_column :users, :avatar_file_name
  38 + remove_column :users, :avatar_content_type
  39 + remove_column :users, :avatar_file_size
  40 + remove_column :users, :avatar_updated_at
  41 + end
  42 + end
  43 +
  44 +In your edit and new views:
  45 +
  46 + <% form_for :user, @user, :url => user_path, :html => { :multipart => true } do |form| %>
  47 + <%= form.file_field :avatar %>
  48 + <% end %>
  49 +
  50 +In your controller:
  51 +
  52 + def create
  53 + @user = User.create( params[:user] )
  54 + end
  55 +
  56 +In your show view:
  57 +
  58 + <%= image_tag @user.avatar.url %>
  59 + <%= image_tag @user.avatar.url(:medium) %>
  60 + <%= image_tag @user.avatar.url(:thumb) %>
  61 +
  62 +==Usage
  63 +
  64 +The basics of paperclip are quite simple: Declare that your model has an
  65 +attachment with the has_attached_file method, and give it a name. Paperclip
  66 +will wrap up up to four attributes (all prefixed with that attachment's name,
  67 +so you can have multiple attachments per model if you wish) and give the a
  68 +friendly front end. The attributes are <attachment>_file_name,
  69 +<attachment>_file_size, <attachment>_content_type, and <attachment>_updated_at.
  70 +Only <attachment>_file_name is required for paperclip to operate. More
  71 +information about the options to has_attached_file is available in the
  72 +documentation of Paperclip::ClassMethods.
  73 +
  74 +Attachments can be validated with Paperclip's validation methods,
  75 +validates_attachment_presence, validates_attachment_content_type, and
  76 +validates_attachment_size.
  77 +
  78 +==Storage
  79 +
  80 +The files that are assigned as attachments are, by default, placed in the
  81 +directory specified by the :path option to has_attached_file. By default, this
  82 +location is ":rails_root/public/system/:attachment/:id/:style/:filename". This
  83 +location was chosen because on standard Capistrano deployments, the
  84 +public/system directory is symlinked to the app's shared directory, meaning it
  85 +will survive between deployments. For example, using that :path, you may have a
  86 +file at
  87 +
  88 + /data/myapp/releases/20081229172410/public/system/avatars/13/small/my_pic.png
  89 +
  90 +NOTE: This is a change from previous versions of Paperclip, but is overall a
  91 +safer choice for the default file store.
  92 +
  93 +You may also choose to store your files using Amazon's S3 service. You can find
  94 +more information about S3 storage at the description for
  95 +Paperclip::Storage::S3.
  96 +
  97 +Files on the local filesystem (and in the Rails app's public directory) will be
  98 +available to the internet at large. If you require access control, it's
  99 +possible to place your files in a different location. You will need to change
  100 +both the :path and :url options in order to make sure the files are unavailable
  101 +to the public. Both :path and :url allow the same set of interpolated
  102 +variables.
  103 +
  104 +==Post Processing
  105 +
  106 +Paperclip supports an extensible selection of post-processors. When you define
  107 +a set of styles for an attachment, by default it is expected that those
  108 +"styles" are actually "thumbnails". However, you can do much more than just
  109 +thumbnail images. By defining a subclass of Paperclip::Processor, you can
  110 +perform any processing you want on the files that are attached. Any file in
  111 +your Rails app's lib/paperclip_processors directory is automatically loaded by
  112 +paperclip, allowing you to easily define custom processors. You can specify a
  113 +processor with the :processors option to has_attached_file:
  114 +
  115 + has_attached_file :scan, :styles => { :text => { :quality => :better } },
  116 + :processors => [:ocr]
  117 +
  118 +This would load the hypothetical class Paperclip::Ocr, which would have the
  119 +hash "{ :quality => :better }" passed to it along with the uploaded file. For
  120 +more information about defining processors, see Paperclip::Processor.
  121 +
  122 +The default processor is Paperclip::Thumbnail. For backwards compatability
  123 +reasons, you can pass a single geometry string or an array containing a
  124 +geometry and a format, which the file will be converted to, like so:
  125 +
  126 + has_attached_file :avatar, :styles => { :thumb => ["32x32#", :png] }
  127 +
  128 +This will convert the "thumb" style to a 32x32 square in png format, regardless
  129 +of what was uploaded. If the format is not specified, it is kept the same (i.e.
  130 +jpgs will remain jpgs).
  131 +
  132 +Multiple processors can be specified, and they will be invoked in the order
  133 +they are defined in the :processors array. Each successive processor will
  134 +be given the result of the previous processor's execution. All processors will
  135 +receive the same parameters, which are what you define in the :styles hash.
  136 +For example, assuming we had this definition:
  137 +
  138 + has_attached_file :scan, :styles => { :text => { :quality => :better } },
  139 + :processors => [:rotator, :ocr]
  140 +
  141 +then both the :rotator processor and the :ocr processor would receive the
  142 +options "{ :quality => :better }". This parameter may not mean anything to one
  143 +or more or the processors, and they are expected to ignore it.
  144 +
  145 +NOTE: Because processors operate by turning the original attachment into the
  146 +styles, no processors will be run if there are no styles defined.
  147 +
  148 +==Events
  149 +
  150 +Before and after the Post Processing step, Paperclip calls back to the model
  151 +with a few callbacks, allowing the model to change or cancel the processing
  152 +step. The callbacks are "before_post_process" and "after_post_process" (which
  153 +are called before and after the processing of each attachment), and the
  154 +attachment-specific "before_<attachment>_post_process" and
  155 +"after_<attachment>_post_process". The callbacks are intended to be as close to
  156 +normal ActiveRecord callbacks as possible, so if you return false (specifically
  157 +- returning nil is not the same) in a before_ filter, the post processing step
  158 +will halt. Returning false in an after_ filter will not halt anything, but you
  159 +can access the model and the attachment if necessary.
  160 +
  161 +NOTE: Post processing will not even *start* if the attachment is not valid
  162 +according to the validations. Your callbacks and processors will *only* be
  163 +called with valid attachments.
  164 +
  165 +==Contributing
  166 +
  167 +If you'd like to contribute a feature or bugfix: Thanks! To make sure your
  168 +fix/feature has a high chance of being included, please read the following
  169 +guidelines:
  170 +
  171 +1. Ask on the mailing list, or post a new GitHub Issue.
  172 +2. Make sure there are tests! We will not accept any patch that is not tested.
  173 + It's a rare time when explicit tests aren't needed. If you have questions
  174 + about writing tests for paperclip, please ask the mailing list.
... ...
vendor/gems/tristandunn-paperclip-2.3.1/Rakefile 0 → 100644
... ... @@ -0,0 +1,99 @@
  1 +require 'rake'
  2 +require 'rake/testtask'
  3 +require 'rake/rdoctask'
  4 +
  5 +$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
  6 +require 'paperclip'
  7 +
  8 +desc 'Default: run unit tests.'
  9 +task :default => [:clean, :test]
  10 +
  11 +desc 'Test the paperclip plugin.'
  12 +Rake::TestTask.new(:test) do |t|
  13 + t.libs << 'lib' << 'profile'
  14 + t.pattern = 'test/**/*_test.rb'
  15 + t.verbose = true
  16 +end
  17 +
  18 +desc 'Start an IRB session with all necessary files required.'
  19 +task :shell do |t|
  20 + chdir File.dirname(__FILE__)
  21 + exec 'irb -I lib/ -I lib/paperclip -r rubygems -r active_record -r tempfile -r init'
  22 +end
  23 +
  24 +desc 'Generate documentation for the paperclip plugin.'
  25 +Rake::RDocTask.new(:rdoc) do |rdoc|
  26 + rdoc.rdoc_dir = 'doc'
  27 + rdoc.title = 'Paperclip'
  28 + rdoc.options << '--line-numbers' << '--inline-source'
  29 + rdoc.rdoc_files.include('README*')
  30 + rdoc.rdoc_files.include('lib/**/*.rb')
  31 +end
  32 +
  33 +desc 'Update documentation on website'
  34 +task :sync_docs => 'rdoc' do
  35 + `rsync -ave ssh doc/ dev@dev.thoughtbot.com:/home/dev/www/dev.thoughtbot.com/paperclip`
  36 +end
  37 +
  38 +desc 'Clean up files.'
  39 +task :clean do |t|
  40 + FileUtils.rm_rf "doc"
  41 + FileUtils.rm_rf "tmp"
  42 + FileUtils.rm_rf "pkg"
  43 + FileUtils.rm "test/debug.log" rescue nil
  44 + FileUtils.rm "test/paperclip.db" rescue nil
  45 + Dir.glob("paperclip-*.gem").each{|f| FileUtils.rm f }
  46 +end
  47 +
  48 +include_file_globs = ["README*",
  49 + "LICENSE",
  50 + "Rakefile",
  51 + "init.rb",
  52 + "{generators,lib,tasks,test,shoulda_macros}/**/*"]
  53 +exclude_file_globs = ["test/s3.yml",
  54 + "test/debug.log",
  55 + "test/paperclip.db",
  56 + "test/doc",
  57 + "test/doc/*",
  58 + "test/pkg",
  59 + "test/pkg/*",
  60 + "test/tmp",
  61 + "test/tmp/*"]
  62 +spec = Gem::Specification.new do |s|
  63 + s.name = "paperclip"
  64 + s.version = Paperclip::VERSION
  65 + s.author = "Jon Yurek"
  66 + s.email = "jyurek@thoughtbot.com"
  67 + s.homepage = "http://www.thoughtbot.com/projects/paperclip"
  68 + s.platform = Gem::Platform::RUBY
  69 + s.summary = "File attachments as attributes for ActiveRecord"
  70 + s.files = FileList[include_file_globs].to_a - FileList[exclude_file_globs].to_a
  71 + s.require_path = "lib"
  72 + s.test_files = FileList["test/**/test_*.rb"].to_a
  73 + s.rubyforge_project = "paperclip"
  74 + s.has_rdoc = true
  75 + s.extra_rdoc_files = FileList["README*"].to_a
  76 + s.rdoc_options << '--line-numbers' << '--inline-source'
  77 + s.requirements << "ImageMagick"
  78 + s.add_development_dependency 'thoughtbot-shoulda'
  79 + s.add_development_dependency 'mocha'
  80 +end
  81 +
  82 +desc "Print a list of the files to be put into the gem"
  83 +task :manifest => :clean do
  84 + spec.files.each do |file|
  85 + puts file
  86 + end
  87 +end
  88 +
  89 +desc "Generate a gemspec file for GitHub"
  90 +task :gemspec => :clean do
  91 + File.open("#{spec.name}.gemspec", 'w') do |f|
  92 + f.write spec.to_ruby
  93 + end
  94 +end
  95 +
  96 +desc "Build the gem into the current directory"
  97 +task :gem => :gemspec do
  98 + `gem build #{spec.name}.gemspec`
  99 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/generators/paperclip/USAGE 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +Usage:
  2 +
  3 + script/generate paperclip Class attachment1 (attachment2 ...)
  4 +
  5 +This will create a migration that will add the proper columns to your class's table.
0 6 \ No newline at end of file
... ...
vendor/gems/tristandunn-paperclip-2.3.1/generators/paperclip/paperclip_generator.rb 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +class PaperclipGenerator < Rails::Generator::NamedBase
  2 + attr_accessor :attachments, :migration_name
  3 +
  4 + def initialize(args, options = {})
  5 + super
  6 + @class_name, @attachments = args[0], args[1..-1]
  7 + end
  8 +
  9 + def manifest
  10 + file_name = generate_file_name
  11 + @migration_name = file_name.camelize
  12 + record do |m|
  13 + m.migration_template "paperclip_migration.rb.erb",
  14 + File.join('db', 'migrate'),
  15 + :migration_file_name => file_name
  16 + end
  17 + end
  18 +
  19 + private
  20 +
  21 + def generate_file_name
  22 + names = attachments.map{|a| a.underscore }
  23 + names = names[0..-2] + ["and", names[-1]] if names.length > 1
  24 + "add_attachments_#{names.join("_")}_to_#{@class_name.underscore}"
  25 + end
  26 +
  27 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/generators/paperclip/templates/paperclip_migration.rb.erb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +class <%= migration_name %> < ActiveRecord::Migration
  2 + def self.up
  3 +<% attachments.each do |attachment| -%>
  4 + add_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_file_name, :string
  5 + add_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_content_type, :string
  6 + add_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_file_size, :integer
  7 + add_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_updated_at, :datetime
  8 +<% end -%>
  9 + end
  10 +
  11 + def self.down
  12 +<% attachments.each do |attachment| -%>
  13 + remove_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_file_name
  14 + remove_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_content_type
  15 + remove_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_file_size
  16 + remove_column :<%= class_name.underscore.camelize.tableize %>, :<%= attachment %>_updated_at
  17 +<% end -%>
  18 + end
  19 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/init.rb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +require File.join(File.dirname(__FILE__), "lib", "paperclip")
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip.rb 0 → 100644
... ... @@ -0,0 +1,350 @@
  1 +# Paperclip allows file attachments that are stored in the filesystem. All graphical
  2 +# transformations are done using the Graphics/ImageMagick command line utilities and
  3 +# are stored in Tempfiles until the record is saved. Paperclip does not require a
  4 +# separate model for storing the attachment's information, instead adding a few simple
  5 +# columns to your table.
  6 +#
  7 +# Author:: Jon Yurek
  8 +# Copyright:: Copyright (c) 2008-2009 thoughtbot, inc.
  9 +# License:: MIT License (http://www.opensource.org/licenses/mit-license.php)
  10 +#
  11 +# Paperclip defines an attachment as any file, though it makes special considerations
  12 +# for image files. You can declare that a model has an attached file with the
  13 +# +has_attached_file+ method:
  14 +#
  15 +# class User < ActiveRecord::Base
  16 +# has_attached_file :avatar, :styles => { :thumb => "100x100" }
  17 +# end
  18 +#
  19 +# user = User.new
  20 +# user.avatar = params[:user][:avatar]
  21 +# user.avatar.url
  22 +# # => "/users/avatars/4/original_me.jpg"
  23 +# user.avatar.url(:thumb)
  24 +# # => "/users/avatars/4/thumb_me.jpg"
  25 +#
  26 +# See the +has_attached_file+ documentation for more details.
  27 +
  28 +require 'tempfile'
  29 +require 'paperclip/upfile'
  30 +require 'paperclip/iostream'
  31 +require 'paperclip/geometry'
  32 +require 'paperclip/processor'
  33 +require 'paperclip/thumbnail'
  34 +require 'paperclip/storage'
  35 +require 'paperclip/interpolations'
  36 +require 'paperclip/attachment'
  37 +if defined? RAILS_ROOT
  38 + Dir.glob(File.join(File.expand_path(RAILS_ROOT), "lib", "paperclip_processors", "*.rb")).each do |processor|
  39 + require processor
  40 + end
  41 +end
  42 +
  43 +# The base module that gets included in ActiveRecord::Base. See the
  44 +# documentation for Paperclip::ClassMethods for more useful information.
  45 +module Paperclip
  46 +
  47 + VERSION = "2.3.1"
  48 +
  49 + class << self
  50 + # Provides configurability to Paperclip. There are a number of options available, such as:
  51 + # * whiny: Will raise an error if Paperclip cannot process thumbnails of
  52 + # an uploaded image. Defaults to true.
  53 + # * log: Logs progress to the Rails log. Uses ActiveRecord's logger, so honors
  54 + # log levels, etc. Defaults to true.
  55 + # * command_path: Defines the path at which to find the command line
  56 + # programs if they are not visible to Rails the system's search path. Defaults to
  57 + # nil, which uses the first executable found in the user's search path.
  58 + # * image_magick_path: Deprecated alias of command_path.
  59 + def options
  60 + @options ||= {
  61 + :whiny => true,
  62 + :image_magick_path => nil,
  63 + :command_path => nil,
  64 + :log => true,
  65 + :log_command => false,
  66 + :swallow_stderr => true
  67 + }
  68 + end
  69 +
  70 + def path_for_command command #:nodoc:
  71 + if options[:image_magick_path]
  72 + warn("[DEPRECATION] :image_magick_path is deprecated and will be removed. Use :command_path instead")
  73 + end
  74 + path = [options[:command_path] || options[:image_magick_path], command].compact
  75 + File.join(*path)
  76 + end
  77 +
  78 + def interpolates key, &block
  79 + Paperclip::Interpolations[key] = block
  80 + end
  81 +
  82 + # The run method takes a command to execute and a string of parameters
  83 + # that get passed to it. The command is prefixed with the :command_path
  84 + # option from Paperclip.options. If you have many commands to run and
  85 + # they are in different paths, the suggested course of action is to
  86 + # symlink them so they are all in the same directory.
  87 + #
  88 + # If the command returns with a result code that is not one of the
  89 + # expected_outcodes, a PaperclipCommandLineError will be raised. Generally
  90 + # a code of 0 is expected, but a list of codes may be passed if necessary.
  91 + #
  92 + # This method can log the command being run when
  93 + # Paperclip.options[:log_command] is set to true (defaults to false). This
  94 + # will only log if logging in general is set to true as well.
  95 + def run cmd, params = "", expected_outcodes = 0
  96 + command = %Q[#{path_for_command(cmd)} #{params}].gsub(/\s+/, " ")
  97 + command = "#{command} 2>#{bit_bucket}" if Paperclip.options[:swallow_stderr]
  98 + Paperclip.log(command) if Paperclip.options[:log_command]
  99 + output = `#{command}`
  100 + unless [expected_outcodes].flatten.include?($?.exitstatus)
  101 + raise PaperclipCommandLineError, "Error while running #{cmd}"
  102 + end
  103 + output
  104 + end
  105 +
  106 + def bit_bucket #:nodoc:
  107 + File.exists?("/dev/null") ? "/dev/null" : "NUL"
  108 + end
  109 +
  110 + def included base #:nodoc:
  111 + base.extend ClassMethods
  112 + unless base.respond_to?(:define_callbacks)
  113 + base.send(:include, Paperclip::CallbackCompatability)
  114 + end
  115 + end
  116 +
  117 + def processor name #:nodoc:
  118 + name = name.to_s.camelize
  119 + processor = Paperclip.const_get(name)
  120 + unless processor.ancestors.include?(Paperclip::Processor)
  121 + raise PaperclipError.new("Processor #{name} was not found")
  122 + end
  123 + processor
  124 + end
  125 +
  126 + # Log a paperclip-specific line. Uses ActiveRecord::Base.logger
  127 + # by default. Set Paperclip.options[:log] to false to turn off.
  128 + def log message
  129 + logger.info("[paperclip] #{message}") if logging?
  130 + end
  131 +
  132 + def logger #:nodoc:
  133 + ActiveRecord::Base.logger
  134 + end
  135 +
  136 + def logging? #:nodoc:
  137 + options[:log]
  138 + end
  139 + end
  140 +
  141 + class PaperclipError < StandardError #:nodoc:
  142 + end
  143 +
  144 + class PaperclipCommandLineError < StandardError #:nodoc:
  145 + end
  146 +
  147 + class NotIdentifiedByImageMagickError < PaperclipError #:nodoc:
  148 + end
  149 +
  150 + class InfiniteInterpolationError < PaperclipError #:nodoc:
  151 + end
  152 +
  153 + module ClassMethods
  154 + # +has_attached_file+ gives the class it is called on an attribute that maps to a file. This
  155 + # is typically a file stored somewhere on the filesystem and has been uploaded by a user.
  156 + # The attribute returns a Paperclip::Attachment object which handles the management of
  157 + # that file. The intent is to make the attachment as much like a normal attribute. The
  158 + # thumbnails will be created when the new file is assigned, but they will *not* be saved
  159 + # until +save+ is called on the record. Likewise, if the attribute is set to +nil+ is
  160 + # called on it, the attachment will *not* be deleted until +save+ is called. See the
  161 + # Paperclip::Attachment documentation for more specifics. There are a number of options
  162 + # you can set to change the behavior of a Paperclip attachment:
  163 + # * +url+: The full URL of where the attachment is publically accessible. This can just
  164 + # as easily point to a directory served directly through Apache as it can to an action
  165 + # that can control permissions. You can specify the full domain and path, but usually
  166 + # just an absolute path is sufficient. The leading slash *must* be included manually for
  167 + # absolute paths. The default value is
  168 + # "/system/:attachment/:id/:style/:filename". See
  169 + # Paperclip::Attachment#interpolate for more information on variable interpolaton.
  170 + # :url => "/:class/:attachment/:id/:style_:filename"
  171 + # :url => "http://some.other.host/stuff/:class/:id_:extension"
  172 + # * +default_url+: The URL that will be returned if there is no attachment assigned.
  173 + # This field is interpolated just as the url is. The default value is
  174 + # "/:attachment/:style/missing.png"
  175 + # has_attached_file :avatar, :default_url => "/images/default_:style_avatar.png"
  176 + # User.new.avatar_url(:small) # => "/images/default_small_avatar.png"
  177 + # * +styles+: A hash of thumbnail styles and their geometries. You can find more about
  178 + # geometry strings at the ImageMagick website
  179 + # (http://www.imagemagick.org/script/command-line-options.php#resize). Paperclip
  180 + # also adds the "#" option (e.g. "50x50#"), which will resize the image to fit maximally
  181 + # inside the dimensions and then crop the rest off (weighted at the center). The
  182 + # default value is to generate no thumbnails.
  183 + # * +default_style+: The thumbnail style that will be used by default URLs.
  184 + # Defaults to +original+.
  185 + # has_attached_file :avatar, :styles => { :normal => "100x100#" },
  186 + # :default_style => :normal
  187 + # user.avatar.url # => "/avatars/23/normal_me.png"
  188 + # * +whiny+: Will raise an error if Paperclip cannot post_process an uploaded file due
  189 + # to a command line error. This will override the global setting for this attachment.
  190 + # Defaults to true. This option used to be called :whiny_thumbanils, but this is
  191 + # deprecated.
  192 + # * +convert_options+: When creating thumbnails, use this free-form options
  193 + # field to pass in various convert command options. Typical options are "-strip" to
  194 + # remove all Exif data from the image (save space for thumbnails and avatars) or
  195 + # "-depth 8" to specify the bit depth of the resulting conversion. See ImageMagick
  196 + # convert documentation for more options: (http://www.imagemagick.org/script/convert.php)
  197 + # Note that this option takes a hash of options, each of which correspond to the style
  198 + # of thumbnail being generated. You can also specify :all as a key, which will apply
  199 + # to all of the thumbnails being generated. If you specify options for the :original,
  200 + # it would be best if you did not specify destructive options, as the intent of keeping
  201 + # the original around is to regenerate all the thumbnails when requirements change.
  202 + # has_attached_file :avatar, :styles => { :large => "300x300", :negative => "100x100" }
  203 + # :convert_options => {
  204 + # :all => "-strip",
  205 + # :negative => "-negate"
  206 + # }
  207 + # NOTE: While not deprecated yet, it is not recommended to specify options this way.
  208 + # It is recommended that :convert_options option be included in the hash passed to each
  209 + # :styles for compatability with future versions.
  210 + # * +storage+: Chooses the storage backend where the files will be stored. The current
  211 + # choices are :filesystem and :s3. The default is :filesystem. Make sure you read the
  212 + # documentation for Paperclip::Storage::Filesystem and Paperclip::Storage::S3
  213 + # for backend-specific options.
  214 + def has_attached_file name, options = {}
  215 + include InstanceMethods
  216 +
  217 + write_inheritable_attribute(:attachment_definitions, {}) if attachment_definitions.nil?
  218 + attachment_definitions[name] = {:validations => []}.merge(options)
  219 +
  220 + after_save :save_attached_files
  221 + before_destroy :destroy_attached_files
  222 +
  223 + define_callbacks :before_post_process, :after_post_process
  224 + define_callbacks :"before_#{name}_post_process", :"after_#{name}_post_process"
  225 +
  226 + define_method name do |*args|
  227 + a = attachment_for(name)
  228 + (args.length > 0) ? a.to_s(args.first) : a
  229 + end
  230 +
  231 + define_method "#{name}=" do |file|
  232 + attachment_for(name).assign(file)
  233 + end
  234 +
  235 + define_method "#{name}?" do
  236 + attachment_for(name).file?
  237 + end
  238 +
  239 + validates_each(name) do |record, attr, value|
  240 + attachment = record.attachment_for(name)
  241 + attachment.send(:flush_errors) unless attachment.valid?
  242 + end
  243 + end
  244 +
  245 + # Places ActiveRecord-style validations on the size of the file assigned. The
  246 + # possible options are:
  247 + # * +in+: a Range of bytes (i.e. +1..1.megabyte+),
  248 + # * +less_than+: equivalent to :in => 0..options[:less_than]
  249 + # * +greater_than+: equivalent to :in => options[:greater_than]..Infinity
  250 + # * +message+: error message to display, use :min and :max as replacements
  251 + # * +if+: A lambda or name of a method on the instance. Validation will only
  252 + # be run is this lambda or method returns true.
  253 + # * +unless+: Same as +if+ but validates if lambda or method returns false.
  254 + def validates_attachment_size name, options = {}
  255 + min = options[:greater_than] || (options[:in] && options[:in].first) || 0
  256 + max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
  257 + range = (min..max)
  258 + message = options[:message] || "file size must be between :min and :max bytes."
  259 +
  260 + attachment_definitions[name][:validations] << [:size, {:range => range,
  261 + :message => message,
  262 + :if => options[:if],
  263 + :unless => options[:unless]}]
  264 + end
  265 +
  266 + # Adds errors if thumbnail creation fails. The same as specifying :whiny_thumbnails => true.
  267 + def validates_attachment_thumbnails name, options = {}
  268 + warn('[DEPRECATION] validates_attachment_thumbnail is deprecated. ' +
  269 + 'This validation is on by default and will be removed from future versions. ' +
  270 + 'If you wish to turn it off, supply :whiny => false in your definition.')
  271 + attachment_definitions[name][:whiny_thumbnails] = true
  272 + end
  273 +
  274 + # Places ActiveRecord-style validations on the presence of a file.
  275 + # Options:
  276 + # * +if+: A lambda or name of a method on the instance. Validation will only
  277 + # be run is this lambda or method returns true.
  278 + # * +unless+: Same as +if+ but validates if lambda or method returns false.
  279 + def validates_attachment_presence name, options = {}
  280 + message = options[:message] || "must be set."
  281 + attachment_definitions[name][:validations] << [:presence, {:message => message,
  282 + :if => options[:if],
  283 + :unless => options[:unless]}]
  284 + end
  285 +
  286 + # Places ActiveRecord-style validations on the content type of the file
  287 + # assigned. The possible options are:
  288 + # * +content_type+: Allowed content types. Can be a single content type
  289 + # or an array. Each type can be a String or a Regexp. It should be
  290 + # noted that Internet Explorer upload files with content_types that you
  291 + # may not expect. For example, JPEG images are given image/pjpeg and
  292 + # PNGs are image/x-png, so keep that in mind when determining how you
  293 + # match. Allows all by default.
  294 + # * +message+: The message to display when the uploaded file has an invalid
  295 + # content type.
  296 + # * +if+: A lambda or name of a method on the instance. Validation will only
  297 + # be run is this lambda or method returns true.
  298 + # * +unless+: Same as +if+ but validates if lambda or method returns false.
  299 + # NOTE: If you do not specify an [attachment]_content_type field on your
  300 + # model, content_type validation will work _ONLY upon assignment_ and
  301 + # re-validation after the instance has been reloaded will always succeed.
  302 + def validates_attachment_content_type name, options = {}
  303 + attachment_definitions[name][:validations] << [:content_type, {:content_type => options[:content_type],
  304 + :message => options[:message],
  305 + :if => options[:if],
  306 + :unless => options[:unless]}]
  307 + end
  308 +
  309 + # Returns the attachment definitions defined by each call to
  310 + # has_attached_file.
  311 + def attachment_definitions
  312 + read_inheritable_attribute(:attachment_definitions)
  313 + end
  314 + end
  315 +
  316 + module InstanceMethods #:nodoc:
  317 + def attachment_for name
  318 + @_paperclip_attachments ||= {}
  319 + @_paperclip_attachments[name] ||= Attachment.new(name, self, self.class.attachment_definitions[name])
  320 + end
  321 +
  322 + def each_attachment
  323 + self.class.attachment_definitions.each do |name, definition|
  324 + yield(name, attachment_for(name))
  325 + end
  326 + end
  327 +
  328 + def save_attached_files
  329 + logger.info("[paperclip] Saving attachments.")
  330 + each_attachment do |name, attachment|
  331 + attachment.send(:save)
  332 + end
  333 + end
  334 +
  335 + def destroy_attached_files
  336 + logger.info("[paperclip] Deleting attachments.")
  337 + each_attachment do |name, attachment|
  338 + attachment.send(:queue_existing_for_delete)
  339 + attachment.send(:flush_deletes)
  340 + end
  341 + end
  342 + end
  343 +
  344 +end
  345 +
  346 +# Set it all up.
  347 +if Object.const_defined?("ActiveRecord")
  348 + ActiveRecord::Base.send(:include, Paperclip)
  349 + File.send(:include, Paperclip::Upfile)
  350 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/attachment.rb 0 → 100644
... ... @@ -0,0 +1,414 @@
  1 +# encoding: utf-8
  2 +module Paperclip
  3 + # The Attachment class manages the files for a given attachment. It saves
  4 + # when the model saves, deletes when the model is destroyed, and processes
  5 + # the file upon assignment.
  6 + class Attachment
  7 +
  8 + def self.default_options
  9 + @default_options ||= {
  10 + :url => "/system/:attachment/:id/:style/:filename",
  11 + :path => ":rails_root/public:url",
  12 + :styles => {},
  13 + :default_url => "/:attachment/:style/missing.png",
  14 + :default_style => :original,
  15 + :validations => [],
  16 + :storage => :filesystem,
  17 + :whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails]
  18 + }
  19 + end
  20 +
  21 + attr_reader :name, :instance, :styles, :default_style, :convert_options, :queued_for_write, :options
  22 +
  23 + # Creates an Attachment object. +name+ is the name of the attachment,
  24 + # +instance+ is the ActiveRecord object instance it's attached to, and
  25 + # +options+ is the same as the hash passed to +has_attached_file+.
  26 + def initialize name, instance, options = {}
  27 + @name = name
  28 + @instance = instance
  29 +
  30 + options = self.class.default_options.merge(options)
  31 +
  32 + @url = options[:url]
  33 + @url = @url.call(self) if @url.is_a?(Proc)
  34 + @path = options[:path]
  35 + @path = @path.call(self) if @path.is_a?(Proc)
  36 + @styles = options[:styles]
  37 + @styles = @styles.call(self) if @styles.is_a?(Proc)
  38 + @default_url = options[:default_url]
  39 + @validations = options[:validations]
  40 + @default_style = options[:default_style]
  41 + @storage = options[:storage]
  42 + @whiny = options[:whiny_thumbnails] || options[:whiny]
  43 + @convert_options = options[:convert_options] || {}
  44 + @processors = options[:processors] || [:thumbnail]
  45 + @options = options
  46 + @queued_for_delete = []
  47 + @queued_for_write = {}
  48 + @errors = {}
  49 + @validation_errors = nil
  50 + @dirty = false
  51 +
  52 + normalize_style_definition
  53 + initialize_storage
  54 + end
  55 +
  56 + # What gets called when you call instance.attachment = File. It clears
  57 + # errors, assigns attributes, processes the file, and runs validations. It
  58 + # also queues up the previous file for deletion, to be flushed away on
  59 + # #save of its host. In addition to form uploads, you can also assign
  60 + # another Paperclip attachment:
  61 + # new_user.avatar = old_user.avatar
  62 + # If the file that is assigned is not valid, the processing (i.e.
  63 + # thumbnailing, etc) will NOT be run.
  64 + def assign uploaded_file
  65 + ensure_required_accessors!
  66 +
  67 + if uploaded_file.is_a?(Paperclip::Attachment)
  68 + uploaded_file = uploaded_file.to_file(:original)
  69 + close_uploaded_file = uploaded_file.respond_to?(:close)
  70 + end
  71 +
  72 + return nil unless valid_assignment?(uploaded_file)
  73 +
  74 + uploaded_file.binmode if uploaded_file.respond_to? :binmode
  75 + self.clear
  76 +
  77 + return nil if uploaded_file.nil?
  78 +
  79 + @queued_for_write[:original] = uploaded_file.to_tempfile
  80 + instance_write(:file_name, uploaded_file.original_filename.strip.gsub(/[^A-Za-z\d\.\-_]+/, '_'))
  81 + instance_write(:content_type, uploaded_file.content_type.to_s.strip)
  82 + instance_write(:file_size, uploaded_file.size.to_i)
  83 + instance_write(:updated_at, Time.now)
  84 +
  85 + @dirty = true
  86 +
  87 + post_process if valid?
  88 +
  89 + # Reset the file size if the original file was reprocessed.
  90 + instance_write(:file_size, @queued_for_write[:original].size.to_i)
  91 + ensure
  92 + uploaded_file.close if close_uploaded_file
  93 + validate
  94 + end
  95 +
  96 + # Returns the public URL of the attachment, with a given style. Note that
  97 + # this does not necessarily need to point to a file that your web server
  98 + # can access and can point to an action in your app, if you need fine
  99 + # grained security. This is not recommended if you don't need the
  100 + # security, however, for performance reasons. set
  101 + # include_updated_timestamp to false if you want to stop the attachment
  102 + # update time appended to the url
  103 + def url style = default_style, include_updated_timestamp = true
  104 + url = original_filename.nil? ? interpolate(@default_url, style) : interpolate(@url, style)
  105 + include_updated_timestamp && updated_at ? [url, updated_at].compact.join(url.include?("?") ? "&" : "?") : url
  106 + end
  107 +
  108 + # Returns the path of the attachment as defined by the :path option. If the
  109 + # file is stored in the filesystem the path refers to the path of the file
  110 + # on disk. If the file is stored in S3, the path is the "key" part of the
  111 + # URL, and the :bucket option refers to the S3 bucket.
  112 + def path style = default_style
  113 + original_filename.nil? ? nil : interpolate(@path, style)
  114 + end
  115 +
  116 + # Alias to +url+
  117 + def to_s style = nil
  118 + url(style)
  119 + end
  120 +
  121 + # Returns true if there are no errors on this attachment.
  122 + def valid?
  123 + validate
  124 + errors.empty?
  125 + end
  126 +
  127 + # Returns an array containing the errors on this attachment.
  128 + def errors
  129 + @errors
  130 + end
  131 +
  132 + # Returns true if there are changes that need to be saved.
  133 + def dirty?
  134 + @dirty
  135 + end
  136 +
  137 + # Saves the file, if there are no errors. If there are, it flushes them to
  138 + # the instance's errors and returns false, cancelling the save.
  139 + def save
  140 + if valid?
  141 + flush_deletes
  142 + flush_writes
  143 + @dirty = false
  144 + true
  145 + else
  146 + flush_errors
  147 + false
  148 + end
  149 + end
  150 +
  151 + # Clears out the attachment. Has the same effect as previously assigning
  152 + # nil to the attachment. Does NOT save. If you wish to clear AND save,
  153 + # use #destroy.
  154 + def clear
  155 + queue_existing_for_delete
  156 + @errors = {}
  157 + @validation_errors = nil
  158 + end
  159 +
  160 + # Destroys the attachment. Has the same effect as previously assigning
  161 + # nil to the attachment *and saving*. This is permanent. If you wish to
  162 + # wipe out the existing attachment but not save, use #clear.
  163 + def destroy
  164 + clear
  165 + save
  166 + end
  167 +
  168 + # Returns the name of the file as originally assigned, and lives in the
  169 + # <attachment>_file_name attribute of the model.
  170 + def original_filename
  171 + instance_read(:file_name)
  172 + end
  173 +
  174 + # Returns the size of the file as originally assigned, and lives in the
  175 + # <attachment>_file_size attribute of the model.
  176 + def size
  177 + instance_read(:file_size) || (@queued_for_write[:original] && @queued_for_write[:original].size)
  178 + end
  179 +
  180 + # Returns the content_type of the file as originally assigned, and lives
  181 + # in the <attachment>_content_type attribute of the model.
  182 + def content_type
  183 + instance_read(:content_type)
  184 + end
  185 +
  186 + # Returns the last modified time of the file as originally assigned, and
  187 + # lives in the <attachment>_updated_at attribute of the model.
  188 + def updated_at
  189 + time = instance_read(:updated_at)
  190 + time && time.to_i
  191 + end
  192 +
  193 + # Paths and URLs can have a number of variables interpolated into them
  194 + # to vary the storage location based on name, id, style, class, etc.
  195 + # This method is a deprecated access into supplying and retrieving these
  196 + # interpolations. Future access should use either Paperclip.interpolates
  197 + # or extend the Paperclip::Interpolations module directly.
  198 + def self.interpolations
  199 + warn('[DEPRECATION] Paperclip::Attachment.interpolations is deprecated ' +
  200 + 'and will be removed from future versions. ' +
  201 + 'Use Paperclip.interpolates instead')
  202 + Paperclip::Interpolations
  203 + end
  204 +
  205 + # This method really shouldn't be called that often. It's expected use is
  206 + # in the paperclip:refresh rake task and that's it. It will regenerate all
  207 + # thumbnails forcefully, by reobtaining the original file and going through
  208 + # the post-process again.
  209 + def reprocess!
  210 + new_original = Tempfile.new("paperclip-reprocess")
  211 + new_original.binmode
  212 + if old_original = to_file(:original)
  213 + new_original.write( old_original.read )
  214 + new_original.rewind
  215 +
  216 + @queued_for_write = { :original => new_original }
  217 + post_process
  218 +
  219 + old_original.close if old_original.respond_to?(:close)
  220 +
  221 + save
  222 + else
  223 + true
  224 + end
  225 + end
  226 +
  227 + # Returns true if a file has been assigned.
  228 + def file?
  229 + !original_filename.blank?
  230 + end
  231 +
  232 + # Writes the attachment-specific attribute on the instance. For example,
  233 + # instance_write(:file_name, "me.jpg") will write "me.jpg" to the instance's
  234 + # "avatar_file_name" field (assuming the attachment is called avatar).
  235 + def instance_write(attr, value)
  236 + setter = :"#{name}_#{attr}="
  237 + responds = instance.respond_to?(setter)
  238 + self.instance_variable_set("@_#{setter.to_s.chop}", value)
  239 + instance.send(setter, value) if responds || attr.to_s == "file_name"
  240 + end
  241 +
  242 + # Reads the attachment-specific attribute on the instance. See instance_write
  243 + # for more details.
  244 + def instance_read(attr)
  245 + getter = :"#{name}_#{attr}"
  246 + responds = instance.respond_to?(getter)
  247 + cached = self.instance_variable_get("@_#{getter}")
  248 + return cached if cached
  249 + instance.send(getter) if responds || attr.to_s == "file_name"
  250 + end
  251 +
  252 + private
  253 +
  254 + def ensure_required_accessors! #:nodoc:
  255 + %w(file_name).each do |field|
  256 + unless @instance.respond_to?("#{name}_#{field}") && @instance.respond_to?("#{name}_#{field}=")
  257 + raise PaperclipError.new("#{@instance.class} model missing required attr_accessor for '#{name}_#{field}'")
  258 + end
  259 + end
  260 + end
  261 +
  262 + def log message #:nodoc:
  263 + Paperclip.log(message)
  264 + end
  265 +
  266 + def valid_assignment? file #:nodoc:
  267 + file.nil? || (file.respond_to?(:original_filename) && file.respond_to?(:content_type))
  268 + end
  269 +
  270 + def validate #:nodoc:
  271 + unless @validation_errors
  272 + @validation_errors = @validations.inject({}) do |errors, validation|
  273 + name, options = validation
  274 + errors[name] = send(:"validate_#{name}", options) if allow_validation?(options)
  275 + errors
  276 + end
  277 + @validation_errors.reject!{|k,v| v == nil }
  278 + @errors.merge!(@validation_errors)
  279 + end
  280 + @validation_errors
  281 + end
  282 +
  283 + def allow_validation? options #:nodoc:
  284 + (options[:if].nil? || check_guard(options[:if])) && (options[:unless].nil? || !check_guard(options[:unless]))
  285 + end
  286 +
  287 + def check_guard guard #:nodoc:
  288 + if guard.respond_to? :call
  289 + guard.call(instance)
  290 + elsif ! guard.blank?
  291 + instance.send(guard.to_s)
  292 + end
  293 + end
  294 +
  295 + def validate_size options #:nodoc:
  296 + if file? && !options[:range].include?(size.to_i)
  297 + options[:message].gsub(/:min/, options[:min].to_s).gsub(/:max/, options[:max].to_s)
  298 + end
  299 + end
  300 +
  301 + def validate_presence options #:nodoc:
  302 + options[:message] unless file?
  303 + end
  304 +
  305 + def validate_content_type options #:nodoc:
  306 + valid_types = [options[:content_type]].flatten
  307 + unless original_filename.blank?
  308 + unless valid_types.blank?
  309 + content_type = instance_read(:content_type)
  310 + unless valid_types.any?{|t| content_type.nil? || t === content_type }
  311 + options[:message] || "is not one of the allowed file types."
  312 + end
  313 + end
  314 + end
  315 + end
  316 +
  317 + def normalize_style_definition #:nodoc:
  318 + @styles.each do |name, args|
  319 + unless args.is_a? Hash
  320 + dimensions, format = [args, nil].flatten[0..1]
  321 + format = nil if format.blank?
  322 + @styles[name] = {
  323 + :processors => @processors,
  324 + :geometry => dimensions,
  325 + :format => format,
  326 + :whiny => @whiny,
  327 + :convert_options => extra_options_for(name)
  328 + }
  329 + else
  330 + @styles[name] = {
  331 + :processors => @processors,
  332 + :whiny => @whiny,
  333 + :convert_options => extra_options_for(name)
  334 + }.merge(@styles[name])
  335 + end
  336 + end
  337 + end
  338 +
  339 + def solidify_style_definitions #:nodoc:
  340 + @styles.each do |name, args|
  341 + @styles[name][:geometry] = @styles[name][:geometry].call(instance) if @styles[name][:geometry].respond_to?(:call)
  342 + @styles[name][:processors] = @styles[name][:processors].call(instance) if @styles[name][:processors].respond_to?(:call)
  343 + end
  344 + end
  345 +
  346 + def initialize_storage #:nodoc:
  347 + @storage_module = Paperclip::Storage.const_get(@storage.to_s.capitalize)
  348 + self.extend(@storage_module)
  349 + end
  350 +
  351 + def extra_options_for(style) #:nodoc:
  352 + all_options = convert_options[:all]
  353 + all_options = all_options.call(instance) if all_options.respond_to?(:call)
  354 + style_options = convert_options[style]
  355 + style_options = style_options.call(instance) if style_options.respond_to?(:call)
  356 +
  357 + [ style_options, all_options ].compact.join(" ")
  358 + end
  359 +
  360 + def post_process #:nodoc:
  361 + return if @queued_for_write[:original].nil?
  362 + solidify_style_definitions
  363 + return if fire_events(:before)
  364 + post_process_styles
  365 + return if fire_events(:after)
  366 + end
  367 +
  368 + def fire_events(which) #:nodoc:
  369 + return true if callback(:"#{which}_post_process") == false
  370 + return true if callback(:"#{which}_#{name}_post_process") == false
  371 + end
  372 +
  373 + def callback which #:nodoc:
  374 + instance.run_callbacks(which, @queued_for_write){|result, obj| result == false }
  375 + end
  376 +
  377 + def post_process_styles #:nodoc:
  378 + @styles.each do |name, args|
  379 + begin
  380 + raise RuntimeError.new("Style #{name} has no processors defined.") if args[:processors].blank?
  381 + @queued_for_write[name] = args[:processors].inject(@queued_for_write[:original]) do |file, processor|
  382 + Paperclip.processor(processor).make(file, args, self)
  383 + end
  384 + rescue PaperclipError => e
  385 + log("An error was received while processing: #{e.inspect}")
  386 + (@errors[:processing] ||= []) << e.message if @whiny
  387 + end
  388 + end
  389 + end
  390 +
  391 + def interpolate pattern, style = default_style #:nodoc:
  392 + Paperclip::Interpolations.interpolate(pattern, self, style)
  393 + end
  394 +
  395 + def queue_existing_for_delete #:nodoc:
  396 + return unless file?
  397 + @queued_for_delete += [:original, *@styles.keys].uniq.map do |style|
  398 + path(style) if exists?(style)
  399 + end.compact
  400 + instance_write(:file_name, nil)
  401 + instance_write(:content_type, nil)
  402 + instance_write(:file_size, nil)
  403 + instance_write(:updated_at, nil)
  404 + end
  405 +
  406 + def flush_errors #:nodoc:
  407 + @errors.each do |error, message|
  408 + [message].flatten.each {|m| instance.errors.add(name, m) }
  409 + end
  410 + end
  411 +
  412 + end
  413 +end
  414 +
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/callback_compatability.rb 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +module Paperclip
  2 + # This module is intended as a compatability shim for the differences in
  3 + # callbacks between Rails 2.0 and Rails 2.1.
  4 + module CallbackCompatability
  5 + def self.included(base)
  6 + base.extend(ClassMethods)
  7 + base.send(:include, InstanceMethods)
  8 + end
  9 +
  10 + module ClassMethods
  11 + # The implementation of this method is taken from the Rails 1.2.6 source,
  12 + # from rails/activerecord/lib/active_record/callbacks.rb, line 192.
  13 + def define_callbacks(*args)
  14 + args.each do |method|
  15 + self.class_eval <<-"end_eval"
  16 + def self.#{method}(*callbacks, &block)
  17 + callbacks << block if block_given?
  18 + write_inheritable_array(#{method.to_sym.inspect}, callbacks)
  19 + end
  20 + end_eval
  21 + end
  22 + end
  23 + end
  24 +
  25 + module InstanceMethods
  26 + # The callbacks in < 2.1 don't worry about the extra options or the
  27 + # block, so just run what we have available.
  28 + def run_callbacks(meth, opts = nil, &blk)
  29 + callback(meth)
  30 + end
  31 + end
  32 + end
  33 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/geometry.rb 0 → 100644
... ... @@ -0,0 +1,115 @@
  1 +module Paperclip
  2 +
  3 + # Defines the geometry of an image.
  4 + class Geometry
  5 + attr_accessor :height, :width, :modifier
  6 +
  7 + # Gives a Geometry representing the given height and width
  8 + def initialize width = nil, height = nil, modifier = nil
  9 + @height = height.to_f
  10 + @width = width.to_f
  11 + @modifier = modifier
  12 + end
  13 +
  14 + # Uses ImageMagick to determing the dimensions of a file, passed in as either a
  15 + # File or path.
  16 + def self.from_file file
  17 + file = file.path if file.respond_to? "path"
  18 + geometry = begin
  19 + Paperclip.run("identify", %Q[-format "%wx%h" "#{file}"[0]])
  20 + rescue PaperclipCommandLineError
  21 + ""
  22 + end
  23 + parse(geometry) ||
  24 + raise(NotIdentifiedByImageMagickError.new("#{file} is not recognized by the 'identify' command."))
  25 + end
  26 +
  27 + # Parses a "WxH" formatted string, where W is the width and H is the height.
  28 + def self.parse string
  29 + if match = (string && string.match(/\b(\d*)x?(\d*)\b([\>\<\#\@\%^!])?/i))
  30 + Geometry.new(*match[1,3])
  31 + end
  32 + end
  33 +
  34 + # True if the dimensions represent a square
  35 + def square?
  36 + height == width
  37 + end
  38 +
  39 + # True if the dimensions represent a horizontal rectangle
  40 + def horizontal?
  41 + height < width
  42 + end
  43 +
  44 + # True if the dimensions represent a vertical rectangle
  45 + def vertical?
  46 + height > width
  47 + end
  48 +
  49 + # The aspect ratio of the dimensions.
  50 + def aspect
  51 + width / height
  52 + end
  53 +
  54 + # Returns the larger of the two dimensions
  55 + def larger
  56 + [height, width].max
  57 + end
  58 +
  59 + # Returns the smaller of the two dimensions
  60 + def smaller
  61 + [height, width].min
  62 + end
  63 +
  64 + # Returns the width and height in a format suitable to be passed to Geometry.parse
  65 + def to_s
  66 + s = ""
  67 + s << width.to_i.to_s if width > 0
  68 + s << "x#{height.to_i}" if height > 0
  69 + s << modifier.to_s
  70 + s
  71 + end
  72 +
  73 + # Same as to_s
  74 + def inspect
  75 + to_s
  76 + end
  77 +
  78 + # Returns the scaling and cropping geometries (in string-based ImageMagick format)
  79 + # neccessary to transform this Geometry into the Geometry given. If crop is true,
  80 + # then it is assumed the destination Geometry will be the exact final resolution.
  81 + # In this case, the source Geometry is scaled so that an image containing the
  82 + # destination Geometry would be completely filled by the source image, and any
  83 + # overhanging image would be cropped. Useful for square thumbnail images. The cropping
  84 + # is weighted at the center of the Geometry.
  85 + def transformation_to dst, crop = false
  86 + if crop
  87 + ratio = Geometry.new( dst.width / self.width, dst.height / self.height )
  88 + scale_geometry, scale = scaling(dst, ratio)
  89 + crop_geometry = cropping(dst, ratio, scale)
  90 + else
  91 + scale_geometry = dst.to_s
  92 + end
  93 +
  94 + [ scale_geometry, crop_geometry ]
  95 + end
  96 +
  97 + private
  98 +
  99 + def scaling dst, ratio
  100 + if ratio.horizontal? || ratio.square?
  101 + [ "%dx" % dst.width, ratio.width ]
  102 + else
  103 + [ "x%d" % dst.height, ratio.height ]
  104 + end
  105 + end
  106 +
  107 + def cropping dst, ratio, scale
  108 + if ratio.horizontal? || ratio.square?
  109 + "%dx%d+%d+%d" % [ dst.width, dst.height, 0, (self.height * scale - dst.height) / 2 ]
  110 + else
  111 + "%dx%d+%d+%d" % [ dst.width, dst.height, (self.width * scale - dst.width) / 2, 0 ]
  112 + end
  113 + end
  114 + end
  115 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/interpolations.rb 0 → 100644
... ... @@ -0,0 +1,105 @@
  1 +module Paperclip
  2 + # This module contains all the methods that are available for interpolation
  3 + # in paths and urls. To add your own (or override an existing one), you
  4 + # can either open this module and define it, or call the
  5 + # Paperclip.interpolates method.
  6 + module Interpolations
  7 + extend self
  8 +
  9 + # Hash assignment of interpolations. Included only for compatability,
  10 + # and is not intended for normal use.
  11 + def self.[]= name, block
  12 + define_method(name, &block)
  13 + end
  14 +
  15 + # Hash access of interpolations. Included only for compatability,
  16 + # and is not intended for normal use.
  17 + def self.[] name
  18 + method(name)
  19 + end
  20 +
  21 + # Returns a sorted list of all interpolations.
  22 + def self.all
  23 + self.instance_methods(false).sort
  24 + end
  25 +
  26 + # Perform the actual interpolation. Takes the pattern to interpolate
  27 + # and the arguments to pass, which are the attachment and style name.
  28 + def self.interpolate pattern, *args
  29 + all.reverse.inject( pattern.dup ) do |result, tag|
  30 + result.gsub(/:#{tag}/) do |match|
  31 + send( tag, *args )
  32 + end
  33 + end
  34 + end
  35 +
  36 + # Returns the filename, the same way as ":basename.:extension" would.
  37 + def filename attachment, style
  38 + "#{basename(attachment, style)}.#{extension(attachment, style)}"
  39 + end
  40 +
  41 + # Returns the interpolated URL. Will raise an error if the url itself
  42 + # contains ":url" to prevent infinite recursion. This interpolation
  43 + # is used in the default :path to ease default specifications.
  44 + def url attachment, style
  45 + raise InfiniteInterpolationError if attachment.options[:url].include?(":url")
  46 + attachment.url(style, false)
  47 + end
  48 +
  49 + # Returns the timestamp as defined by the <attachment>_updated_at field
  50 + def timestamp attachment, style
  51 + attachment.instance_read(:updated_at).to_s
  52 + end
  53 +
  54 + # Returns the RAILS_ROOT constant.
  55 + def rails_root attachment, style
  56 + RAILS_ROOT
  57 + end
  58 +
  59 + # Returns the RAILS_ENV constant.
  60 + def rails_env attachment, style
  61 + RAILS_ENV
  62 + end
  63 +
  64 + # Returns the underscored, pluralized version of the class name.
  65 + # e.g. "users" for the User class.
  66 + def class attachment, style
  67 + attachment.instance.class.to_s.underscore.pluralize
  68 + end
  69 +
  70 + # Returns the basename of the file. e.g. "file" for "file.jpg"
  71 + def basename attachment, style
  72 + attachment.original_filename.gsub(/#{File.extname(attachment.original_filename)}$/, "")
  73 + end
  74 +
  75 + # Returns the extension of the file. e.g. "jpg" for "file.jpg"
  76 + # If the style has a format defined, it will return the format instead
  77 + # of the actual extension.
  78 + def extension attachment, style
  79 + ((style = attachment.styles[style]) && style[:format]) ||
  80 + File.extname(attachment.original_filename).gsub(/^\.+/, "")
  81 + end
  82 +
  83 + # Returns the id of the instance.
  84 + def id attachment, style
  85 + attachment.instance.id
  86 + end
  87 +
  88 + # Returns the id of the instance in a split path form. e.g. returns
  89 + # 000/001/234 for an id of 1234.
  90 + def id_partition attachment, style
  91 + ("%09d" % attachment.instance.id).scan(/\d{3}/).join("/")
  92 + end
  93 +
  94 + # Returns the pluralized form of the attachment name. e.g.
  95 + # "avatars" for an attachment of :avatar
  96 + def attachment attachment, style
  97 + attachment.name.to_s.downcase.pluralize
  98 + end
  99 +
  100 + # Returns the style, or the default style if nil is supplied.
  101 + def style attachment, style
  102 + style || attachment.default_style
  103 + end
  104 + end
  105 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/iostream.rb 0 → 100644
... ... @@ -0,0 +1,58 @@
  1 +# Provides method that can be included on File-type objects (IO, StringIO, Tempfile, etc) to allow stream copying
  2 +# and Tempfile conversion.
  3 +module IOStream
  4 +
  5 + # Returns a Tempfile containing the contents of the readable object.
  6 + def to_tempfile
  7 + tempfile = Tempfile.new("stream")
  8 + tempfile.binmode
  9 + self.stream_to(tempfile)
  10 + end
  11 +
  12 + # Copies one read-able object from one place to another in blocks, obviating the need to load
  13 + # the whole thing into memory. Defaults to 8k blocks. If this module is included in both
  14 + # StringIO and Tempfile, then either can have its data copied anywhere else without typing
  15 + # worries or memory overhead worries. Returns a File if a String is passed in as the destination
  16 + # and returns the IO or Tempfile as passed in if one is sent as the destination.
  17 + def stream_to path_or_file, in_blocks_of = 8192
  18 + dstio = case path_or_file
  19 + when String then File.new(path_or_file, "wb+")
  20 + when IO then path_or_file
  21 + when Tempfile then path_or_file
  22 + end
  23 + buffer = ""
  24 + self.rewind
  25 + while self.read(in_blocks_of, buffer) do
  26 + dstio.write(buffer)
  27 + end
  28 + dstio.rewind
  29 + dstio
  30 + end
  31 +end
  32 +
  33 +class IO #:nodoc:
  34 + include IOStream
  35 +end
  36 +
  37 +%w( Tempfile StringIO ).each do |klass|
  38 + if Object.const_defined? klass
  39 + Object.const_get(klass).class_eval do
  40 + include IOStream
  41 + end
  42 + end
  43 +end
  44 +
  45 +# Corrects a bug in Windows when asking for Tempfile size.
  46 +if defined? Tempfile
  47 + class Tempfile
  48 + def size
  49 + if @tmpfile
  50 + @tmpfile.fsync
  51 + @tmpfile.flush
  52 + @tmpfile.stat.size
  53 + else
  54 + 0
  55 + end
  56 + end
  57 + end
  58 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/matchers.rb 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +require 'paperclip/matchers/have_attached_file_matcher'
  2 +require 'paperclip/matchers/validate_attachment_presence_matcher'
  3 +require 'paperclip/matchers/validate_attachment_content_type_matcher'
  4 +require 'paperclip/matchers/validate_attachment_size_matcher'
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/matchers/have_attached_file_matcher.rb 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +module Paperclip
  2 + module Shoulda
  3 + module Matchers
  4 + def have_attached_file name
  5 + HaveAttachedFileMatcher.new(name)
  6 + end
  7 +
  8 + class HaveAttachedFileMatcher
  9 + def initialize attachment_name
  10 + @attachment_name = attachment_name
  11 + end
  12 +
  13 + def matches? subject
  14 + @subject = subject
  15 + responds? && has_column? && included?
  16 + end
  17 +
  18 + def failure_message
  19 + "Should have an attachment named #{@attachment_name}"
  20 + end
  21 +
  22 + def negative_failure_message
  23 + "Should not have an attachment named #{@attachment_name}"
  24 + end
  25 +
  26 + def description
  27 + "have an attachment named #{@attachment_name}"
  28 + end
  29 +
  30 + protected
  31 +
  32 + def responds?
  33 + methods = @subject.instance_methods.map(&:to_s)
  34 + methods.include?("#{@attachment_name}") &&
  35 + methods.include?("#{@attachment_name}=") &&
  36 + methods.include?("#{@attachment_name}?")
  37 + end
  38 +
  39 + def has_column?
  40 + @subject.column_names.include?("#{@attachment_name}_file_name")
  41 + end
  42 +
  43 + def included?
  44 + @subject.ancestors.include?(Paperclip::InstanceMethods)
  45 + end
  46 + end
  47 + end
  48 + end
  49 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb 0 → 100644
... ... @@ -0,0 +1,66 @@
  1 +module Paperclip
  2 + module Shoulda
  3 + module Matchers
  4 + def validate_attachment_content_type name
  5 + ValidateAttachmentContentTypeMatcher.new(name)
  6 + end
  7 +
  8 + class ValidateAttachmentContentTypeMatcher
  9 + def initialize attachment_name
  10 + @attachment_name = attachment_name
  11 + end
  12 +
  13 + def allowing *types
  14 + @allowed_types = types.flatten
  15 + self
  16 + end
  17 +
  18 + def rejecting *types
  19 + @rejected_types = types.flatten
  20 + self
  21 + end
  22 +
  23 + def matches? subject
  24 + @subject = subject
  25 + @allowed_types && @rejected_types &&
  26 + allowed_types_allowed? && rejected_types_rejected?
  27 + end
  28 +
  29 + def failure_message
  30 + "Content types #{@allowed_types.join(", ")} should be accepted" +
  31 + " and #{@rejected_types.join(", ")} rejected by #{@attachment_name}"
  32 + end
  33 +
  34 + def negative_failure_message
  35 + "Content types #{@allowed_types.join(", ")} should be rejected" +
  36 + " and #{@rejected_types.join(", ")} accepted by #{@attachment_name}"
  37 + end
  38 +
  39 + def description
  40 + "validate the content types allowed on attachment #{@attachment_name}"
  41 + end
  42 +
  43 + protected
  44 +
  45 + def allow_types?(types)
  46 + types.all? do |type|
  47 + file = StringIO.new(".")
  48 + file.content_type = type
  49 + attachment = @subject.new.attachment_for(@attachment_name)
  50 + attachment.assign(file)
  51 + attachment.errors[:content_type].nil?
  52 + end
  53 + end
  54 +
  55 + def allowed_types_allowed?
  56 + allow_types?(@allowed_types)
  57 + end
  58 +
  59 + def rejected_types_rejected?
  60 + not allow_types?(@rejected_types)
  61 + end
  62 + end
  63 + end
  64 + end
  65 +end
  66 +
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/matchers/validate_attachment_presence_matcher.rb 0 → 100644
... ... @@ -0,0 +1,48 @@
  1 +module Paperclip
  2 + module Shoulda
  3 + module Matchers
  4 + def validate_attachment_presence name
  5 + ValidateAttachmentPresenceMatcher.new(name)
  6 + end
  7 +
  8 + class ValidateAttachmentPresenceMatcher
  9 + def initialize attachment_name
  10 + @attachment_name = attachment_name
  11 + end
  12 +
  13 + def matches? subject
  14 + @subject = subject
  15 + error_when_not_valid? && no_error_when_valid?
  16 + end
  17 +
  18 + def failure_message
  19 + "Attachment #{@attachment_name} should be required"
  20 + end
  21 +
  22 + def negative_failure_message
  23 + "Attachment #{@attachment_name} should not be required"
  24 + end
  25 +
  26 + def description
  27 + "require presence of attachment #{@attachment_name}"
  28 + end
  29 +
  30 + protected
  31 +
  32 + def error_when_not_valid?
  33 + @attachment = @subject.new.send(@attachment_name)
  34 + @attachment.assign(nil)
  35 + not @attachment.errors[:presence].nil?
  36 + end
  37 +
  38 + def no_error_when_valid?
  39 + @file = StringIO.new(".")
  40 + @attachment = @subject.new.send(@attachment_name)
  41 + @attachment.assign(@file)
  42 + @attachment.errors[:presence].nil?
  43 + end
  44 + end
  45 + end
  46 + end
  47 +end
  48 +
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/matchers/validate_attachment_size_matcher.rb 0 → 100644
... ... @@ -0,0 +1,83 @@
  1 +module Paperclip
  2 + module Shoulda
  3 + module Matchers
  4 + def validate_attachment_size name
  5 + ValidateAttachmentSizeMatcher.new(name)
  6 + end
  7 +
  8 + class ValidateAttachmentSizeMatcher
  9 + def initialize attachment_name
  10 + @attachment_name = attachment_name
  11 + @low, @high = 0, (1.0/0)
  12 + end
  13 +
  14 + def less_than size
  15 + @high = size
  16 + self
  17 + end
  18 +
  19 + def greater_than size
  20 + @low = size
  21 + self
  22 + end
  23 +
  24 + def in range
  25 + @low, @high = range.first, range.last
  26 + self
  27 + end
  28 +
  29 + def matches? subject
  30 + @subject = subject
  31 + lower_than_low? && higher_than_low? && lower_than_high? && higher_than_high?
  32 + end
  33 +
  34 + def failure_message
  35 + "Attachment #{@attachment_name} must be between #{@low} and #{@high} bytes"
  36 + end
  37 +
  38 + def negative_failure_message
  39 + "Attachment #{@attachment_name} cannot be between #{@low} and #{@high} bytes"
  40 + end
  41 +
  42 + def description
  43 + "validate the size of attachment #{@attachment_name}"
  44 + end
  45 +
  46 + protected
  47 +
  48 + def override_method object, method, &replacement
  49 + (class << object; self; end).class_eval do
  50 + define_method(method, &replacement)
  51 + end
  52 + end
  53 +
  54 + def passes_validation_with_size(new_size)
  55 + file = StringIO.new(".")
  56 + override_method(file, :size){ new_size }
  57 + attachment = @subject.new.attachment_for(@attachment_name)
  58 + attachment.assign(file)
  59 + attachment.errors[:size].nil?
  60 + end
  61 +
  62 + def lower_than_low?
  63 + not passes_validation_with_size(@low - 1)
  64 + end
  65 +
  66 + def higher_than_low?
  67 + passes_validation_with_size(@low + 1)
  68 + end
  69 +
  70 + def lower_than_high?
  71 + return true if @high == (1.0/0)
  72 + passes_validation_with_size(@high - 1)
  73 + end
  74 +
  75 + def higher_than_high?
  76 + return true if @high == (1.0/0)
  77 + not passes_validation_with_size(@high + 1)
  78 + end
  79 + end
  80 + end
  81 + end
  82 +end
  83 +
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/processor.rb 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +module Paperclip
  2 + # Paperclip processors allow you to modify attached files when they are
  3 + # attached in any way you are able. Paperclip itself uses command-line
  4 + # programs for its included Thumbnail processor, but custom processors
  5 + # are not required to follow suit.
  6 + #
  7 + # Processors are required to be defined inside the Paperclip module and
  8 + # are also required to be a subclass of Paperclip::Processor. There is
  9 + # only one method you *must* implement to properly be a subclass:
  10 + # #make, but #initialize may also be of use. Both methods accept 3
  11 + # arguments: the file that will be operated on (which is an instance of
  12 + # File), a hash of options that were defined in has_attached_file's
  13 + # style hash, and the Paperclip::Attachment itself.
  14 + #
  15 + # All #make needs to return is an instance of File (Tempfile is
  16 + # acceptable) which contains the results of the processing.
  17 + #
  18 + # See Paperclip.run for more information about using command-line
  19 + # utilities from within Processors.
  20 + class Processor
  21 + attr_accessor :file, :options, :attachment
  22 +
  23 + def initialize file, options = {}, attachment = nil
  24 + @file = file
  25 + @options = options
  26 + @attachment = attachment
  27 + end
  28 +
  29 + def make
  30 + end
  31 +
  32 + def self.make file, options = {}, attachment = nil
  33 + new(file, options, attachment).make
  34 + end
  35 + end
  36 +
  37 + # Due to how ImageMagick handles its image format conversion and how Tempfile
  38 + # handles its naming scheme, it is necessary to override how Tempfile makes
  39 + # its names so as to allow for file extensions. Idea taken from the comments
  40 + # on this blog post:
  41 + # http://marsorange.com/archives/of-mogrify-ruby-tempfile-dynamic-class-definitions
  42 + class Tempfile < ::Tempfile
  43 + # Replaces Tempfile's +make_tmpname+ with one that honors file extensions.
  44 + def make_tmpname(basename, n)
  45 + extension = File.extname(basename)
  46 + sprintf("%s,%d,%d%s", File.basename(basename, extension), $$, n, extension)
  47 + end
  48 + end
  49 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/storage.rb 0 → 100644
... ... @@ -0,0 +1,237 @@
  1 +module Paperclip
  2 + module Storage
  3 +
  4 + # The default place to store attachments is in the filesystem. Files on the local
  5 + # filesystem can be very easily served by Apache without requiring a hit to your app.
  6 + # They also can be processed more easily after they've been saved, as they're just
  7 + # normal files. There is one Filesystem-specific option for has_attached_file.
  8 + # * +path+: The location of the repository of attachments on disk. This can (and, in
  9 + # almost all cases, should) be coordinated with the value of the +url+ option to
  10 + # allow files to be saved into a place where Apache can serve them without
  11 + # hitting your app. Defaults to
  12 + # ":rails_root/public/:attachment/:id/:style/:basename.:extension"
  13 + # By default this places the files in the app's public directory which can be served
  14 + # directly. If you are using capistrano for deployment, a good idea would be to
  15 + # make a symlink to the capistrano-created system directory from inside your app's
  16 + # public directory.
  17 + # See Paperclip::Attachment#interpolate for more information on variable interpolaton.
  18 + # :path => "/var/app/attachments/:class/:id/:style/:basename.:extension"
  19 + module Filesystem
  20 + def self.extended base
  21 + end
  22 +
  23 + def exists?(style = default_style)
  24 + if original_filename
  25 + File.exist?(path(style))
  26 + else
  27 + false
  28 + end
  29 + end
  30 +
  31 + # Returns representation of the data of the file assigned to the given
  32 + # style, in the format most representative of the current storage.
  33 + def to_file style = default_style
  34 + @queued_for_write[style] || (File.new(path(style), 'rb') if exists?(style))
  35 + end
  36 +
  37 + def flush_writes #:nodoc:
  38 + @queued_for_write.each do |style, file|
  39 + file.close
  40 + FileUtils.mkdir_p(File.dirname(path(style)))
  41 + log("saving #{path(style)}")
  42 + FileUtils.mv(file.path, path(style))
  43 + FileUtils.chmod(0644, path(style))
  44 + end
  45 + @queued_for_write = {}
  46 + end
  47 +
  48 + def flush_deletes #:nodoc:
  49 + @queued_for_delete.each do |path|
  50 + begin
  51 + log("deleting #{path}")
  52 + FileUtils.rm(path) if File.exist?(path)
  53 + rescue Errno::ENOENT => e
  54 + # ignore file-not-found, let everything else pass
  55 + end
  56 + begin
  57 + while(true)
  58 + path = File.dirname(path)
  59 + FileUtils.rmdir(path)
  60 + end
  61 + rescue Errno::EEXIST, Errno::ENOTEMPTY, Errno::ENOENT, Errno::EINVAL, Errno::ENOTDIR
  62 + # Stop trying to remove parent directories
  63 + rescue SystemCallError => e
  64 + log("There was an unexpected error while deleting directories: #{e.class}")
  65 + # Ignore it
  66 + end
  67 + end
  68 + @queued_for_delete = []
  69 + end
  70 + end
  71 +
  72 + # Amazon's S3 file hosting service is a scalable, easy place to store files for
  73 + # distribution. You can find out more about it at http://aws.amazon.com/s3
  74 + # There are a few S3-specific options for has_attached_file:
  75 + # * +s3_credentials+: Takes a path, a File, or a Hash. The path (or File) must point
  76 + # to a YAML file containing the +access_key_id+ and +secret_access_key+ that Amazon
  77 + # gives you. You can 'environment-space' this just like you do to your
  78 + # database.yml file, so different environments can use different accounts:
  79 + # development:
  80 + # access_key_id: 123...
  81 + # secret_access_key: 123...
  82 + # test:
  83 + # access_key_id: abc...
  84 + # secret_access_key: abc...
  85 + # production:
  86 + # access_key_id: 456...
  87 + # secret_access_key: 456...
  88 + # This is not required, however, and the file may simply look like this:
  89 + # access_key_id: 456...
  90 + # secret_access_key: 456...
  91 + # In which case, those access keys will be used in all environments. You can also
  92 + # put your bucket name in this file, instead of adding it to the code directly.
  93 + # This is useful when you want the same account but a different bucket for
  94 + # development versus production.
  95 + # * +s3_permissions+: This is a String that should be one of the "canned" access
  96 + # policies that S3 provides (more information can be found here:
  97 + # http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html#RESTCannedAccessPolicies)
  98 + # The default for Paperclip is "public-read".
  99 + # * +s3_protocol+: The protocol for the URLs generated to your S3 assets. Can be either
  100 + # 'http' or 'https'. Defaults to 'http' when your :s3_permissions are 'public-read' (the
  101 + # default), and 'https' when your :s3_permissions are anything else.
  102 + # * +s3_headers+: A hash of headers such as {'Expires' => 1.year.from_now.httpdate}
  103 + # * +bucket+: This is the name of the S3 bucket that will store your files. Remember
  104 + # that the bucket must be unique across all of Amazon S3. If the bucket does not exist
  105 + # Paperclip will attempt to create it. The bucket name will not be interpolated.
  106 + # You can define the bucket as a Proc if you want to determine it's name at runtime.
  107 + # Paperclip will call that Proc with attachment as the only argument.
  108 + # * +s3_host_alias+: The fully-qualified domain name (FQDN) that is the alias to the
  109 + # S3 domain of your bucket. Used with the :s3_alias_url url interpolation. See the
  110 + # link in the +url+ entry for more information about S3 domains and buckets.
  111 + # * +url+: There are three options for the S3 url. You can choose to have the bucket's name
  112 + # placed domain-style (bucket.s3.amazonaws.com) or path-style (s3.amazonaws.com/bucket).
  113 + # Lastly, you can specify a CNAME (which requires the CNAME to be specified as
  114 + # :s3_alias_url. You can read more about CNAMEs and S3 at
  115 + # http://docs.amazonwebservices.com/AmazonS3/latest/index.html?VirtualHosting.html
  116 + # Normally, this won't matter in the slightest and you can leave the default (which is
  117 + # path-style, or :s3_path_url). But in some cases paths don't work and you need to use
  118 + # the domain-style (:s3_domain_url). Anything else here will be treated like path-style.
  119 + # NOTE: If you use a CNAME for use with CloudFront, you can NOT specify https as your
  120 + # :s3_protocol; This is *not supported* by S3/CloudFront. Finally, when using the host
  121 + # alias, the :bucket parameter is ignored, as the hostname is used as the bucket name
  122 + # by S3.
  123 + # * +path+: This is the key under the bucket in which the file will be stored. The
  124 + # URL will be constructed from the bucket and the path. This is what you will want
  125 + # to interpolate. Keys should be unique, like filenames, and despite the fact that
  126 + # S3 (strictly speaking) does not support directories, you can still use a / to
  127 + # separate parts of your file name.
  128 + module S3
  129 + def self.extended base
  130 + require 'aws/s3'
  131 + base.instance_eval do
  132 + @s3_credentials = parse_credentials(@options[:s3_credentials])
  133 + @bucket = @options[:bucket] || @s3_credentials[:bucket]
  134 + @bucket = @bucket.call(self) if @bucket.is_a?(Proc)
  135 + @s3_options = @options[:s3_options] || {}
  136 + @s3_permissions = @options[:s3_permissions] || :public_read
  137 + @s3_protocol = @options[:s3_protocol] || (@s3_permissions == :public_read ? 'http' : 'https')
  138 + @s3_headers = @options[:s3_headers] || {}
  139 + @s3_host_alias = @options[:s3_host_alias]
  140 + @url = ":s3_path_url" unless @url.to_s.match(/^:s3.*url$/)
  141 + AWS::S3::Base.establish_connection!( @s3_options.merge(
  142 + :access_key_id => @s3_credentials[:access_key_id],
  143 + :secret_access_key => @s3_credentials[:secret_access_key]
  144 + ))
  145 + end
  146 + Paperclip.interpolates(:s3_alias_url) do |attachment, style|
  147 + "#{attachment.s3_protocol}://#{attachment.s3_host_alias}/#{attachment.path(style).gsub(%r{^/}, "")}"
  148 + end
  149 + Paperclip.interpolates(:s3_path_url) do |attachment, style|
  150 + "#{attachment.s3_protocol}://s3.amazonaws.com/#{attachment.bucket_name}/#{attachment.path(style).gsub(%r{^/}, "")}"
  151 + end
  152 + Paperclip.interpolates(:s3_domain_url) do |attachment, style|
  153 + "#{attachment.s3_protocol}://#{attachment.bucket_name}.s3.amazonaws.com/#{attachment.path(style).gsub(%r{^/}, "")}"
  154 + end
  155 + end
  156 +
  157 + def bucket_name
  158 + @bucket
  159 + end
  160 +
  161 + def s3_host_alias
  162 + @s3_host_alias
  163 + end
  164 +
  165 + def parse_credentials creds
  166 + creds = find_credentials(creds).stringify_keys
  167 + (creds[RAILS_ENV] || creds).symbolize_keys
  168 + end
  169 +
  170 + def exists?(style = default_style)
  171 + if original_filename
  172 + AWS::S3::S3Object.exists?(path(style), bucket_name)
  173 + else
  174 + false
  175 + end
  176 + end
  177 +
  178 + def s3_protocol
  179 + @s3_protocol
  180 + end
  181 +
  182 + # Returns representation of the data of the file assigned to the given
  183 + # style, in the format most representative of the current storage.
  184 + def to_file style = default_style
  185 + return @queued_for_write[style] if @queued_for_write[style]
  186 + file = Tempfile.new(path(style))
  187 + file.write(AWS::S3::S3Object.value(path(style), bucket_name))
  188 + file.rewind
  189 + return file
  190 + end
  191 +
  192 + def flush_writes #:nodoc:
  193 + @queued_for_write.each do |style, file|
  194 + begin
  195 + log("saving #{path(style)}")
  196 + AWS::S3::S3Object.store(path(style),
  197 + file,
  198 + bucket_name,
  199 + {:content_type => instance_read(:content_type),
  200 + :access => @s3_permissions,
  201 + }.merge(@s3_headers))
  202 + rescue AWS::S3::ResponseError => e
  203 + raise
  204 + end
  205 + end
  206 + @queued_for_write = {}
  207 + end
  208 +
  209 + def flush_deletes #:nodoc:
  210 + @queued_for_delete.each do |path|
  211 + begin
  212 + log("deleting #{path}")
  213 + AWS::S3::S3Object.delete(path, bucket_name)
  214 + rescue AWS::S3::ResponseError
  215 + # Ignore this.
  216 + end
  217 + end
  218 + @queued_for_delete = []
  219 + end
  220 +
  221 + def find_credentials creds
  222 + case creds
  223 + when File
  224 + YAML.load_file(creds.path)
  225 + when String
  226 + YAML.load_file(creds)
  227 + when Hash
  228 + creds
  229 + else
  230 + raise ArgumentError, "Credentials are not a path, file, or hash."
  231 + end
  232 + end
  233 + private :find_credentials
  234 +
  235 + end
  236 + end
  237 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/thumbnail.rb 0 → 100644
... ... @@ -0,0 +1,73 @@
  1 +module Paperclip
  2 + # Handles thumbnailing images that are uploaded.
  3 + class Thumbnail < Processor
  4 +
  5 + attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options, :source_file_options
  6 +
  7 + # Creates a Thumbnail object set to work on the +file+ given. It
  8 + # will attempt to transform the image into one defined by +target_geometry+
  9 + # which is a "WxH"-style string. +format+ will be inferred from the +file+
  10 + # unless specified. Thumbnail creation will raise no errors unless
  11 + # +whiny+ is true (which it is, by default. If +convert_options+ is
  12 + # set, the options will be appended to the convert command upon image conversion
  13 + def initialize file, options = {}, attachment = nil
  14 + super
  15 + geometry = options[:geometry]
  16 + @file = file
  17 + @crop = geometry[-1,1] == '#'
  18 + @target_geometry = Geometry.parse geometry
  19 + @current_geometry = Geometry.from_file @file
  20 + @source_file_options = options[:source_file_options]
  21 + @convert_options = options[:convert_options]
  22 + @whiny = options[:whiny].nil? ? true : options[:whiny]
  23 + @format = options[:format]
  24 +
  25 + @current_format = File.extname(@file.path)
  26 + @basename = File.basename(@file.path, @current_format)
  27 + end
  28 +
  29 + # Returns true if the +target_geometry+ is meant to crop.
  30 + def crop?
  31 + @crop
  32 + end
  33 +
  34 + # Returns true if the image is meant to make use of additional convert options.
  35 + def convert_options?
  36 + not @convert_options.blank?
  37 + end
  38 +
  39 + # Performs the conversion of the +file+ into a thumbnail. Returns the Tempfile
  40 + # that contains the new image.
  41 + def make
  42 + src = @file
  43 + dst = Tempfile.new([@basename, @format].compact.join("."))
  44 + dst.binmode
  45 +
  46 + command = <<-end_command
  47 + #{ source_file_options }
  48 + "#{ File.expand_path(src.path) }[0]"
  49 + #{ transformation_command }
  50 + "#{ File.expand_path(dst.path) }"
  51 + end_command
  52 +
  53 + begin
  54 + success = Paperclip.run("convert", command.gsub(/\s+/, " "))
  55 + rescue PaperclipCommandLineError
  56 + raise PaperclipError, "There was an error processing the thumbnail for #{@basename}" if @whiny
  57 + end
  58 +
  59 + dst
  60 + end
  61 +
  62 + # Returns the command ImageMagick's +convert+ needs to transform the image
  63 + # into the thumbnail.
  64 + def transformation_command
  65 + scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
  66 + trans = ""
  67 + trans << " -resize \"#{scale}\"" unless scale.blank?
  68 + trans << " -crop \"#{crop}\" +repage" if crop
  69 + trans << " #{convert_options}" if convert_options?
  70 + trans
  71 + end
  72 + end
  73 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/lib/paperclip/upfile.rb 0 → 100644
... ... @@ -0,0 +1,48 @@
  1 +module Paperclip
  2 + # The Upfile module is a convenience module for adding uploaded-file-type methods
  3 + # to the +File+ class. Useful for testing.
  4 + # user.avatar = File.new("test/test_avatar.jpg")
  5 + module Upfile
  6 +
  7 + # Infer the MIME-type of the file from the extension.
  8 + def content_type
  9 + type = (self.path.match(/\.(\w+)$/)[1] rescue "octet-stream").downcase
  10 + case type
  11 + when %r"jpe?g" then "image/jpeg"
  12 + when %r"tiff?" then "image/tiff"
  13 + when %r"png", "gif", "bmp" then "image/#{type}"
  14 + when "txt" then "text/plain"
  15 + when %r"html?" then "text/html"
  16 + when "csv", "xml", "css", "js" then "text/#{type}"
  17 + else "application/x-#{type}"
  18 + end
  19 + end
  20 +
  21 + # Returns the file's normal name.
  22 + def original_filename
  23 + File.basename(self.path)
  24 + end
  25 +
  26 + # Returns the size of the file.
  27 + def size
  28 + File.size(self)
  29 + end
  30 + end
  31 +end
  32 +
  33 +if defined? StringIO
  34 + class StringIO
  35 + attr_accessor :original_filename, :content_type
  36 + def original_filename
  37 + @original_filename ||= "stringio.txt"
  38 + end
  39 + def content_type
  40 + @content_type ||= "text/plain"
  41 + end
  42 + end
  43 +end
  44 +
  45 +class File #:nodoc:
  46 + include Paperclip::Upfile
  47 +end
  48 +
... ...
vendor/gems/tristandunn-paperclip-2.3.1/shoulda_macros/paperclip.rb 0 → 100644
... ... @@ -0,0 +1,68 @@
  1 +require 'paperclip/matchers'
  2 +
  3 +module Paperclip
  4 + # =Paperclip Shoulda Macros
  5 + #
  6 + # These macros are intended for use with shoulda, and will be included into
  7 + # your tests automatically. All of the macros use the standard shoulda
  8 + # assumption that the name of the test is based on the name of the model
  9 + # you're testing (that is, UserTest is the test for the User model), and
  10 + # will load that class for testing purposes.
  11 + module Shoulda
  12 + include Matchers
  13 + # This will test whether you have defined your attachment correctly by
  14 + # checking for all the required fields exist after the definition of the
  15 + # attachment.
  16 + def should_have_attached_file name
  17 + klass = self.name.gsub(/Test$/, '').constantize
  18 + matcher = have_attached_file name
  19 + should matcher.description do
  20 + assert_accepts(matcher, klass)
  21 + end
  22 + end
  23 +
  24 + # Tests for validations on the presence of the attachment.
  25 + def should_validate_attachment_presence name
  26 + klass = self.name.gsub(/Test$/, '').constantize
  27 + matcher = validate_attachment_presence name
  28 + should matcher.description do
  29 + assert_accepts(matcher, klass)
  30 + end
  31 + end
  32 +
  33 + # Tests that you have content_type validations specified. There are two
  34 + # options, :valid and :invalid. Both accept an array of strings. The
  35 + # strings should be a list of content types which will pass and fail
  36 + # validation, respectively.
  37 + def should_validate_attachment_content_type name, options = {}
  38 + klass = self.name.gsub(/Test$/, '').constantize
  39 + valid = [options[:valid]].flatten
  40 + invalid = [options[:invalid]].flatten
  41 + matcher = validate_attachment_content_type(name).allowing(valid).rejecting(invalid)
  42 + should matcher.description do
  43 + assert_accepts(matcher, klass)
  44 + end
  45 + end
  46 +
  47 + # Tests to ensure that you have file size validations turned on. You
  48 + # can pass the same options to this that you can to
  49 + # validate_attachment_file_size - :less_than, :greater_than, and :in.
  50 + # :less_than checks that a file is less than a certain size, :greater_than
  51 + # checks that a file is more than a certain size, and :in takes a Range or
  52 + # Array which specifies the lower and upper limits of the file size.
  53 + def should_validate_attachment_size name, options = {}
  54 + klass = self.name.gsub(/Test$/, '').constantize
  55 + min = options[:greater_than] || (options[:in] && options[:in].first) || 0
  56 + max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
  57 + range = (min..max)
  58 + matcher = validate_attachment_size(name).in(range)
  59 + should matcher.description do
  60 + assert_accepts(matcher, klass)
  61 + end
  62 + end
  63 + end
  64 +end
  65 +
  66 +class Test::Unit::TestCase #:nodoc:
  67 + extend Paperclip::Shoulda
  68 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/tasks/paperclip_tasks.rake 0 → 100644
... ... @@ -0,0 +1,79 @@
  1 +def obtain_class
  2 + class_name = ENV['CLASS'] || ENV['class']
  3 + raise "Must specify CLASS" unless class_name
  4 + @klass = Object.const_get(class_name)
  5 +end
  6 +
  7 +def obtain_attachments
  8 + name = ENV['ATTACHMENT'] || ENV['attachment']
  9 + raise "Class #{@klass.name} has no attachments specified" unless @klass.respond_to?(:attachment_definitions)
  10 + if !name.blank? && @klass.attachment_definitions.keys.include?(name)
  11 + [ name ]
  12 + else
  13 + @klass.attachment_definitions.keys
  14 + end
  15 +end
  16 +
  17 +def for_all_attachments
  18 + klass = obtain_class
  19 + names = obtain_attachments
  20 + ids = klass.connection.select_values(klass.send(:construct_finder_sql, :select => 'id'))
  21 +
  22 + ids.each do |id|
  23 + instance = klass.find(id)
  24 + names.each do |name|
  25 + result = if instance.send("#{ name }?")
  26 + yield(instance, name)
  27 + else
  28 + true
  29 + end
  30 + print result ? "." : "x"; $stdout.flush
  31 + end
  32 + end
  33 + puts " Done."
  34 +end
  35 +
  36 +namespace :paperclip do
  37 + desc "Refreshes both metadata and thumbnails."
  38 + task :refresh => ["paperclip:refresh:metadata", "paperclip:refresh:thumbnails"]
  39 +
  40 + namespace :refresh do
  41 + desc "Regenerates thumbnails for a given CLASS (and optional ATTACHMENT)."
  42 + task :thumbnails => :environment do
  43 + errors = []
  44 + for_all_attachments do |instance, name|
  45 + result = instance.send(name).reprocess!
  46 + errors << [instance.id, instance.errors] unless instance.errors.blank?
  47 + result
  48 + end
  49 + errors.each{|e| puts "#{e.first}: #{e.last.full_messages.inspect}" }
  50 + end
  51 +
  52 + desc "Regenerates content_type/size metadata for a given CLASS (and optional ATTACHMENT)."
  53 + task :metadata => :environment do
  54 + for_all_attachments do |instance, name|
  55 + if file = instance.send(name).to_file
  56 + instance.send("#{name}_file_name=", instance.send("#{name}_file_name").strip)
  57 + instance.send("#{name}_content_type=", file.content_type.strip)
  58 + instance.send("#{name}_file_size=", file.size) if instance.respond_to?("#{name}_file_size")
  59 + instance.save(false)
  60 + else
  61 + true
  62 + end
  63 + end
  64 + end
  65 + end
  66 +
  67 + desc "Cleans out invalid attachments. Useful after you've added new validations."
  68 + task :clean => :environment do
  69 + for_all_attachments do |instance, name|
  70 + instance.send(name).send(:validate)
  71 + if instance.send(name).valid?
  72 + true
  73 + else
  74 + instance.send("#{name}=", nil)
  75 + instance.save
  76 + end
  77 + end
  78 + end
  79 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/attachment_test.rb 0 → 100644
... ... @@ -0,0 +1,779 @@
  1 +# encoding: utf-8
  2 +require 'test/helper'
  3 +
  4 +class Dummy
  5 + # This is a dummy class
  6 +end
  7 +
  8 +class AttachmentTest < Test::Unit::TestCase
  9 + should "return the path based on the url by default" do
  10 + @attachment = attachment :url => "/:class/:id/:basename"
  11 + @model = @attachment.instance
  12 + @model.id = 1234
  13 + @model.avatar_file_name = "fake.jpg"
  14 + assert_equal "#{RAILS_ROOT}/public/fake_models/1234/fake", @attachment.path
  15 + end
  16 +
  17 + should "call a proc sent to check_guard" do
  18 + @dummy = Dummy.new
  19 + @dummy.expects(:one).returns(:one)
  20 + assert_equal :one, @dummy.avatar.send(:check_guard, lambda{|x| x.one })
  21 + end
  22 +
  23 + should "call a method name sent to check_guard" do
  24 + @dummy = Dummy.new
  25 + @dummy.expects(:one).returns(:one)
  26 + assert_equal :one, @dummy.avatar.send(:check_guard, :one)
  27 + end
  28 +
  29 + context "Attachment default_options" do
  30 + setup do
  31 + rebuild_model
  32 + @old_default_options = Paperclip::Attachment.default_options.dup
  33 + @new_default_options = @old_default_options.merge({
  34 + :path => "argle/bargle",
  35 + :url => "fooferon",
  36 + :default_url => "not here.png"
  37 + })
  38 + end
  39 +
  40 + teardown do
  41 + Paperclip::Attachment.default_options.merge! @old_default_options
  42 + end
  43 +
  44 + should "be overrideable" do
  45 + Paperclip::Attachment.default_options.merge!(@new_default_options)
  46 + @new_default_options.keys.each do |key|
  47 + assert_equal @new_default_options[key],
  48 + Paperclip::Attachment.default_options[key]
  49 + end
  50 + end
  51 +
  52 + context "without an Attachment" do
  53 + setup do
  54 + @dummy = Dummy.new
  55 + end
  56 +
  57 + should "return false when asked exists?" do
  58 + assert !@dummy.avatar.exists?
  59 + end
  60 + end
  61 +
  62 + context "on an Attachment" do
  63 + setup do
  64 + @dummy = Dummy.new
  65 + @attachment = @dummy.avatar
  66 + end
  67 +
  68 + Paperclip::Attachment.default_options.keys.each do |key|
  69 + should "be the default_options for #{key}" do
  70 + assert_equal @old_default_options[key],
  71 + @attachment.instance_variable_get("@#{key}"),
  72 + key
  73 + end
  74 + end
  75 +
  76 + context "when redefined" do
  77 + setup do
  78 + Paperclip::Attachment.default_options.merge!(@new_default_options)
  79 + @dummy = Dummy.new
  80 + @attachment = @dummy.avatar
  81 + end
  82 +
  83 + Paperclip::Attachment.default_options.keys.each do |key|
  84 + should "be the new default_options for #{key}" do
  85 + assert_equal @new_default_options[key],
  86 + @attachment.instance_variable_get("@#{key}"),
  87 + key
  88 + end
  89 + end
  90 + end
  91 + end
  92 + end
  93 +
  94 + context "An attachment with similarly named interpolations" do
  95 + setup do
  96 + rebuild_model :path => ":id.omg/:id-bbq/:idwhat/:id_partition.wtf"
  97 + @dummy = Dummy.new
  98 + @dummy.stubs(:id).returns(1024)
  99 + @file = File.new(File.join(File.dirname(__FILE__),
  100 + "fixtures",
  101 + "5k.png"), 'rb')
  102 + @dummy.avatar = @file
  103 + end
  104 +
  105 + teardown { @file.close }
  106 +
  107 + should "make sure that they are interpolated correctly" do
  108 + assert_equal "1024.omg/1024-bbq/1024what/000/001/024.wtf", @dummy.avatar.path
  109 + end
  110 + end
  111 +
  112 + context "An attachment with a :rails_env interpolation" do
  113 + setup do
  114 + @rails_env = "blah"
  115 + @id = 1024
  116 + rebuild_model :path => ":rails_env/:id.png"
  117 + @dummy = Dummy.new
  118 + @dummy.stubs(:id).returns(@id)
  119 + @file = StringIO.new(".")
  120 + @dummy.avatar = @file
  121 + end
  122 +
  123 + should "return the proper path" do
  124 + temporary_rails_env(@rails_env) {
  125 + assert_equal "#{@rails_env}/#{@id}.png", @dummy.avatar.path
  126 + }
  127 + end
  128 + end
  129 +
  130 + context "An attachment with a default style and an extension interpolation" do
  131 + setup do
  132 + @attachment = attachment :path => ":basename.:extension",
  133 + :styles => { :default => ["100x100", :png] },
  134 + :default_style => :default
  135 + @file = StringIO.new("...")
  136 + @file.expects(:original_filename).returns("file.jpg")
  137 + end
  138 + should "return the right extension for the path" do
  139 + @attachment.assign(@file)
  140 + assert_equal "file.png", @attachment.path
  141 + end
  142 + end
  143 +
  144 + context "An attachment with :convert_options" do
  145 + setup do
  146 + rebuild_model :styles => {
  147 + :thumb => "100x100",
  148 + :large => "400x400"
  149 + },
  150 + :convert_options => {
  151 + :all => "-do_stuff",
  152 + :thumb => "-thumbnailize"
  153 + }
  154 + @dummy = Dummy.new
  155 + @dummy.avatar
  156 + end
  157 +
  158 + should "report the correct options when sent #extra_options_for(:thumb)" do
  159 + assert_equal "-thumbnailize -do_stuff", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
  160 + end
  161 +
  162 + should "report the correct options when sent #extra_options_for(:large)" do
  163 + assert_equal "-do_stuff", @dummy.avatar.send(:extra_options_for, :large)
  164 + end
  165 +
  166 + before_should "call extra_options_for(:thumb/:large)" do
  167 + Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
  168 + Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
  169 + end
  170 + end
  171 +
  172 + context "An attachment with :convert_options that is a proc" do
  173 + setup do
  174 + rebuild_model :styles => {
  175 + :thumb => "100x100",
  176 + :large => "400x400"
  177 + },
  178 + :convert_options => {
  179 + :all => lambda{|i| i.all },
  180 + :thumb => lambda{|i| i.thumb }
  181 + }
  182 + Dummy.class_eval do
  183 + def all; "-all"; end
  184 + def thumb; "-thumb"; end
  185 + end
  186 + @dummy = Dummy.new
  187 + @dummy.avatar
  188 + end
  189 +
  190 + should "report the correct options when sent #extra_options_for(:thumb)" do
  191 + assert_equal "-thumb -all", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
  192 + end
  193 +
  194 + should "report the correct options when sent #extra_options_for(:large)" do
  195 + assert_equal "-all", @dummy.avatar.send(:extra_options_for, :large)
  196 + end
  197 +
  198 + before_should "call extra_options_for(:thumb/:large)" do
  199 + Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
  200 + Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
  201 + end
  202 + end
  203 +
  204 + context "An attachment with :path that is a proc" do
  205 + setup do
  206 + rebuild_model :path => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
  207 +
  208 + @file = File.new(File.join(File.dirname(__FILE__),
  209 + "fixtures",
  210 + "5k.png"), 'rb')
  211 + @dummyA = Dummy.new(:other => 'a')
  212 + @dummyA.avatar = @file
  213 + @dummyB = Dummy.new(:other => 'b')
  214 + @dummyB.avatar = @file
  215 + end
  216 +
  217 + teardown { @file.close }
  218 +
  219 + should "return correct path" do
  220 + assert_equal "path/a.png", @dummyA.avatar.path
  221 + assert_equal "path/b.png", @dummyB.avatar.path
  222 + end
  223 + end
  224 +
  225 + context "An attachment with :styles that is a proc" do
  226 + setup do
  227 + rebuild_model :styles => lambda{ |attachment| {:thumb => "50x50#", :large => "400x400"} }
  228 +
  229 + @attachment = Dummy.new.avatar
  230 + end
  231 +
  232 + should "have the correct geometry" do
  233 + assert_equal "50x50#", @attachment.styles[:thumb][:geometry]
  234 + end
  235 + end
  236 +
  237 + context "An attachment with :url that is a proc" do
  238 + setup do
  239 + rebuild_model :url => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
  240 +
  241 + @file = File.new(File.join(File.dirname(__FILE__),
  242 + "fixtures",
  243 + "5k.png"), 'rb')
  244 + @dummyA = Dummy.new(:other => 'a')
  245 + @dummyA.avatar = @file
  246 + @dummyB = Dummy.new(:other => 'b')
  247 + @dummyB.avatar = @file
  248 + end
  249 +
  250 + teardown { @file.close }
  251 +
  252 + should "return correct url" do
  253 + assert_equal "path/a.png", @dummyA.avatar.url(:original, false)
  254 + assert_equal "path/b.png", @dummyB.avatar.url(:original, false)
  255 + end
  256 + end
  257 +
  258 + geometry_specs = [
  259 + [ lambda{|z| "50x50#" }, :png ],
  260 + lambda{|z| "50x50#" },
  261 + { :geometry => lambda{|z| "50x50#" } }
  262 + ]
  263 + geometry_specs.each do |geometry_spec|
  264 + context "An attachment geometry like #{geometry_spec}" do
  265 + setup do
  266 + rebuild_model :styles => { :normal => geometry_spec }
  267 + @attachment = Dummy.new.avatar
  268 + end
  269 +
  270 + should "not run the procs immediately" do
  271 + assert_kind_of Proc, @attachment.styles[:normal][:geometry]
  272 + end
  273 +
  274 + context "when assigned" do
  275 + setup do
  276 + @file = StringIO.new(".")
  277 + @attachment.assign(@file)
  278 + end
  279 +
  280 + should "have the correct geometry" do
  281 + assert_equal "50x50#", @attachment.styles[:normal][:geometry]
  282 + end
  283 + end
  284 + end
  285 + end
  286 +
  287 + context "An attachment with both 'normal' and hash-style styles" do
  288 + setup do
  289 + rebuild_model :styles => {
  290 + :normal => ["50x50#", :png],
  291 + :hash => { :geometry => "50x50#", :format => :png }
  292 + }
  293 + @dummy = Dummy.new
  294 + @attachment = @dummy.avatar
  295 + end
  296 +
  297 + [:processors, :whiny, :convert_options, :geometry, :format].each do |field|
  298 + should "have the same #{field} field" do
  299 + assert_equal @attachment.styles[:normal][field], @attachment.styles[:hash][field]
  300 + end
  301 + end
  302 + end
  303 +
  304 + context "An attachment with :processors that is a proc" do
  305 + setup do
  306 + rebuild_model :styles => { :normal => '' }, :processors => lambda { |a| [ :test ] }
  307 + @attachment = Dummy.new.avatar
  308 + end
  309 +
  310 + should "not run the proc immediately" do
  311 + assert_kind_of Proc, @attachment.styles[:normal][:processors]
  312 + end
  313 +
  314 + context "when assigned" do
  315 + setup do
  316 + @attachment.assign(StringIO.new("."))
  317 + end
  318 +
  319 + should "have the correct processors" do
  320 + assert_equal [ :test ], @attachment.styles[:normal][:processors]
  321 + end
  322 + end
  323 + end
  324 +
  325 + context "An attachment with erroring processor" do
  326 + setup do
  327 + rebuild_model :processor => [:thumbnail], :styles => { :small => '' }, :whiny_thumbnails => true
  328 + @dummy = Dummy.new
  329 + Paperclip::Thumbnail.expects(:make).raises(Paperclip::PaperclipError, "cannot be processed.")
  330 + @file = StringIO.new("...")
  331 + @file.stubs(:to_tempfile).returns(@file)
  332 + @dummy.avatar = @file
  333 + end
  334 +
  335 + should "correctly forward processing error message to the instance" do
  336 + @dummy.valid?
  337 + assert_contains @dummy.errors.full_messages, "Avatar cannot be processed."
  338 + end
  339 + end
  340 +
  341 + context "An attachment with multiple processors" do
  342 + setup do
  343 + class Paperclip::Test < Paperclip::Processor; end
  344 + @style_params = { :once => {:one => 1, :two => 2} }
  345 + rebuild_model :processors => [:thumbnail, :test], :styles => @style_params
  346 + @dummy = Dummy.new
  347 + @file = StringIO.new("...")
  348 + @file.stubs(:to_tempfile).returns(@file)
  349 + Paperclip::Test.stubs(:make).returns(@file)
  350 + Paperclip::Thumbnail.stubs(:make).returns(@file)
  351 + end
  352 +
  353 + context "when assigned" do
  354 + setup { @dummy.avatar = @file }
  355 +
  356 + before_should "call #make on all specified processors" do
  357 + expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
  358 + Paperclip::Thumbnail.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
  359 + Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
  360 + end
  361 +
  362 + before_should "call #make with attachment passed as third argument" do
  363 + expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
  364 + Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
  365 + end
  366 + end
  367 + end
  368 +
  369 + context "An attachment with no processors defined" do
  370 + setup do
  371 + rebuild_model :processors => [], :styles => {:something => 1}
  372 + @dummy = Dummy.new
  373 + @file = StringIO.new("...")
  374 + end
  375 + should "raise when assigned to" do
  376 + assert_raises(RuntimeError){ @dummy.avatar = @file }
  377 + end
  378 + end
  379 +
  380 + context "Assigning an attachment with post_process hooks" do
  381 + setup do
  382 + rebuild_model :styles => { :something => "100x100#" }
  383 + Dummy.class_eval do
  384 + before_avatar_post_process :do_before_avatar
  385 + after_avatar_post_process :do_after_avatar
  386 + before_post_process :do_before_all
  387 + after_post_process :do_after_all
  388 + def do_before_avatar; end
  389 + def do_after_avatar; end
  390 + def do_before_all; end
  391 + def do_after_all; end
  392 + end
  393 + @file = StringIO.new(".")
  394 + @file.stubs(:to_tempfile).returns(@file)
  395 + @dummy = Dummy.new
  396 + Paperclip::Thumbnail.stubs(:make).returns(@file)
  397 + @attachment = @dummy.avatar
  398 + end
  399 +
  400 + should "call the defined callbacks when assigned" do
  401 + @dummy.expects(:do_before_avatar).with()
  402 + @dummy.expects(:do_after_avatar).with()
  403 + @dummy.expects(:do_before_all).with()
  404 + @dummy.expects(:do_after_all).with()
  405 + Paperclip::Thumbnail.expects(:make).returns(@file)
  406 + @dummy.avatar = @file
  407 + end
  408 +
  409 + should "not cancel the processing if a before_post_process returns nil" do
  410 + @dummy.expects(:do_before_avatar).with().returns(nil)
  411 + @dummy.expects(:do_after_avatar).with()
  412 + @dummy.expects(:do_before_all).with().returns(nil)
  413 + @dummy.expects(:do_after_all).with()
  414 + Paperclip::Thumbnail.expects(:make).returns(@file)
  415 + @dummy.avatar = @file
  416 + end
  417 +
  418 + should "cancel the processing if a before_post_process returns false" do
  419 + @dummy.expects(:do_before_avatar).never
  420 + @dummy.expects(:do_after_avatar).never
  421 + @dummy.expects(:do_before_all).with().returns(false)
  422 + @dummy.expects(:do_after_all).never
  423 + Paperclip::Thumbnail.expects(:make).never
  424 + @dummy.avatar = @file
  425 + end
  426 +
  427 + should "cancel the processing if a before_avatar_post_process returns false" do
  428 + @dummy.expects(:do_before_avatar).with().returns(false)
  429 + @dummy.expects(:do_after_avatar).never
  430 + @dummy.expects(:do_before_all).with().returns(true)
  431 + @dummy.expects(:do_after_all).never
  432 + Paperclip::Thumbnail.expects(:make).never
  433 + @dummy.avatar = @file
  434 + end
  435 + end
  436 +
  437 + context "Assigning an attachment" do
  438 + setup do
  439 + rebuild_model :styles => { :something => "100x100#" }
  440 + @file = StringIO.new(".")
  441 + @file.expects(:original_filename).returns("5k.png\n\n")
  442 + @file.expects(:content_type).returns("image/png\n\n")
  443 + @file.stubs(:to_tempfile).returns(@file)
  444 + @dummy = Dummy.new
  445 + Paperclip::Thumbnail.expects(:make).returns(@file)
  446 + @dummy.expects(:run_callbacks).with(:before_avatar_post_process, {:original => @file})
  447 + @dummy.expects(:run_callbacks).with(:before_post_process, {:original => @file})
  448 + @dummy.expects(:run_callbacks).with(:after_avatar_post_process, {:original => @file, :something => @file})
  449 + @dummy.expects(:run_callbacks).with(:after_post_process, {:original => @file, :something => @file})
  450 + @attachment = @dummy.avatar
  451 + @dummy.avatar = @file
  452 + end
  453 +
  454 + should "strip whitespace from original_filename field" do
  455 + assert_equal "5k.png", @dummy.avatar.original_filename
  456 + end
  457 +
  458 + should "strip whitespace from content_type field" do
  459 + assert_equal "image/png", @dummy.avatar.instance.avatar_content_type
  460 + end
  461 + end
  462 +
  463 + context "Attachment with strange letters" do
  464 + setup do
  465 + rebuild_model
  466 +
  467 + @not_file = mock
  468 + @tempfile = mock
  469 + @not_file.stubs(:nil?).returns(false)
  470 + @not_file.expects(:size).returns(10)
  471 + @tempfile.expects(:size).returns(10)
  472 + @not_file.expects(:to_tempfile).returns(@tempfile)
  473 + @not_file.expects(:original_filename).returns("sheep_say_bæ.png\r\n")
  474 + @not_file.expects(:content_type).returns("image/png\r\n")
  475 +
  476 + @dummy = Dummy.new
  477 + @attachment = @dummy.avatar
  478 + @attachment.expects(:valid_assignment?).with(@not_file).returns(true)
  479 + @attachment.expects(:queue_existing_for_delete)
  480 + @attachment.expects(:post_process)
  481 + @attachment.expects(:valid?).returns(true)
  482 + @attachment.expects(:validate)
  483 + @dummy.avatar = @not_file
  484 + end
  485 +
  486 + should "remove strange letters and replace with underscore (_)" do
  487 + assert_equal "sheep_say_b_.png", @dummy.avatar.original_filename
  488 + end
  489 +
  490 + end
  491 +
  492 + context "An attachment" do
  493 + setup do
  494 + @old_defaults = Paperclip::Attachment.default_options.dup
  495 + Paperclip::Attachment.default_options.merge!({
  496 + :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
  497 + })
  498 + FileUtils.rm_rf("tmp")
  499 + rebuild_model
  500 + @instance = Dummy.new
  501 + @attachment = Paperclip::Attachment.new(:avatar, @instance)
  502 + @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
  503 + end
  504 +
  505 + teardown do
  506 + @file.close
  507 + Paperclip::Attachment.default_options.merge!(@old_defaults)
  508 + end
  509 +
  510 + should "raise if there are not the correct columns when you try to assign" do
  511 + @other_attachment = Paperclip::Attachment.new(:not_here, @instance)
  512 + assert_raises(Paperclip::PaperclipError) do
  513 + @other_attachment.assign(@file)
  514 + end
  515 + end
  516 +
  517 + should "return its default_url when no file assigned" do
  518 + assert @attachment.to_file.nil?
  519 + assert_equal "/avatars/original/missing.png", @attachment.url
  520 + assert_equal "/avatars/blah/missing.png", @attachment.url(:blah)
  521 + end
  522 +
  523 + should "return nil as path when no file assigned" do
  524 + assert @attachment.to_file.nil?
  525 + assert_equal nil, @attachment.path
  526 + assert_equal nil, @attachment.path(:blah)
  527 + end
  528 +
  529 + context "with a file assigned in the database" do
  530 + setup do
  531 + @attachment.stubs(:instance_read).with(:file_name).returns("5k.png")
  532 + @attachment.stubs(:instance_read).with(:content_type).returns("image/png")
  533 + @attachment.stubs(:instance_read).with(:file_size).returns(12345)
  534 + now = Time.now
  535 + Time.stubs(:now).returns(now)
  536 + @attachment.stubs(:instance_read).with(:updated_at).returns(Time.now)
  537 + end
  538 +
  539 + should "return a correct url even if the file does not exist" do
  540 + assert_nil @attachment.to_file
  541 + assert_match %r{^/system/avatars/#{@instance.id}/blah/5k\.png}, @attachment.url(:blah)
  542 + end
  543 +
  544 + should "make sure the updated_at mtime is in the url if it is defined" do
  545 + assert_match %r{#{Time.now.to_i}$}, @attachment.url(:blah)
  546 + end
  547 +
  548 + should "make sure the updated_at mtime is NOT in the url if false is passed to the url method" do
  549 + assert_no_match %r{#{Time.now.to_i}$}, @attachment.url(:blah, false)
  550 + end
  551 +
  552 + context "with the updated_at field removed" do
  553 + setup do
  554 + @attachment.stubs(:instance_read).with(:updated_at).returns(nil)
  555 + end
  556 +
  557 + should "only return the url without the updated_at when sent #url" do
  558 + assert_match "/avatars/#{@instance.id}/blah/5k.png", @attachment.url(:blah)
  559 + end
  560 + end
  561 +
  562 + should "return the proper path when filename has a single .'s" do
  563 + assert_equal File.expand_path("./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.png"), File.expand_path(@attachment.path)
  564 + end
  565 +
  566 + should "return the proper path when filename has multiple .'s" do
  567 + @attachment.stubs(:instance_read).with(:file_name).returns("5k.old.png")
  568 + assert_equal File.expand_path("./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.old.png"), File.expand_path(@attachment.path)
  569 + end
  570 +
  571 + context "when expecting three styles" do
  572 + setup do
  573 + styles = {:styles => { :large => ["400x400", :png],
  574 + :medium => ["100x100", :gif],
  575 + :small => ["32x32#", :jpg]}}
  576 + @attachment = Paperclip::Attachment.new(:avatar,
  577 + @instance,
  578 + styles)
  579 + end
  580 +
  581 + context "and assigned a file" do
  582 + setup do
  583 + now = Time.now
  584 + Time.stubs(:now).returns(now)
  585 + @attachment.assign(@file)
  586 + end
  587 +
  588 + should "be dirty" do
  589 + assert @attachment.dirty?
  590 + end
  591 +
  592 + context "and saved" do
  593 + setup do
  594 + @attachment.save
  595 + end
  596 +
  597 + should "return the real url" do
  598 + file = @attachment.to_file
  599 + assert file
  600 + assert_match %r{^/system/avatars/#{@instance.id}/original/5k\.png}, @attachment.url
  601 + assert_match %r{^/system/avatars/#{@instance.id}/small/5k\.jpg}, @attachment.url(:small)
  602 + file.close
  603 + end
  604 +
  605 + should "commit the files to disk" do
  606 + [:large, :medium, :small].each do |style|
  607 + io = @attachment.to_file(style)
  608 + assert File.exists?(io)
  609 + assert ! io.is_a?(::Tempfile)
  610 + io.close
  611 + end
  612 + end
  613 +
  614 + should "save the files as the right formats and sizes" do
  615 + [[:large, 400, 61, "PNG"],
  616 + [:medium, 100, 15, "GIF"],
  617 + [:small, 32, 32, "JPEG"]].each do |style|
  618 + cmd = %Q[identify -format "%w %h %b %m" "#{@attachment.path(style.first)}"]
  619 + out = `#{cmd}`
  620 + width, height, size, format = out.split(" ")
  621 + assert_equal style[1].to_s, width.to_s
  622 + assert_equal style[2].to_s, height.to_s
  623 + assert_equal style[3].to_s, format.to_s
  624 + end
  625 + end
  626 +
  627 + should "still have its #file attribute not be nil" do
  628 + assert ! (file = @attachment.to_file).nil?
  629 + file.close
  630 + end
  631 +
  632 + context "and trying to delete" do
  633 + setup do
  634 + @existing_names = @attachment.styles.keys.collect do |style|
  635 + @attachment.path(style)
  636 + end
  637 + end
  638 +
  639 + should "delete the files after assigning nil" do
  640 + @attachment.expects(:instance_write).with(:file_name, nil)
  641 + @attachment.expects(:instance_write).with(:content_type, nil)
  642 + @attachment.expects(:instance_write).with(:file_size, nil)
  643 + @attachment.expects(:instance_write).with(:updated_at, nil)
  644 + @attachment.assign nil
  645 + @attachment.save
  646 + @existing_names.each{|f| assert ! File.exists?(f) }
  647 + end
  648 +
  649 + should "delete the files when you call #clear and #save" do
  650 + @attachment.expects(:instance_write).with(:file_name, nil)
  651 + @attachment.expects(:instance_write).with(:content_type, nil)
  652 + @attachment.expects(:instance_write).with(:file_size, nil)
  653 + @attachment.expects(:instance_write).with(:updated_at, nil)
  654 + @attachment.clear
  655 + @attachment.save
  656 + @existing_names.each{|f| assert ! File.exists?(f) }
  657 + end
  658 +
  659 + should "delete the files when you call #delete" do
  660 + @attachment.expects(:instance_write).with(:file_name, nil)
  661 + @attachment.expects(:instance_write).with(:content_type, nil)
  662 + @attachment.expects(:instance_write).with(:file_size, nil)
  663 + @attachment.expects(:instance_write).with(:updated_at, nil)
  664 + @attachment.destroy
  665 + @existing_names.each{|f| assert ! File.exists?(f) }
  666 + end
  667 + end
  668 + end
  669 + end
  670 + end
  671 +
  672 + end
  673 +
  674 + context "when trying a nonexistant storage type" do
  675 + setup do
  676 + rebuild_model :storage => :not_here
  677 + end
  678 +
  679 + should "not be able to find the module" do
  680 + assert_raise(NameError){ Dummy.new.avatar }
  681 + end
  682 + end
  683 + end
  684 +
  685 + context "An attachment with only a avatar_file_name column" do
  686 + setup do
  687 + ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
  688 + table.column :avatar_file_name, :string
  689 + end
  690 + rebuild_class
  691 + @dummy = Dummy.new
  692 + @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
  693 + end
  694 +
  695 + teardown { @file.close }
  696 +
  697 + should "not error when assigned an attachment" do
  698 + assert_nothing_raised { @dummy.avatar = @file }
  699 + end
  700 +
  701 + should "return the time when sent #avatar_updated_at" do
  702 + now = Time.now
  703 + Time.stubs(:now).returns(now)
  704 + @dummy.avatar = @file
  705 + assert now, @dummy.avatar.updated_at
  706 + end
  707 +
  708 + should "return nil when reloaded and sent #avatar_updated_at" do
  709 + @dummy.save
  710 + @dummy.reload
  711 + assert_nil @dummy.avatar.updated_at
  712 + end
  713 +
  714 + should "return the right value when sent #avatar_file_size" do
  715 + @dummy.avatar = @file
  716 + assert_equal @file.size, @dummy.avatar.size
  717 + end
  718 +
  719 + context "and avatar_updated_at column" do
  720 + setup do
  721 + ActiveRecord::Base.connection.add_column :dummies, :avatar_updated_at, :timestamp
  722 + rebuild_class
  723 + @dummy = Dummy.new
  724 + end
  725 +
  726 + should "not error when assigned an attachment" do
  727 + assert_nothing_raised { @dummy.avatar = @file }
  728 + end
  729 +
  730 + should "return the right value when sent #avatar_updated_at" do
  731 + now = Time.now
  732 + Time.stubs(:now).returns(now)
  733 + @dummy.avatar = @file
  734 + assert_equal now.to_i, @dummy.avatar.updated_at
  735 + end
  736 + end
  737 +
  738 + context "and avatar_content_type column" do
  739 + setup do
  740 + ActiveRecord::Base.connection.add_column :dummies, :avatar_content_type, :string
  741 + rebuild_class
  742 + @dummy = Dummy.new
  743 + end
  744 +
  745 + should "not error when assigned an attachment" do
  746 + assert_nothing_raised { @dummy.avatar = @file }
  747 + end
  748 +
  749 + should "return the right value when sent #avatar_content_type" do
  750 + @dummy.avatar = @file
  751 + assert_equal "image/png", @dummy.avatar.content_type
  752 + end
  753 + end
  754 +
  755 + context "and avatar_file_size column" do
  756 + setup do
  757 + ActiveRecord::Base.connection.add_column :dummies, :avatar_file_size, :integer
  758 + rebuild_class
  759 + @dummy = Dummy.new
  760 + end
  761 +
  762 + should "not error when assigned an attachment" do
  763 + assert_nothing_raised { @dummy.avatar = @file }
  764 + end
  765 +
  766 + should "return the right value when sent #avatar_file_size" do
  767 + @dummy.avatar = @file
  768 + assert_equal @file.size, @dummy.avatar.size
  769 + end
  770 +
  771 + should "return the right value when saved, reloaded, and sent #avatar_file_size" do
  772 + @dummy.avatar = @file
  773 + @dummy.save
  774 + @dummy = Dummy.find(@dummy.id)
  775 + assert_equal @file.size, @dummy.avatar.size
  776 + end
  777 + end
  778 + end
  779 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/database.yml 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +test:
  2 + adapter: sqlite3
  3 + database: ":memory:"
  4 +
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/fixtures/12k.png 0 → 100644

11.8 KB

vendor/gems/tristandunn-paperclip-2.3.1/test/fixtures/50x50.png 0 → 100644

1.58 KB

vendor/gems/tristandunn-paperclip-2.3.1/test/fixtures/5k.png 0 → 100644

4.35 KB

vendor/gems/tristandunn-paperclip-2.3.1/test/fixtures/bad.png 0 → 100644
... ... @@ -0,0 +1 @@
  1 +This is not an image.
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/fixtures/s3.yml 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +development:
  2 + key: 54321
  3 +production:
  4 + key: 12345
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/fixtures/text.txt 0 → 100644
vendor/gems/tristandunn-paperclip-2.3.1/test/fixtures/twopage.pdf 0 → 100644
No preview for this file type
vendor/gems/tristandunn-paperclip-2.3.1/test/geometry_test.rb 0 → 100644
... ... @@ -0,0 +1,177 @@
  1 +require 'test/helper'
  2 +
  3 +class GeometryTest < Test::Unit::TestCase
  4 + context "Paperclip::Geometry" do
  5 + should "correctly report its given dimensions" do
  6 + assert @geo = Paperclip::Geometry.new(1024, 768)
  7 + assert_equal 1024, @geo.width
  8 + assert_equal 768, @geo.height
  9 + end
  10 +
  11 + should "set height to 0 if height dimension is missing" do
  12 + assert @geo = Paperclip::Geometry.new(1024)
  13 + assert_equal 1024, @geo.width
  14 + assert_equal 0, @geo.height
  15 + end
  16 +
  17 + should "set width to 0 if width dimension is missing" do
  18 + assert @geo = Paperclip::Geometry.new(nil, 768)
  19 + assert_equal 0, @geo.width
  20 + assert_equal 768, @geo.height
  21 + end
  22 +
  23 + should "be generated from a WxH-formatted string" do
  24 + assert @geo = Paperclip::Geometry.parse("800x600")
  25 + assert_equal 800, @geo.width
  26 + assert_equal 600, @geo.height
  27 + end
  28 +
  29 + should "be generated from a xH-formatted string" do
  30 + assert @geo = Paperclip::Geometry.parse("x600")
  31 + assert_equal 0, @geo.width
  32 + assert_equal 600, @geo.height
  33 + end
  34 +
  35 + should "be generated from a Wx-formatted string" do
  36 + assert @geo = Paperclip::Geometry.parse("800x")
  37 + assert_equal 800, @geo.width
  38 + assert_equal 0, @geo.height
  39 + end
  40 +
  41 + should "be generated from a W-formatted string" do
  42 + assert @geo = Paperclip::Geometry.parse("800")
  43 + assert_equal 800, @geo.width
  44 + assert_equal 0, @geo.height
  45 + end
  46 +
  47 + should "ensure the modifier is nil if not present" do
  48 + assert @geo = Paperclip::Geometry.parse("123x456")
  49 + assert_nil @geo.modifier
  50 + end
  51 +
  52 + should "treat x and X the same in geometries" do
  53 + @lower = Paperclip::Geometry.parse("123x456")
  54 + @upper = Paperclip::Geometry.parse("123X456")
  55 + assert_equal 123, @lower.width
  56 + assert_equal 123, @upper.width
  57 + assert_equal 456, @lower.height
  58 + assert_equal 456, @upper.height
  59 + end
  60 +
  61 + ['>', '<', '#', '@', '%', '^', '!', nil].each do |mod|
  62 + should "ensure the modifier #{mod.inspect} is preserved" do
  63 + assert @geo = Paperclip::Geometry.parse("123x456#{mod}")
  64 + assert_equal mod, @geo.modifier
  65 + assert_equal "123x456#{mod}", @geo.to_s
  66 + end
  67 + end
  68 +
  69 + ['>', '<', '#', '@', '%', '^', '!', nil].each do |mod|
  70 + should "ensure the modifier #{mod.inspect} is preserved with no height" do
  71 + assert @geo = Paperclip::Geometry.parse("123x#{mod}")
  72 + assert_equal mod, @geo.modifier
  73 + assert_equal "123#{mod}", @geo.to_s
  74 + end
  75 + end
  76 +
  77 + should "make sure the modifier gets passed during transformation_to" do
  78 + assert @src = Paperclip::Geometry.parse("123x456")
  79 + assert @dst = Paperclip::Geometry.parse("123x456>")
  80 + assert_equal ["123x456>", nil], @src.transformation_to(@dst)
  81 + end
  82 +
  83 + should "generate correct ImageMagick formatting string for W-formatted string" do
  84 + assert @geo = Paperclip::Geometry.parse("800")
  85 + assert_equal "800", @geo.to_s
  86 + end
  87 +
  88 + should "generate correct ImageMagick formatting string for Wx-formatted string" do
  89 + assert @geo = Paperclip::Geometry.parse("800x")
  90 + assert_equal "800", @geo.to_s
  91 + end
  92 +
  93 + should "generate correct ImageMagick formatting string for xH-formatted string" do
  94 + assert @geo = Paperclip::Geometry.parse("x600")
  95 + assert_equal "x600", @geo.to_s
  96 + end
  97 +
  98 + should "generate correct ImageMagick formatting string for WxH-formatted string" do
  99 + assert @geo = Paperclip::Geometry.parse("800x600")
  100 + assert_equal "800x600", @geo.to_s
  101 + end
  102 +
  103 + should "be generated from a file" do
  104 + file = File.join(File.dirname(__FILE__), "fixtures", "5k.png")
  105 + file = File.new(file, 'rb')
  106 + assert_nothing_raised{ @geo = Paperclip::Geometry.from_file(file) }
  107 + assert @geo.height > 0
  108 + assert @geo.width > 0
  109 + end
  110 +
  111 + should "be generated from a file path" do
  112 + file = File.join(File.dirname(__FILE__), "fixtures", "5k.png")
  113 + assert_nothing_raised{ @geo = Paperclip::Geometry.from_file(file) }
  114 + assert @geo.height > 0
  115 + assert @geo.width > 0
  116 + end
  117 +
  118 + should "not generate from a bad file" do
  119 + file = "/home/This File Does Not Exist.omg"
  120 + assert_raise(Paperclip::NotIdentifiedByImageMagickError){ @geo = Paperclip::Geometry.from_file(file) }
  121 + end
  122 +
  123 + [['vertical', 900, 1440, true, false, false, 1440, 900, 0.625],
  124 + ['horizontal', 1024, 768, false, true, false, 1024, 768, 1.3333],
  125 + ['square', 100, 100, false, false, true, 100, 100, 1]].each do |args|
  126 + context "performing calculations on a #{args[0]} viewport" do
  127 + setup do
  128 + @geo = Paperclip::Geometry.new(args[1], args[2])
  129 + end
  130 +
  131 + should "#{args[3] ? "" : "not"} be vertical" do
  132 + assert_equal args[3], @geo.vertical?
  133 + end
  134 +
  135 + should "#{args[4] ? "" : "not"} be horizontal" do
  136 + assert_equal args[4], @geo.horizontal?
  137 + end
  138 +
  139 + should "#{args[5] ? "" : "not"} be square" do
  140 + assert_equal args[5], @geo.square?
  141 + end
  142 +
  143 + should "report that #{args[6]} is the larger dimension" do
  144 + assert_equal args[6], @geo.larger
  145 + end
  146 +
  147 + should "report that #{args[7]} is the smaller dimension" do
  148 + assert_equal args[7], @geo.smaller
  149 + end
  150 +
  151 + should "have an aspect ratio of #{args[8]}" do
  152 + assert_in_delta args[8], @geo.aspect, 0.0001
  153 + end
  154 + end
  155 + end
  156 +
  157 + [[ [1000, 100], [64, 64], "x64", "64x64+288+0" ],
  158 + [ [100, 1000], [50, 950], "x950", "50x950+22+0" ],
  159 + [ [100, 1000], [50, 25], "50x", "50x25+0+237" ]]. each do |args|
  160 + context "of #{args[0].inspect} and given a Geometry #{args[1].inspect} and sent transform_to" do
  161 + setup do
  162 + @geo = Paperclip::Geometry.new(*args[0])
  163 + @dst = Paperclip::Geometry.new(*args[1])
  164 + @scale, @crop = @geo.transformation_to @dst, true
  165 + end
  166 +
  167 + should "be able to return the correct scaling transformation geometry #{args[2]}" do
  168 + assert_equal args[2], @scale
  169 + end
  170 +
  171 + should "be able to return the correct crop transformation geometry #{args[3]}" do
  172 + assert_equal args[3], @crop
  173 + end
  174 + end
  175 + end
  176 + end
  177 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/helper.rb 0 → 100644
... ... @@ -0,0 +1,99 @@
  1 +require 'rubygems'
  2 +require 'test/unit'
  3 +require 'shoulda'
  4 +require 'mocha'
  5 +require 'tempfile'
  6 +
  7 +gem 'sqlite3-ruby'
  8 +
  9 +require 'active_record'
  10 +require 'active_support'
  11 +begin
  12 + require 'ruby-debug'
  13 +rescue LoadError
  14 + puts "ruby-debug not loaded"
  15 +end
  16 +
  17 +ROOT = File.join(File.dirname(__FILE__), '..')
  18 +RAILS_ROOT = ROOT
  19 +RAILS_ENV = "test"
  20 +
  21 +$LOAD_PATH << File.join(ROOT, 'lib')
  22 +$LOAD_PATH << File.join(ROOT, 'lib', 'paperclip')
  23 +
  24 +require File.join(ROOT, 'lib', 'paperclip.rb')
  25 +
  26 +require 'shoulda_macros/paperclip'
  27 +
  28 +FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
  29 +config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
  30 +ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
  31 +ActiveRecord::Base.establish_connection(config['test'])
  32 +
  33 +def reset_class class_name
  34 + ActiveRecord::Base.send(:include, Paperclip)
  35 + Object.send(:remove_const, class_name) rescue nil
  36 + klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
  37 + klass.class_eval{ include Paperclip }
  38 + klass
  39 +end
  40 +
  41 +def reset_table table_name, &block
  42 + block ||= lambda { |table| true }
  43 + ActiveRecord::Base.connection.create_table :dummies, {:force => true}, &block
  44 +end
  45 +
  46 +def modify_table table_name, &block
  47 + ActiveRecord::Base.connection.change_table :dummies, &block
  48 +end
  49 +
  50 +def rebuild_model options = {}
  51 + ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
  52 + table.column :other, :string
  53 + table.column :avatar_file_name, :string
  54 + table.column :avatar_content_type, :string
  55 + table.column :avatar_file_size, :integer
  56 + table.column :avatar_updated_at, :datetime
  57 + end
  58 + rebuild_class options
  59 +end
  60 +
  61 +def rebuild_class options = {}
  62 + ActiveRecord::Base.send(:include, Paperclip)
  63 + Object.send(:remove_const, "Dummy") rescue nil
  64 + Object.const_set("Dummy", Class.new(ActiveRecord::Base))
  65 + Dummy.class_eval do
  66 + include Paperclip
  67 + has_attached_file :avatar, options
  68 + end
  69 +end
  70 +
  71 +def temporary_rails_env(new_env)
  72 + old_env = Object.const_defined?("RAILS_ENV") ? RAILS_ENV : nil
  73 + silence_warnings do
  74 + Object.const_set("RAILS_ENV", new_env)
  75 + end
  76 + yield
  77 + silence_warnings do
  78 + Object.const_set("RAILS_ENV", old_env)
  79 + end
  80 +end
  81 +
  82 +class FakeModel
  83 + attr_accessor :avatar_file_name,
  84 + :avatar_file_size,
  85 + :avatar_last_updated,
  86 + :avatar_content_type,
  87 + :id
  88 +
  89 + def errors
  90 + @errors ||= []
  91 + end
  92 +
  93 + def run_callbacks name, *args
  94 + end
  95 +end
  96 +
  97 +def attachment options
  98 + Paperclip::Attachment.new(:avatar, FakeModel.new, options)
  99 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/integration_test.rb 0 → 100644
... ... @@ -0,0 +1,483 @@
  1 +require 'test/helper'
  2 +
  3 +class IntegrationTest < Test::Unit::TestCase
  4 + context "Many models at once" do
  5 + setup do
  6 + rebuild_model
  7 + @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
  8 + 300.times do |i|
  9 + Dummy.create! :avatar => @file
  10 + end
  11 + end
  12 +
  13 + should "not exceed the open file limit" do
  14 + assert_nothing_raised do
  15 + dummies = Dummy.find(:all)
  16 + dummies.each { |dummy| dummy.avatar }
  17 + end
  18 + end
  19 + end
  20 +
  21 + context "An attachment" do
  22 + setup do
  23 + rebuild_model :styles => { :thumb => "50x50#" }
  24 + @dummy = Dummy.new
  25 + @file = File.new(File.join(File.dirname(__FILE__),
  26 + "fixtures",
  27 + "5k.png"), 'rb')
  28 + @dummy.avatar = @file
  29 + assert @dummy.save
  30 + end
  31 +
  32 + teardown { @file.close }
  33 +
  34 + should "create its thumbnails properly" do
  35 + assert_match /\b50x50\b/, `identify "#{@dummy.avatar.path(:thumb)}"`
  36 + end
  37 +
  38 + context "redefining its attachment styles" do
  39 + setup do
  40 + Dummy.class_eval do
  41 + has_attached_file :avatar, :styles => { :thumb => "150x25#" }
  42 + has_attached_file :avatar, :styles => { :thumb => "150x25#", :dynamic => lambda { |a| '50x50#' } }
  43 + end
  44 + @d2 = Dummy.find(@dummy.id)
  45 + @d2.avatar.reprocess!
  46 + @d2.save
  47 + end
  48 +
  49 + should "create its thumbnails properly" do
  50 + assert_match /\b150x25\b/, `identify "#{@dummy.avatar.path(:thumb)}"`
  51 + assert_match /\b50x50\b/, `identify "#{@dummy.avatar.path(:dynamic)}"`
  52 + end
  53 + end
  54 + end
  55 +
  56 + context "A model that modifies its original" do
  57 + setup do
  58 + rebuild_model :styles => { :original => "2x2#" }
  59 + @dummy = Dummy.new
  60 + @file = File.new(File.join(File.dirname(__FILE__),
  61 + "fixtures",
  62 + "5k.png"), 'rb')
  63 + @dummy.avatar = @file
  64 + end
  65 +
  66 + should "report the file size of the processed file and not the original" do
  67 + assert_not_equal @file.size, @dummy.avatar.size
  68 + end
  69 +
  70 + teardown { @file.close }
  71 + end
  72 +
  73 + context "A model with attachments scoped under an id" do
  74 + setup do
  75 + rebuild_model :styles => { :large => "100x100",
  76 + :medium => "50x50" },
  77 + :path => ":rails_root/tmp/:id/:attachments/:style.:extension"
  78 + @dummy = Dummy.new
  79 + @file = File.new(File.join(File.dirname(__FILE__),
  80 + "fixtures",
  81 + "5k.png"), 'rb')
  82 + @dummy.avatar = @file
  83 + end
  84 +
  85 + teardown { @file.close }
  86 +
  87 + context "when saved" do
  88 + setup do
  89 + @dummy.save
  90 + @saved_path = @dummy.avatar.path(:large)
  91 + end
  92 +
  93 + should "have a large file in the right place" do
  94 + assert File.exists?(@dummy.avatar.path(:large))
  95 + end
  96 +
  97 + context "and deleted" do
  98 + setup do
  99 + @dummy.avatar.clear
  100 + @dummy.save
  101 + end
  102 +
  103 + should "not have a large file in the right place anymore" do
  104 + assert ! File.exists?(@saved_path)
  105 + end
  106 +
  107 + should "not have its next two parent directories" do
  108 + assert ! File.exists?(File.dirname(@saved_path))
  109 + assert ! File.exists?(File.dirname(File.dirname(@saved_path)))
  110 + end
  111 +
  112 + before_should "not die if an unexpected SystemCallError happens" do
  113 + FileUtils.stubs(:rmdir).raises(Errno::EPIPE)
  114 + end
  115 + end
  116 + end
  117 + end
  118 +
  119 + context "A model with no attachment validation" do
  120 + setup do
  121 + rebuild_model :styles => { :large => "300x300>",
  122 + :medium => "100x100",
  123 + :thumb => ["32x32#", :gif] },
  124 + :default_style => :medium,
  125 + :url => "/:attachment/:class/:style/:id/:basename.:extension",
  126 + :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
  127 + @dummy = Dummy.new
  128 + end
  129 +
  130 + should "have its definition return false when asked about whiny_thumbnails" do
  131 + assert ! Dummy.attachment_definitions[:avatar][:whiny_thumbnails]
  132 + end
  133 +
  134 + context "when validates_attachment_thumbnails is called" do
  135 + setup do
  136 + Dummy.validates_attachment_thumbnails :avatar
  137 + end
  138 +
  139 + should "have its definition return true when asked about whiny_thumbnails" do
  140 + assert_equal true, Dummy.attachment_definitions[:avatar][:whiny_thumbnails]
  141 + end
  142 + end
  143 +
  144 + context "redefined to have attachment validations" do
  145 + setup do
  146 + rebuild_model :styles => { :large => "300x300>",
  147 + :medium => "100x100",
  148 + :thumb => ["32x32#", :gif] },
  149 + :whiny_thumbnails => true,
  150 + :default_style => :medium,
  151 + :url => "/:attachment/:class/:style/:id/:basename.:extension",
  152 + :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
  153 + end
  154 +
  155 + should "have its definition return true when asked about whiny_thumbnails" do
  156 + assert_equal true, Dummy.attachment_definitions[:avatar][:whiny_thumbnails]
  157 + end
  158 + end
  159 + end
  160 +
  161 + context "A model with no convert_options setting" do
  162 + setup do
  163 + rebuild_model :styles => { :large => "300x300>",
  164 + :medium => "100x100",
  165 + :thumb => ["32x32#", :gif] },
  166 + :default_style => :medium,
  167 + :url => "/:attachment/:class/:style/:id/:basename.:extension",
  168 + :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
  169 + @dummy = Dummy.new
  170 + end
  171 +
  172 + should "have its definition return nil when asked about convert_options" do
  173 + assert ! Dummy.attachment_definitions[:avatar][:convert_options]
  174 + end
  175 +
  176 + context "redefined to have convert_options setting" do
  177 + setup do
  178 + rebuild_model :styles => { :large => "300x300>",
  179 + :medium => "100x100",
  180 + :thumb => ["32x32#", :gif] },
  181 + :convert_options => "-strip -depth 8",
  182 + :default_style => :medium,
  183 + :url => "/:attachment/:class/:style/:id/:basename.:extension",
  184 + :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
  185 + end
  186 +
  187 + should "have its definition return convert_options value when asked about convert_options" do
  188 + assert_equal "-strip -depth 8", Dummy.attachment_definitions[:avatar][:convert_options]
  189 + end
  190 + end
  191 + end
  192 +
  193 + context "A model with a filesystem attachment" do
  194 + setup do
  195 + rebuild_model :styles => { :large => "300x300>",
  196 + :medium => "100x100",
  197 + :thumb => ["32x32#", :gif] },
  198 + :whiny_thumbnails => true,
  199 + :default_style => :medium,
  200 + :url => "/:attachment/:class/:style/:id/:basename.:extension",
  201 + :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
  202 + @dummy = Dummy.new
  203 + @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
  204 + @bad_file = File.new(File.join(FIXTURES_DIR, "bad.png"), 'rb')
  205 +
  206 + assert @dummy.avatar = @file
  207 + assert @dummy.valid?
  208 + assert @dummy.save
  209 + end
  210 +
  211 + should "write and delete its files" do
  212 + [["434x66", :original],
  213 + ["300x46", :large],
  214 + ["100x15", :medium],
  215 + ["32x32", :thumb]].each do |geo, style|
  216 + cmd = %Q[identify -format "%wx%h" "#{@dummy.avatar.path(style)}"]
  217 + assert_equal geo, `#{cmd}`.chomp, cmd
  218 + end
  219 +
  220 + saved_paths = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.path(s) }
  221 +
  222 + @d2 = Dummy.find(@dummy.id)
  223 + assert_equal "100x15", `identify -format "%wx%h" "#{@d2.avatar.path}"`.chomp
  224 + assert_equal "434x66", `identify -format "%wx%h" "#{@d2.avatar.path(:original)}"`.chomp
  225 + assert_equal "300x46", `identify -format "%wx%h" "#{@d2.avatar.path(:large)}"`.chomp
  226 + assert_equal "100x15", `identify -format "%wx%h" "#{@d2.avatar.path(:medium)}"`.chomp
  227 + assert_equal "32x32", `identify -format "%wx%h" "#{@d2.avatar.path(:thumb)}"`.chomp
  228 +
  229 + @dummy.avatar = "not a valid file but not nil"
  230 + assert_equal File.basename(@file.path), @dummy.avatar_file_name
  231 + assert @dummy.valid?
  232 + assert @dummy.save
  233 +
  234 + saved_paths.each do |p|
  235 + assert File.exists?(p)
  236 + end
  237 +
  238 + @dummy.avatar.clear
  239 + assert_nil @dummy.avatar_file_name
  240 + assert @dummy.valid?
  241 + assert @dummy.save
  242 +
  243 + saved_paths.each do |p|
  244 + assert ! File.exists?(p)
  245 + end
  246 +
  247 + @d2 = Dummy.find(@dummy.id)
  248 + assert_nil @d2.avatar_file_name
  249 + end
  250 +
  251 + should "work exactly the same when new as when reloaded" do
  252 + @d2 = Dummy.find(@dummy.id)
  253 +
  254 + assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
  255 + [:thumb, :medium, :large, :original].each do |style|
  256 + assert_equal @dummy.avatar.path(style), @d2.avatar.path(style)
  257 + end
  258 +
  259 + saved_paths = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.path(s) }
  260 +
  261 + @d2.avatar.clear
  262 + assert @d2.save
  263 +
  264 + saved_paths.each do |p|
  265 + assert ! File.exists?(p)
  266 + end
  267 + end
  268 +
  269 + should "know the difference between good files, bad files, and not files" do
  270 + expected = @dummy.avatar.to_file
  271 + @dummy.avatar = "not a file"
  272 + assert @dummy.valid?
  273 + assert_equal expected.path, @dummy.avatar.path
  274 + expected.close
  275 +
  276 + @dummy.avatar = @bad_file
  277 + assert ! @dummy.valid?
  278 + end
  279 +
  280 + should "know the difference between good files, bad files, and not files when validating" do
  281 + Dummy.validates_attachment_presence :avatar
  282 + @d2 = Dummy.find(@dummy.id)
  283 + @d2.avatar = @file
  284 + assert @d2.valid?, @d2.errors.full_messages.inspect
  285 + @d2.avatar = @bad_file
  286 + assert ! @d2.valid?
  287 + end
  288 +
  289 + should "be able to reload without saving and not have the file disappear" do
  290 + @dummy.avatar = @file
  291 + assert @dummy.save
  292 + @dummy.avatar.clear
  293 + assert_nil @dummy.avatar_file_name
  294 + @dummy.reload
  295 + assert_equal "5k.png", @dummy.avatar_file_name
  296 + end
  297 +
  298 + context "that is assigned its file from another Paperclip attachment" do
  299 + setup do
  300 + @dummy2 = Dummy.new
  301 + @file2 = File.new(File.join(FIXTURES_DIR, "12k.png"), 'rb')
  302 + assert @dummy2.avatar = @file2
  303 + @dummy2.save
  304 + end
  305 +
  306 + should "work when assigned a file" do
  307 + assert_not_equal `identify -format "%wx%h" "#{@dummy.avatar.path(:original)}"`,
  308 + `identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
  309 +
  310 + assert @dummy.avatar = @dummy2.avatar
  311 + @dummy.save
  312 + assert_equal `identify -format "%wx%h" "#{@dummy.avatar.path(:original)}"`,
  313 + `identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
  314 + end
  315 + end
  316 +
  317 + end
  318 +
  319 + context "A model with an attachments association and a Paperclip attachment" do
  320 + setup do
  321 + Dummy.class_eval do
  322 + has_many :attachments, :class_name => 'Dummy'
  323 + end
  324 +
  325 + @dummy = Dummy.new
  326 + @dummy.avatar = File.new(File.join(File.dirname(__FILE__),
  327 + "fixtures",
  328 + "5k.png"), 'rb')
  329 + end
  330 +
  331 + should "should not error when saving" do
  332 + assert_nothing_raised do
  333 + @dummy.save!
  334 + end
  335 + end
  336 + end
  337 +
  338 + if ENV['S3_TEST_BUCKET']
  339 + def s3_files_for attachment
  340 + [:thumb, :medium, :large, :original].inject({}) do |files, style|
  341 + data = `curl "#{attachment.url(style)}" 2>/dev/null`.chomp
  342 + t = Tempfile.new("paperclip-test")
  343 + t.binmode
  344 + t.write(data)
  345 + t.rewind
  346 + files[style] = t
  347 + files
  348 + end
  349 + end
  350 +
  351 + def s3_headers_for attachment, style
  352 + `curl --head "#{attachment.url(style)}" 2>/dev/null`.split("\n").inject({}) do |h,head|
  353 + split_head = head.chomp.split(/\s*:\s*/, 2)
  354 + h[split_head.first.downcase] = split_head.last unless split_head.empty?
  355 + h
  356 + end
  357 + end
  358 +
  359 + context "A model with an S3 attachment" do
  360 + setup do
  361 + rebuild_model :styles => { :large => "300x300>",
  362 + :medium => "100x100",
  363 + :thumb => ["32x32#", :gif] },
  364 + :storage => :s3,
  365 + :whiny_thumbnails => true,
  366 + # :s3_options => {:logger => Logger.new(StringIO.new)},
  367 + :s3_credentials => File.new(File.join(File.dirname(__FILE__), "s3.yml")),
  368 + :default_style => :medium,
  369 + :bucket => ENV['S3_TEST_BUCKET'],
  370 + :path => ":class/:attachment/:id/:style/:basename.:extension"
  371 + @dummy = Dummy.new
  372 + @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
  373 + @bad_file = File.new(File.join(FIXTURES_DIR, "bad.png"), 'rb')
  374 +
  375 + assert @dummy.avatar = @file
  376 + assert @dummy.valid?
  377 + assert @dummy.save
  378 +
  379 + @files_on_s3 = s3_files_for @dummy.avatar
  380 + end
  381 +
  382 + should "have the same contents as the original" do
  383 + @file.rewind
  384 + assert_equal @file.read, @files_on_s3[:original].read
  385 + end
  386 +
  387 + should "write and delete its files" do
  388 + [["434x66", :original],
  389 + ["300x46", :large],
  390 + ["100x15", :medium],
  391 + ["32x32", :thumb]].each do |geo, style|
  392 + cmd = %Q[identify -format "%wx%h" "#{@files_on_s3[style].path}"]
  393 + assert_equal geo, `#{cmd}`.chomp, cmd
  394 + end
  395 +
  396 + @d2 = Dummy.find(@dummy.id)
  397 + @d2_files = s3_files_for @d2.avatar
  398 + [["434x66", :original],
  399 + ["300x46", :large],
  400 + ["100x15", :medium],
  401 + ["32x32", :thumb]].each do |geo, style|
  402 + cmd = %Q[identify -format "%wx%h" "#{@d2_files[style].path}"]
  403 + assert_equal geo, `#{cmd}`.chomp, cmd
  404 + end
  405 +
  406 + @dummy.avatar = "not a valid file but not nil"
  407 + assert_equal File.basename(@file.path), @dummy.avatar_file_name
  408 + assert @dummy.valid?
  409 + assert @dummy.save
  410 +
  411 + [:thumb, :medium, :large, :original].each do |style|
  412 + assert @dummy.avatar.exists?(style)
  413 + end
  414 +
  415 + @dummy.avatar.clear
  416 + assert_nil @dummy.avatar_file_name
  417 + assert @dummy.valid?
  418 + assert @dummy.save
  419 +
  420 + [:thumb, :medium, :large, :original].each do |style|
  421 + assert ! @dummy.avatar.exists?(style)
  422 + end
  423 +
  424 + @d2 = Dummy.find(@dummy.id)
  425 + assert_nil @d2.avatar_file_name
  426 + end
  427 +
  428 + should "work exactly the same when new as when reloaded" do
  429 + @d2 = Dummy.find(@dummy.id)
  430 +
  431 + assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
  432 + [:thumb, :medium, :large, :original].each do |style|
  433 + assert_equal @dummy.avatar.to_file(style).read, @d2.avatar.to_file(style).read
  434 + end
  435 +
  436 + saved_keys = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s) }
  437 +
  438 + @d2.avatar.clear
  439 + assert @d2.save
  440 +
  441 + [:thumb, :medium, :large, :original].each do |style|
  442 + assert ! @dummy.avatar.exists?(style)
  443 + end
  444 + end
  445 +
  446 + should "know the difference between good files, bad files, not files, and nil" do
  447 + expected = @dummy.avatar.to_file
  448 + @dummy.avatar = "not a file"
  449 + assert @dummy.valid?
  450 + assert_equal expected.read, @dummy.avatar.to_file.read
  451 +
  452 + @dummy.avatar = @bad_file
  453 + assert ! @dummy.valid?
  454 + @dummy.avatar = nil
  455 + assert @dummy.valid?
  456 +
  457 + Dummy.validates_attachment_presence :avatar
  458 + @d2 = Dummy.find(@dummy.id)
  459 + @d2.avatar = @file
  460 + assert @d2.valid?
  461 + @d2.avatar = @bad_file
  462 + assert ! @d2.valid?
  463 + @d2.avatar = nil
  464 + assert ! @d2.valid?
  465 + end
  466 +
  467 + should "be able to reload without saving and not have the file disappear" do
  468 + @dummy.avatar = @file
  469 + assert @dummy.save
  470 + @dummy.avatar = nil
  471 + assert_nil @dummy.avatar_file_name
  472 + @dummy.reload
  473 + assert_equal "5k.png", @dummy.avatar_file_name
  474 + end
  475 +
  476 + should "have the right content type" do
  477 + headers = s3_headers_for(@dummy.avatar, :original)
  478 + assert_equal 'image/png', headers['content-type']
  479 + end
  480 + end
  481 + end
  482 +end
  483 +
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/interpolations_test.rb 0 → 100644
... ... @@ -0,0 +1,120 @@
  1 +require 'test/helper'
  2 +
  3 +class InterpolationsTest < Test::Unit::TestCase
  4 + should "return all methods but the infrastructure when sent #all" do
  5 + methods = Paperclip::Interpolations.all
  6 + assert ! methods.include?(:[])
  7 + assert ! methods.include?(:[]=)
  8 + assert ! methods.include?(:all)
  9 + methods.each do |m|
  10 + assert Paperclip::Interpolations.respond_to? m
  11 + end
  12 + end
  13 +
  14 + should "return the RAILS_ROOT" do
  15 + assert_equal RAILS_ROOT, Paperclip::Interpolations.rails_root(:attachment, :style)
  16 + end
  17 +
  18 + should "return the RAILS_ENV" do
  19 + assert_equal RAILS_ENV, Paperclip::Interpolations.rails_env(:attachment, :style)
  20 + end
  21 +
  22 + should "return the class of the instance" do
  23 + attachment = mock
  24 + attachment.expects(:instance).returns(attachment)
  25 + attachment.expects(:class).returns("Thing")
  26 + assert_equal "things", Paperclip::Interpolations.class(attachment, :style)
  27 + end
  28 +
  29 + should "return the basename of the file" do
  30 + attachment = mock
  31 + attachment.expects(:original_filename).returns("one.jpg").times(2)
  32 + assert_equal "one", Paperclip::Interpolations.basename(attachment, :style)
  33 + end
  34 +
  35 + should "return the extension of the file" do
  36 + attachment = mock
  37 + attachment.expects(:original_filename).returns("one.jpg")
  38 + attachment.expects(:styles).returns({})
  39 + assert_equal "jpg", Paperclip::Interpolations.extension(attachment, :style)
  40 + end
  41 +
  42 + should "return the extension of the file as the format if defined in the style" do
  43 + attachment = mock
  44 + attachment.expects(:original_filename).never
  45 + attachment.expects(:styles).returns({:style => {:format => "png"}})
  46 + assert_equal "png", Paperclip::Interpolations.extension(attachment, :style)
  47 + end
  48 +
  49 + should "return the id of the attachment" do
  50 + attachment = mock
  51 + attachment.expects(:id).returns(23)
  52 + attachment.expects(:instance).returns(attachment)
  53 + assert_equal 23, Paperclip::Interpolations.id(attachment, :style)
  54 + end
  55 +
  56 + should "return the partitioned id of the attachment" do
  57 + attachment = mock
  58 + attachment.expects(:id).returns(23)
  59 + attachment.expects(:instance).returns(attachment)
  60 + assert_equal "000/000/023", Paperclip::Interpolations.id_partition(attachment, :style)
  61 + end
  62 +
  63 + should "return the name of the attachment" do
  64 + attachment = mock
  65 + attachment.expects(:name).returns("file")
  66 + assert_equal "files", Paperclip::Interpolations.attachment(attachment, :style)
  67 + end
  68 +
  69 + should "return the style" do
  70 + assert_equal :style, Paperclip::Interpolations.style(:attachment, :style)
  71 + end
  72 +
  73 + should "return the default style" do
  74 + attachment = mock
  75 + attachment.expects(:default_style).returns(:default_style)
  76 + assert_equal :default_style, Paperclip::Interpolations.style(attachment, nil)
  77 + end
  78 +
  79 + should "reinterpolate :url" do
  80 + attachment = mock
  81 + attachment.expects(:options).returns({:url => ":id"})
  82 + attachment.expects(:url).with(:style, false).returns("1234")
  83 + assert_equal "1234", Paperclip::Interpolations.url(attachment, :style)
  84 + end
  85 +
  86 + should "raise if infinite loop detcted reinterpolating :url" do
  87 + attachment = mock
  88 + attachment.expects(:options).returns({:url => ":url"})
  89 + assert_raises(Paperclip::InfiniteInterpolationError){ Paperclip::Interpolations.url(attachment, :style) }
  90 + end
  91 +
  92 + should "return the filename as basename.extension" do
  93 + attachment = mock
  94 + attachment.expects(:styles).returns({})
  95 + attachment.expects(:original_filename).returns("one.jpg").times(3)
  96 + assert_equal "one.jpg", Paperclip::Interpolations.filename(attachment, :style)
  97 + end
  98 +
  99 + should "return the filename as basename.extension when format supplied" do
  100 + attachment = mock
  101 + attachment.expects(:styles).returns({:style => {:format => :png}})
  102 + attachment.expects(:original_filename).returns("one.jpg").times(2)
  103 + assert_equal "one.png", Paperclip::Interpolations.filename(attachment, :style)
  104 + end
  105 +
  106 + should "return the timestamp" do
  107 + now = Time.now
  108 + attachment = mock
  109 + attachment.expects(:instance_read).with(:updated_at).returns(now)
  110 + assert_equal now.to_s, Paperclip::Interpolations.timestamp(attachment, :style)
  111 + end
  112 +
  113 + should "call all expected interpolations with the given arguments" do
  114 + Paperclip::Interpolations.expects(:id).with(:attachment, :style).returns(1234)
  115 + Paperclip::Interpolations.expects(:attachment).with(:attachment, :style).returns("attachments")
  116 + Paperclip::Interpolations.expects(:notreal).never
  117 + value = Paperclip::Interpolations.interpolate(":notreal/:id/:attachment", :attachment, :style)
  118 + assert_equal ":notreal/1234/attachments", value
  119 + end
  120 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/iostream_test.rb 0 → 100644
... ... @@ -0,0 +1,71 @@
  1 +require 'test/helper'
  2 +
  3 +class IOStreamTest < Test::Unit::TestCase
  4 + context "IOStream" do
  5 + should "be included in IO, File, Tempfile, and StringIO" do
  6 + [IO, File, Tempfile, StringIO].each do |klass|
  7 + assert klass.included_modules.include?(IOStream), "Not in #{klass}"
  8 + end
  9 + end
  10 + end
  11 +
  12 + context "A file" do
  13 + setup do
  14 + @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
  15 + end
  16 +
  17 + teardown { @file.close }
  18 +
  19 + context "that is sent #stream_to" do
  20 +
  21 + context "and given a String" do
  22 + setup do
  23 + FileUtils.mkdir_p(File.join(ROOT, 'tmp'))
  24 + assert @result = @file.stream_to(File.join(ROOT, 'tmp', 'iostream.string.test'))
  25 + end
  26 +
  27 + should "return a File" do
  28 + assert @result.is_a?(File)
  29 + end
  30 +
  31 + should "contain the same data as the original file" do
  32 + @file.rewind; @result.rewind
  33 + assert_equal @file.read, @result.read
  34 + end
  35 + end
  36 +
  37 + context "and given a Tempfile" do
  38 + setup do
  39 + tempfile = Tempfile.new('iostream.test')
  40 + tempfile.binmode
  41 + assert @result = @file.stream_to(tempfile)
  42 + end
  43 +
  44 + should "return a Tempfile" do
  45 + assert @result.is_a?(Tempfile)
  46 + end
  47 +
  48 + should "contain the same data as the original file" do
  49 + @file.rewind; @result.rewind
  50 + assert_equal @file.read, @result.read
  51 + end
  52 + end
  53 +
  54 + end
  55 +
  56 + context "that is sent #to_tempfile" do
  57 + setup do
  58 + assert @tempfile = @file.to_tempfile
  59 + end
  60 +
  61 + should "convert it to a Tempfile" do
  62 + assert @tempfile.is_a?(Tempfile)
  63 + end
  64 +
  65 + should "have the Tempfile contain the same data as the file" do
  66 + @file.rewind; @tempfile.rewind
  67 + assert_equal @file.read, @tempfile.read
  68 + end
  69 + end
  70 + end
  71 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/matchers/have_attached_file_matcher_test.rb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +require 'test/helper'
  2 +
  3 +class HaveAttachedFileMatcherTest < Test::Unit::TestCase
  4 + context "have_attached_file" do
  5 + setup do
  6 + @dummy_class = reset_class "Dummy"
  7 + reset_table "dummies"
  8 + @matcher = self.class.have_attached_file(:avatar)
  9 + end
  10 +
  11 + should "reject a class with no attachment" do
  12 + assert_rejects @matcher, @dummy_class
  13 + end
  14 +
  15 + should "accept a class with an attachment" do
  16 + modify_table("dummies"){|d| d.string :avatar_file_name }
  17 + @dummy_class.has_attached_file :avatar
  18 + assert_accepts @matcher, @dummy_class
  19 + end
  20 + end
  21 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/matchers/validate_attachment_content_type_matcher_test.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +require 'test/helper'
  2 +
  3 +class ValidateAttachmentContentTypeMatcherTest < Test::Unit::TestCase
  4 + context "validate_attachment_content_type" do
  5 + setup do
  6 + reset_table("dummies") do |d|
  7 + d.string :avatar_file_name
  8 + end
  9 + @dummy_class = reset_class "Dummy"
  10 + @dummy_class.has_attached_file :avatar
  11 + @matcher = self.class.validate_attachment_content_type(:avatar).
  12 + allowing(%w(image/png image/jpeg)).
  13 + rejecting(%w(audio/mp3 application/octet-stream))
  14 + end
  15 +
  16 + should "reject a class with no validation" do
  17 + assert_rejects @matcher, @dummy_class
  18 + end
  19 +
  20 + should "reject a class with a validation that doesn't match" do
  21 + @dummy_class.validates_attachment_content_type :avatar, :content_type => %r{audio/.*}
  22 + assert_rejects @matcher, @dummy_class
  23 + end
  24 +
  25 + should "accept a class with a validation" do
  26 + @dummy_class.validates_attachment_content_type :avatar, :content_type => %r{image/.*}
  27 + assert_accepts @matcher, @dummy_class
  28 + end
  29 + end
  30 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/matchers/validate_attachment_presence_matcher_test.rb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +require 'test/helper'
  2 +
  3 +class ValidateAttachmentPresenceMatcherTest < Test::Unit::TestCase
  4 + context "validate_attachment_presence" do
  5 + setup do
  6 + reset_table("dummies"){|d| d.string :avatar_file_name }
  7 + @dummy_class = reset_class "Dummy"
  8 + @dummy_class.has_attached_file :avatar
  9 + @matcher = self.class.validate_attachment_presence(:avatar)
  10 + end
  11 +
  12 + should "reject a class with no validation" do
  13 + assert_rejects @matcher, @dummy_class
  14 + end
  15 +
  16 + should "accept a class with a validation" do
  17 + @dummy_class.validates_attachment_presence :avatar
  18 + assert_accepts @matcher, @dummy_class
  19 + end
  20 + end
  21 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/matchers/validate_attachment_size_matcher_test.rb 0 → 100644
... ... @@ -0,0 +1,50 @@
  1 +require 'test/helper'
  2 +
  3 +class ValidateAttachmentSizeMatcherTest < Test::Unit::TestCase
  4 + context "validate_attachment_size" do
  5 + setup do
  6 + reset_table("dummies") do |d|
  7 + d.string :avatar_file_name
  8 + end
  9 + @dummy_class = reset_class "Dummy"
  10 + @dummy_class.has_attached_file :avatar
  11 + end
  12 +
  13 + context "of limited size" do
  14 + setup{ @matcher = self.class.validate_attachment_size(:avatar).in(256..1024) }
  15 +
  16 + should "reject a class with no validation" do
  17 + assert_rejects @matcher, @dummy_class
  18 + end
  19 +
  20 + should "reject a class with a validation that's too high" do
  21 + @dummy_class.validates_attachment_size :avatar, :in => 256..2048
  22 + assert_rejects @matcher, @dummy_class
  23 + end
  24 +
  25 + should "reject a class with a validation that's too low" do
  26 + @dummy_class.validates_attachment_size :avatar, :in => 0..1024
  27 + assert_rejects @matcher, @dummy_class
  28 + end
  29 +
  30 + should "accept a class with a validation that matches" do
  31 + @dummy_class.validates_attachment_size :avatar, :in => 256..1024
  32 + assert_accepts @matcher, @dummy_class
  33 + end
  34 + end
  35 +
  36 + context "validates_attachment_size with infinite range" do
  37 + setup{ @matcher = self.class.validate_attachment_size(:avatar) }
  38 +
  39 + should "accept a class with an upper limit" do
  40 + @dummy_class.validates_attachment_size :avatar, :less_than => 1
  41 + assert_accepts @matcher, @dummy_class
  42 + end
  43 +
  44 + should "accept a class with no upper limit" do
  45 + @dummy_class.validates_attachment_size :avatar, :greater_than => 1
  46 + assert_accepts @matcher, @dummy_class
  47 + end
  48 + end
  49 + end
  50 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/paperclip_test.rb 0 → 100644
... ... @@ -0,0 +1,312 @@
  1 +require 'test/helper'
  2 +
  3 +class PaperclipTest < Test::Unit::TestCase
  4 + [:image_magick_path, :command_path].each do |path|
  5 + context "Calling Paperclip.run with #{path} specified" do
  6 + setup do
  7 + Paperclip.options[:image_magick_path] = nil
  8 + Paperclip.options[:command_path] = nil
  9 + Paperclip.options[path] = "/usr/bin"
  10 + end
  11 +
  12 + should "return the expected path for path_for_command" do
  13 + assert_equal "/usr/bin/convert", Paperclip.path_for_command("convert")
  14 + end
  15 +
  16 + should "execute the right command" do
  17 + Paperclip.expects(:path_for_command).with("convert").returns("/usr/bin/convert")
  18 + Paperclip.expects(:bit_bucket).returns("/dev/null")
  19 + Paperclip.expects(:"`").with("/usr/bin/convert one.jpg two.jpg 2>/dev/null")
  20 + Paperclip.run("convert", "one.jpg two.jpg")
  21 + end
  22 + end
  23 + end
  24 +
  25 + context "Calling Paperclip.run with no path specified" do
  26 + setup do
  27 + Paperclip.options[:image_magick_path] = nil
  28 + Paperclip.options[:command_path] = nil
  29 + end
  30 +
  31 + should "return the expected path fro path_for_command" do
  32 + assert_equal "convert", Paperclip.path_for_command("convert")
  33 + end
  34 +
  35 + should "execute the right command" do
  36 + Paperclip.expects(:path_for_command).with("convert").returns("convert")
  37 + Paperclip.expects(:bit_bucket).returns("/dev/null")
  38 + Paperclip.expects(:"`").with("convert one.jpg two.jpg 2>/dev/null")
  39 + Paperclip.run("convert", "one.jpg two.jpg")
  40 + end
  41 + end
  42 +
  43 + context "Calling Paperclip.run and logging" do
  44 + setup do
  45 + Paperclip.options[:image_magick_path] = nil
  46 + Paperclip.options[:command_path] = nil
  47 + Paperclip.stubs(:bit_bucket).returns("/dev/null")
  48 + Paperclip.stubs(:log)
  49 + Paperclip.stubs(:"`").with("this is the command 2>/dev/null")
  50 + end
  51 +
  52 + should "log the command when :log_command is true" do
  53 + Paperclip.options[:log_command] = true
  54 + Paperclip.run("this","is the command")
  55 + assert_received(Paperclip, :log) do |p|
  56 + p.with("this is the command 2>/dev/null")
  57 + end
  58 + assert_received(Paperclip, :`) do |p|
  59 + p.with("this is the command 2>/dev/null")
  60 + end
  61 + end
  62 +
  63 + should "not log the command when :log_command is false" do
  64 + Paperclip.options[:log_command] = false
  65 + Paperclip.run("this","is the command")
  66 + assert_received(Paperclip, :log) do |p|
  67 + p.with("this is the command 2>/dev/null").never
  68 + end
  69 + assert_received(Paperclip, :`) do |p|
  70 + p.with("this is the command 2>/dev/null")
  71 + end
  72 + end
  73 + end
  74 +
  75 + context "Paperclip.bit_bucket" do
  76 + context "on systems without /dev/null" do
  77 + setup do
  78 + File.expects(:exists?).with("/dev/null").returns(false)
  79 + end
  80 +
  81 + should "return 'NUL'" do
  82 + assert_equal "NUL", Paperclip.bit_bucket
  83 + end
  84 + end
  85 +
  86 + context "on systems with /dev/null" do
  87 + setup do
  88 + File.expects(:exists?).with("/dev/null").returns(true)
  89 + end
  90 +
  91 + should "return '/dev/null'" do
  92 + assert_equal "/dev/null", Paperclip.bit_bucket
  93 + end
  94 + end
  95 + end
  96 +
  97 + should "raise when sent #processor and the name of a class that exists but isn't a subclass of Processor" do
  98 + assert_raises(Paperclip::PaperclipError){ Paperclip.processor(:attachment) }
  99 + end
  100 +
  101 + should "raise when sent #processor and the name of a class that doesn't exist" do
  102 + assert_raises(NameError){ Paperclip.processor(:boogey_man) }
  103 + end
  104 +
  105 + should "return a class when sent #processor and the name of a class under Paperclip" do
  106 + assert_equal ::Paperclip::Thumbnail, Paperclip.processor(:thumbnail)
  107 + end
  108 +
  109 + context "An ActiveRecord model with an 'avatar' attachment" do
  110 + setup do
  111 + rebuild_model :path => "tmp/:class/omg/:style.:extension"
  112 + @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
  113 + end
  114 +
  115 + teardown { @file.close }
  116 +
  117 + should "not error when trying to also create a 'blah' attachment" do
  118 + assert_nothing_raised do
  119 + Dummy.class_eval do
  120 + has_attached_file :blah
  121 + end
  122 + end
  123 + end
  124 +
  125 + context "that is attr_protected" do
  126 + setup do
  127 + Dummy.class_eval do
  128 + attr_protected :avatar
  129 + end
  130 + @dummy = Dummy.new
  131 + end
  132 +
  133 + should "not assign the avatar on mass-set" do
  134 + @dummy.attributes = { :other => "I'm set!",
  135 + :avatar => @file }
  136 +
  137 + assert_equal "I'm set!", @dummy.other
  138 + assert ! @dummy.avatar?
  139 + end
  140 +
  141 + should "still allow assigment on normal set" do
  142 + @dummy.other = "I'm set!"
  143 + @dummy.avatar = @file
  144 +
  145 + assert_equal "I'm set!", @dummy.other
  146 + assert @dummy.avatar?
  147 + end
  148 + end
  149 +
  150 + context "with a subclass" do
  151 + setup do
  152 + class ::SubDummy < Dummy; end
  153 + end
  154 +
  155 + should "be able to use the attachment from the subclass" do
  156 + assert_nothing_raised do
  157 + @subdummy = SubDummy.create(:avatar => @file)
  158 + end
  159 + end
  160 +
  161 + should "be able to see the attachment definition from the subclass's class" do
  162 + assert_equal "tmp/:class/omg/:style.:extension",
  163 + SubDummy.attachment_definitions[:avatar][:path]
  164 + end
  165 +
  166 + teardown do
  167 + Object.send(:remove_const, "SubDummy") rescue nil
  168 + end
  169 + end
  170 +
  171 + should "have an #avatar method" do
  172 + assert Dummy.new.respond_to?(:avatar)
  173 + end
  174 +
  175 + should "have an #avatar= method" do
  176 + assert Dummy.new.respond_to?(:avatar=)
  177 + end
  178 +
  179 + context "that is valid" do
  180 + setup do
  181 + @dummy = Dummy.new
  182 + @dummy.avatar = @file
  183 + end
  184 +
  185 + should "be valid" do
  186 + assert @dummy.valid?
  187 + end
  188 +
  189 + context "then has a validation added that makes it invalid" do
  190 + setup do
  191 + assert @dummy.save
  192 + Dummy.class_eval do
  193 + validates_attachment_content_type :avatar, :content_type => ["text/plain"]
  194 + end
  195 + @dummy2 = Dummy.find(@dummy.id)
  196 + end
  197 +
  198 + should "be invalid when reloaded" do
  199 + assert ! @dummy2.valid?, @dummy2.errors.inspect
  200 + end
  201 +
  202 + should "be able to call #valid? twice without having duplicate errors" do
  203 + @dummy2.avatar.valid?
  204 + first_errors = @dummy2.avatar.errors
  205 + @dummy2.avatar.valid?
  206 + assert_equal first_errors, @dummy2.avatar.errors
  207 + end
  208 + end
  209 + end
  210 +
  211 + context "a validation with an if guard clause" do
  212 + setup do
  213 + Dummy.send(:"validates_attachment_presence", :avatar, :if => lambda{|i| i.foo })
  214 + @dummy = Dummy.new
  215 + end
  216 +
  217 + should "attempt validation if the guard returns true" do
  218 + @dummy.expects(:foo).returns(true)
  219 + @dummy.avatar.expects(:validate_presence).returns(nil)
  220 + @dummy.valid?
  221 + end
  222 +
  223 + should "not attempt validation if the guard returns false" do
  224 + @dummy.expects(:foo).returns(false)
  225 + @dummy.avatar.expects(:validate_presence).never
  226 + @dummy.valid?
  227 + end
  228 + end
  229 +
  230 + context "a validation with an unless guard clause" do
  231 + setup do
  232 + Dummy.send(:"validates_attachment_presence", :avatar, :unless => lambda{|i| i.foo })
  233 + @dummy = Dummy.new
  234 + end
  235 +
  236 + should "attempt validation if the guard returns true" do
  237 + @dummy.expects(:foo).returns(false)
  238 + @dummy.avatar.expects(:validate_presence).returns(nil)
  239 + @dummy.valid?
  240 + end
  241 +
  242 + should "not attempt validation if the guard returns false" do
  243 + @dummy.expects(:foo).returns(true)
  244 + @dummy.avatar.expects(:validate_presence).never
  245 + @dummy.valid?
  246 + end
  247 + end
  248 +
  249 + def self.should_validate validation, options, valid_file, invalid_file
  250 + context "with #{validation} validation and #{options.inspect} options" do
  251 + setup do
  252 + Dummy.send(:"validates_attachment_#{validation}", :avatar, options)
  253 + @dummy = Dummy.new
  254 + end
  255 + context "and assigning nil" do
  256 + setup do
  257 + @dummy.avatar = nil
  258 + @dummy.valid?
  259 + end
  260 + if validation == :presence
  261 + should "have an error on the attachment" do
  262 + assert @dummy.errors.on(:avatar)
  263 + end
  264 + else
  265 + should "not have an error on the attachment" do
  266 + assert_nil @dummy.errors.on(:avatar)
  267 + end
  268 + end
  269 + end
  270 + context "and assigned a valid file" do
  271 + setup do
  272 + @dummy.avatar = valid_file
  273 + @dummy.valid?
  274 + end
  275 + should "not have an error when assigned a valid file" do
  276 + assert ! @dummy.avatar.errors.key?(validation)
  277 + end
  278 + should "not have an error on the attachment" do
  279 + assert_nil @dummy.errors.on(:avatar)
  280 + end
  281 + end
  282 + context "and assigned an invalid file" do
  283 + setup do
  284 + @dummy.avatar = invalid_file
  285 + @dummy.valid?
  286 + end
  287 + should "have an error when assigned a valid file" do
  288 + assert_not_nil @dummy.avatar.errors[validation]
  289 + end
  290 + should "have an error on the attachment" do
  291 + assert @dummy.errors.on(:avatar)
  292 + end
  293 + end
  294 + end
  295 + end
  296 +
  297 + [[:presence, {}, "5k.png", nil],
  298 + [:size, {:in => 1..10240}, nil, "12k.png"],
  299 + [:size, {:less_than => 10240}, "5k.png", "12k.png"],
  300 + [:size, {:greater_than => 8096}, "12k.png", "5k.png"],
  301 + [:content_type, {:content_type => "image/png"}, "5k.png", "text.txt"],
  302 + [:content_type, {:content_type => "text/plain"}, "text.txt", "5k.png"],
  303 + [:content_type, {:content_type => %r{image/.*}}, "5k.png", "text.txt"]].each do |args|
  304 + validation, options, valid_file, invalid_file = args
  305 + valid_file &&= File.open(File.join(FIXTURES_DIR, valid_file), "rb")
  306 + invalid_file &&= File.open(File.join(FIXTURES_DIR, invalid_file), "rb")
  307 +
  308 + should_validate validation, options, valid_file, invalid_file
  309 + end
  310 +
  311 + end
  312 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/processor_test.rb 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +require 'test/helper'
  2 +
  3 +class ProcessorTest < Test::Unit::TestCase
  4 + should "instantiate and call #make when sent #make to the class" do
  5 + processor = mock
  6 + processor.expects(:make).with()
  7 + Paperclip::Processor.expects(:new).with(:one, :two, :three).returns(processor)
  8 + Paperclip::Processor.make(:one, :two, :three)
  9 + end
  10 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/storage_test.rb 0 → 100644
... ... @@ -0,0 +1,273 @@
  1 +require 'test/helper'
  2 +
  3 +class StorageTest < Test::Unit::TestCase
  4 + context "Parsing S3 credentials" do
  5 + setup do
  6 + AWS::S3::Base.stubs(:establish_connection!)
  7 + rebuild_model :storage => :s3,
  8 + :bucket => "testing",
  9 + :s3_credentials => {:not => :important}
  10 +
  11 + @dummy = Dummy.new
  12 + @avatar = @dummy.avatar
  13 +
  14 + @current_env = RAILS_ENV
  15 + end
  16 +
  17 + teardown do
  18 + Object.const_set("RAILS_ENV", @current_env)
  19 + end
  20 +
  21 + should "get the correct credentials when RAILS_ENV is production" do
  22 + Object.const_set('RAILS_ENV', "production")
  23 + assert_equal({:key => "12345"},
  24 + @avatar.parse_credentials('production' => {:key => '12345'},
  25 + :development => {:key => "54321"}))
  26 + end
  27 +
  28 + should "get the correct credentials when RAILS_ENV is development" do
  29 + Object.const_set('RAILS_ENV', "development")
  30 + assert_equal({:key => "54321"},
  31 + @avatar.parse_credentials('production' => {:key => '12345'},
  32 + :development => {:key => "54321"}))
  33 + end
  34 +
  35 + should "return the argument if the key does not exist" do
  36 + Object.const_set('RAILS_ENV', "not really an env")
  37 + assert_equal({:test => "12345"}, @avatar.parse_credentials(:test => "12345"))
  38 + end
  39 + end
  40 +
  41 + context "" do
  42 + setup do
  43 + AWS::S3::Base.stubs(:establish_connection!)
  44 + rebuild_model :storage => :s3,
  45 + :s3_credentials => {},
  46 + :bucket => "bucket",
  47 + :path => ":attachment/:basename.:extension",
  48 + :url => ":s3_path_url"
  49 + @dummy = Dummy.new
  50 + @dummy.avatar = StringIO.new(".")
  51 + end
  52 +
  53 + should "return a url based on an S3 path" do
  54 + assert_match %r{^http://s3.amazonaws.com/bucket/avatars/stringio.txt}, @dummy.avatar.url
  55 + end
  56 + end
  57 + context "" do
  58 + setup do
  59 + AWS::S3::Base.stubs(:establish_connection!)
  60 + rebuild_model :storage => :s3,
  61 + :s3_credentials => {},
  62 + :bucket => "bucket",
  63 + :path => ":attachment/:basename.:extension",
  64 + :url => ":s3_domain_url"
  65 + @dummy = Dummy.new
  66 + @dummy.avatar = StringIO.new(".")
  67 + end
  68 +
  69 + should "return a url based on an S3 subdomain" do
  70 + assert_match %r{^http://bucket.s3.amazonaws.com/avatars/stringio.txt}, @dummy.avatar.url
  71 + end
  72 + end
  73 + context "" do
  74 + setup do
  75 + AWS::S3::Base.stubs(:establish_connection!)
  76 + rebuild_model :storage => :s3,
  77 + :s3_credentials => {
  78 + :production => { :bucket => "prod_bucket" },
  79 + :development => { :bucket => "dev_bucket" }
  80 + },
  81 + :s3_host_alias => "something.something.com",
  82 + :path => ":attachment/:basename.:extension",
  83 + :url => ":s3_alias_url"
  84 + @dummy = Dummy.new
  85 + @dummy.avatar = StringIO.new(".")
  86 + end
  87 +
  88 + should "return a url based on the host_alias" do
  89 + assert_match %r{^http://something.something.com/avatars/stringio.txt}, @dummy.avatar.url
  90 + end
  91 + end
  92 +
  93 + context "Parsing S3 credentials with a bucket in them" do
  94 + setup do
  95 + AWS::S3::Base.stubs(:establish_connection!)
  96 + rebuild_model :storage => :s3,
  97 + :s3_credentials => {
  98 + :production => { :bucket => "prod_bucket" },
  99 + :development => { :bucket => "dev_bucket" }
  100 + }
  101 + @dummy = Dummy.new
  102 + @old_env = RAILS_ENV
  103 + end
  104 +
  105 + teardown{ Object.const_set("RAILS_ENV", @old_env) }
  106 +
  107 + should "get the right bucket in production" do
  108 + Object.const_set("RAILS_ENV", "production")
  109 + assert_equal "prod_bucket", @dummy.avatar.bucket_name
  110 + end
  111 +
  112 + should "get the right bucket in development" do
  113 + Object.const_set("RAILS_ENV", "development")
  114 + assert_equal "dev_bucket", @dummy.avatar.bucket_name
  115 + end
  116 + end
  117 +
  118 + context "An attachment with S3 storage" do
  119 + setup do
  120 + rebuild_model :storage => :s3,
  121 + :bucket => "testing",
  122 + :path => ":attachment/:style/:basename.:extension",
  123 + :s3_credentials => {
  124 + 'access_key_id' => "12345",
  125 + 'secret_access_key' => "54321"
  126 + }
  127 + end
  128 +
  129 + should "be extended by the S3 module" do
  130 + assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
  131 + end
  132 +
  133 + should "not be extended by the Filesystem module" do
  134 + assert ! Dummy.new.avatar.is_a?(Paperclip::Storage::Filesystem)
  135 + end
  136 +
  137 + context "when assigned" do
  138 + setup do
  139 + @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
  140 + @dummy = Dummy.new
  141 + @dummy.avatar = @file
  142 + end
  143 +
  144 + teardown { @file.close }
  145 +
  146 + should "not get a bucket to get a URL" do
  147 + @dummy.avatar.expects(:s3).never
  148 + @dummy.avatar.expects(:s3_bucket).never
  149 + assert_match %r{^http://s3\.amazonaws\.com/testing/avatars/original/5k\.png}, @dummy.avatar.url
  150 + end
  151 +
  152 + context "and saved" do
  153 + setup do
  154 + AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path, anything, 'testing', :content_type => 'image/png', :access => :public_read)
  155 + @dummy.save
  156 + end
  157 +
  158 + should "succeed" do
  159 + assert true
  160 + end
  161 + end
  162 +
  163 + context "and remove" do
  164 + setup do
  165 + AWS::S3::S3Object.stubs(:exists?).returns(true)
  166 + AWS::S3::S3Object.stubs(:delete)
  167 + @dummy.destroy_attached_files
  168 + end
  169 +
  170 + should "succeed" do
  171 + assert true
  172 + end
  173 + end
  174 + end
  175 + end
  176 +
  177 + context "An attachment with S3 storage and bucket defined as a Proc" do
  178 + setup do
  179 + AWS::S3::Base.stubs(:establish_connection!)
  180 + rebuild_model :storage => :s3,
  181 + :bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
  182 + :s3_credentials => {:not => :important}
  183 + end
  184 +
  185 + should "get the right bucket name" do
  186 + assert "bucket_a", Dummy.new(:other => 'a').avatar.bucket_name
  187 + assert "bucket_b", Dummy.new(:other => 'b').avatar.bucket_name
  188 + end
  189 + end
  190 +
  191 + context "An attachment with S3 storage and specific s3 headers set" do
  192 + setup do
  193 + AWS::S3::Base.stubs(:establish_connection!)
  194 + rebuild_model :storage => :s3,
  195 + :bucket => "testing",
  196 + :path => ":attachment/:style/:basename.:extension",
  197 + :s3_credentials => {
  198 + 'access_key_id' => "12345",
  199 + 'secret_access_key' => "54321"
  200 + },
  201 + :s3_headers => {'Cache-Control' => 'max-age=31557600'}
  202 + end
  203 +
  204 + context "when assigned" do
  205 + setup do
  206 + @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
  207 + @dummy = Dummy.new
  208 + @dummy.avatar = @file
  209 + end
  210 +
  211 + teardown { @file.close }
  212 +
  213 + context "and saved" do
  214 + setup do
  215 + AWS::S3::Base.stubs(:establish_connection!)
  216 + AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path,
  217 + anything,
  218 + 'testing',
  219 + :content_type => 'image/png',
  220 + :access => :public_read,
  221 + 'Cache-Control' => 'max-age=31557600')
  222 + @dummy.save
  223 + end
  224 +
  225 + should "succeed" do
  226 + assert true
  227 + end
  228 + end
  229 + end
  230 + end
  231 +
  232 + unless ENV["S3_TEST_BUCKET"].blank?
  233 + context "Using S3 for real, an attachment with S3 storage" do
  234 + setup do
  235 + rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
  236 + :storage => :s3,
  237 + :bucket => ENV["S3_TEST_BUCKET"],
  238 + :path => ":class/:attachment/:id/:style.:extension",
  239 + :s3_credentials => File.new(File.join(File.dirname(__FILE__), "s3.yml"))
  240 +
  241 + Dummy.delete_all
  242 + @dummy = Dummy.new
  243 + end
  244 +
  245 + should "be extended by the S3 module" do
  246 + assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
  247 + end
  248 +
  249 + context "when assigned" do
  250 + setup do
  251 + @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
  252 + @dummy.avatar = @file
  253 + end
  254 +
  255 + teardown { @file.close }
  256 +
  257 + should "still return a Tempfile when sent #to_file" do
  258 + assert_equal Tempfile, @dummy.avatar.to_file.class
  259 + end
  260 +
  261 + context "and saved" do
  262 + setup do
  263 + @dummy.save
  264 + end
  265 +
  266 + should "be on S3" do
  267 + assert true
  268 + end
  269 + end
  270 + end
  271 + end
  272 + end
  273 +end
... ...
vendor/gems/tristandunn-paperclip-2.3.1/test/thumbnail_test.rb 0 → 100644
... ... @@ -0,0 +1,227 @@
  1 +require 'test/helper'
  2 +
  3 +class ThumbnailTest < Test::Unit::TestCase
  4 +
  5 + context "A Paperclip Tempfile" do
  6 + setup do
  7 + @tempfile = Paperclip::Tempfile.new("file.jpg")
  8 + end
  9 +
  10 + should "have its path contain a real extension" do
  11 + assert_equal ".jpg", File.extname(@tempfile.path)
  12 + end
  13 +
  14 + should "be a real Tempfile" do
  15 + assert @tempfile.is_a?(::Tempfile)
  16 + end
  17 + end
  18 +
  19 + context "Another Paperclip Tempfile" do
  20 + setup do
  21 + @tempfile = Paperclip::Tempfile.new("file")
  22 + end
  23 +
  24 + should "not have an extension if not given one" do
  25 + assert_equal "", File.extname(@tempfile.path)
  26 + end
  27 +
  28 + should "still be a real Tempfile" do
  29 + assert @tempfile.is_a?(::Tempfile)
  30 + end
  31 + end
  32 +
  33 + context "An image" do
  34 + setup do
  35 + @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
  36 + end
  37 +
  38 + teardown { @file.close }
  39 +
  40 + [["600x600>", "434x66"],
  41 + ["400x400>", "400x61"],
  42 + ["32x32<", "434x66"]
  43 + ].each do |args|
  44 + context "being thumbnailed with a geometry of #{args[0]}" do
  45 + setup do
  46 + @thumb = Paperclip::Thumbnail.new(@file, :geometry => args[0])
  47 + end
  48 +
  49 + should "start with dimensions of 434x66" do
  50 + cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
  51 + assert_equal "434x66", `#{cmd}`.chomp
  52 + end
  53 +
  54 + should "report the correct target geometry" do
  55 + assert_equal args[0], @thumb.target_geometry.to_s
  56 + end
  57 +
  58 + context "when made" do
  59 + setup do
  60 + @thumb_result = @thumb.make
  61 + end
  62 +
  63 + should "be the size we expect it to be" do
  64 + cmd = %Q[identify -format "%wx%h" "#{@thumb_result.path}"]
  65 + assert_equal args[1], `#{cmd}`.chomp
  66 + end
  67 + end
  68 + end
  69 + end
  70 +
  71 + context "being thumbnailed at 100x50 with cropping" do
  72 + setup do
  73 + @thumb = Paperclip::Thumbnail.new(@file, :geometry => "100x50#")
  74 + end
  75 +
  76 + should "report its correct current and target geometries" do
  77 + assert_equal "100x50#", @thumb.target_geometry.to_s
  78 + assert_equal "434x66", @thumb.current_geometry.to_s
  79 + end
  80 +
  81 + should "report its correct format" do
  82 + assert_nil @thumb.format
  83 + end
  84 +
  85 + should "have whiny turned on by default" do
  86 + assert @thumb.whiny
  87 + end
  88 +
  89 + should "have convert_options set to nil by default" do
  90 + assert_equal nil, @thumb.convert_options
  91 + end
  92 +
  93 + should "send the right command to convert when sent #make" do
  94 + Paperclip.expects(:"`").with do |arg|
  95 + arg.match %r{convert\s+"#{File.expand_path(@thumb.file.path)}\[0\]"\s+-resize\s+\"x50\"\s+-crop\s+\"100x50\+114\+0\"\s+\+repage\s+".*?"}
  96 + end
  97 + @thumb.make
  98 + end
  99 +
  100 + should "create the thumbnail when sent #make" do
  101 + dst = @thumb.make
  102 + assert_match /100x50/, `identify "#{dst.path}"`
  103 + end
  104 + end
  105 +
  106 + context "being thumbnailed with source file options set" do
  107 + setup do
  108 + @thumb = Paperclip::Thumbnail.new(@file,
  109 + :geometry => "100x50#",
  110 + :source_file_options => "-strip")
  111 + end
  112 +
  113 + should "have source_file_options value set" do
  114 + assert_equal "-strip", @thumb.source_file_options
  115 + end
  116 +
  117 + should "send the right command to convert when sent #make" do
  118 + Paperclip.expects(:"`").with do |arg|
  119 + arg.match %r{convert\s+-strip\s+"#{File.expand_path(@thumb.file.path)}\[0\]"\s+-resize\s+"x50"\s+-crop\s+"100x50\+114\+0"\s+\+repage\s+".*?"}
  120 + end
  121 + @thumb.make
  122 + end
  123 +
  124 + should "create the thumbnail when sent #make" do
  125 + dst = @thumb.make
  126 + assert_match /100x50/, `identify "#{dst.path}"`
  127 + end
  128 +
  129 + context "redefined to have bad source_file_options setting" do
  130 + setup do
  131 + @thumb = Paperclip::Thumbnail.new(@file,
  132 + :geometry => "100x50#",
  133 + :source_file_options => "-this-aint-no-option")
  134 + end
  135 +
  136 + should "error when trying to create the thumbnail" do
  137 + assert_raises(Paperclip::PaperclipError) do
  138 + @thumb.make
  139 + end
  140 + end
  141 + end
  142 + end
  143 +
  144 + context "being thumbnailed with convert options set" do
  145 + setup do
  146 + @thumb = Paperclip::Thumbnail.new(@file,
  147 + :geometry => "100x50#",
  148 + :convert_options => "-strip -depth 8")
  149 + end
  150 +
  151 + should "have convert_options value set" do
  152 + assert_equal "-strip -depth 8", @thumb.convert_options
  153 + end
  154 +
  155 + should "send the right command to convert when sent #make" do
  156 + Paperclip.expects(:"`").with do |arg|
  157 + arg.match %r{convert\s+"#{File.expand_path(@thumb.file.path)}\[0\]"\s+-resize\s+"x50"\s+-crop\s+"100x50\+114\+0"\s+\+repage\s+-strip\s+-depth\s+8\s+".*?"}
  158 + end
  159 + @thumb.make
  160 + end
  161 +
  162 + should "create the thumbnail when sent #make" do
  163 + dst = @thumb.make
  164 + assert_match /100x50/, `identify "#{dst.path}"`
  165 + end
  166 +
  167 + context "redefined to have bad convert_options setting" do
  168 + setup do
  169 + @thumb = Paperclip::Thumbnail.new(@file,
  170 + :geometry => "100x50#",
  171 + :convert_options => "-this-aint-no-option")
  172 + end
  173 +
  174 + should "error when trying to create the thumbnail" do
  175 + assert_raises(Paperclip::PaperclipError) do
  176 + @thumb.make
  177 + end
  178 + end
  179 + end
  180 + end
  181 +
  182 + context "being thumbnailed with a blank geometry string" do
  183 + setup do
  184 + @thumb = Paperclip::Thumbnail.new(@file,
  185 + :geometry => "",
  186 + :convert_options => "-gravity center -crop \"300x300+0-0\"")
  187 + end
  188 +
  189 + should "not get resized by default" do
  190 + assert_no_match(/-resize/, @thumb.transformation_command)
  191 + end
  192 + end
  193 + end
  194 +
  195 + context "A multipage PDF" do
  196 + setup do
  197 + @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "twopage.pdf"), 'rb')
  198 + end
  199 +
  200 + teardown { @file.close }
  201 +
  202 + should "start with two pages with dimensions 612x792" do
  203 + cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
  204 + assert_equal "612x792"*2, `#{cmd}`.chomp
  205 + end
  206 +
  207 + context "being thumbnailed at 100x100 with cropping" do
  208 + setup do
  209 + @thumb = Paperclip::Thumbnail.new(@file, :geometry => "100x100#", :format => :png)
  210 + end
  211 +
  212 + should "report its correct current and target geometries" do
  213 + assert_equal "100x100#", @thumb.target_geometry.to_s
  214 + assert_equal "612x792", @thumb.current_geometry.to_s
  215 + end
  216 +
  217 + should "report its correct format" do
  218 + assert_equal :png, @thumb.format
  219 + end
  220 +
  221 + should "create the thumbnail when sent #make" do
  222 + dst = @thumb.make
  223 + assert_match /100x100/, `identify "#{dst.path}"`
  224 + end
  225 + end
  226 + end
  227 +end
... ...