jmcnevin-paperclip 2.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. data/LICENSE +26 -0
  2. data/README.md +414 -0
  3. data/Rakefile +86 -0
  4. data/generators/paperclip/USAGE +5 -0
  5. data/generators/paperclip/paperclip_generator.rb +27 -0
  6. data/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  7. data/init.rb +4 -0
  8. data/lib/generators/paperclip/USAGE +8 -0
  9. data/lib/generators/paperclip/paperclip_generator.rb +33 -0
  10. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  11. data/lib/paperclip.rb +480 -0
  12. data/lib/paperclip/attachment.rb +520 -0
  13. data/lib/paperclip/callback_compatibility.rb +61 -0
  14. data/lib/paperclip/geometry.rb +155 -0
  15. data/lib/paperclip/interpolations.rb +171 -0
  16. data/lib/paperclip/iostream.rb +45 -0
  17. data/lib/paperclip/matchers.rb +33 -0
  18. data/lib/paperclip/matchers/have_attached_file_matcher.rb +57 -0
  19. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +81 -0
  20. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +54 -0
  21. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +95 -0
  22. data/lib/paperclip/missing_attachment_styles.rb +87 -0
  23. data/lib/paperclip/options.rb +78 -0
  24. data/lib/paperclip/processor.rb +58 -0
  25. data/lib/paperclip/railtie.rb +26 -0
  26. data/lib/paperclip/storage.rb +3 -0
  27. data/lib/paperclip/storage/filesystem.rb +81 -0
  28. data/lib/paperclip/storage/fog.rb +163 -0
  29. data/lib/paperclip/storage/s3.rb +270 -0
  30. data/lib/paperclip/style.rb +95 -0
  31. data/lib/paperclip/thumbnail.rb +105 -0
  32. data/lib/paperclip/upfile.rb +62 -0
  33. data/lib/paperclip/version.rb +3 -0
  34. data/lib/tasks/paperclip.rake +101 -0
  35. data/rails/init.rb +2 -0
  36. data/shoulda_macros/paperclip.rb +124 -0
  37. data/test/attachment_test.rb +1161 -0
  38. data/test/database.yml +4 -0
  39. data/test/fixtures/12k.png +0 -0
  40. data/test/fixtures/50x50.png +0 -0
  41. data/test/fixtures/5k.png +0 -0
  42. data/test/fixtures/animated.gif +0 -0
  43. data/test/fixtures/bad.png +1 -0
  44. data/test/fixtures/double spaces in name.png +0 -0
  45. data/test/fixtures/fog.yml +8 -0
  46. data/test/fixtures/s3.yml +8 -0
  47. data/test/fixtures/spaced file.png +0 -0
  48. data/test/fixtures/text.txt +1 -0
  49. data/test/fixtures/twopage.pdf +0 -0
  50. data/test/fixtures/uppercase.PNG +0 -0
  51. data/test/fog_test.rb +192 -0
  52. data/test/geometry_test.rb +206 -0
  53. data/test/helper.rb +158 -0
  54. data/test/integration_test.rb +781 -0
  55. data/test/interpolations_test.rb +202 -0
  56. data/test/iostream_test.rb +71 -0
  57. data/test/matchers/have_attached_file_matcher_test.rb +24 -0
  58. data/test/matchers/validate_attachment_content_type_matcher_test.rb +87 -0
  59. data/test/matchers/validate_attachment_presence_matcher_test.rb +26 -0
  60. data/test/matchers/validate_attachment_size_matcher_test.rb +51 -0
  61. data/test/options_test.rb +75 -0
  62. data/test/paperclip_missing_attachment_styles_test.rb +80 -0
  63. data/test/paperclip_test.rb +340 -0
  64. data/test/processor_test.rb +10 -0
  65. data/test/storage/filesystem_test.rb +56 -0
  66. data/test/storage/s3_live_test.rb +88 -0
  67. data/test/storage/s3_test.rb +689 -0
  68. data/test/style_test.rb +180 -0
  69. data/test/thumbnail_test.rb +383 -0
  70. data/test/upfile_test.rb +53 -0
  71. metadata +294 -0
@@ -0,0 +1,4 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: ":memory:"
4
+
Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+ This is not an image.
@@ -0,0 +1,8 @@
1
+ development:
2
+ provider: AWS
3
+ aws_access_key_id: AWS_ID
4
+ aws_secret_access_key: AWS_SECRET
5
+ test:
6
+ provider: AWS
7
+ aws_access_key_id: AWS_ID
8
+ aws_secret_access_key: AWS_SECRET
@@ -0,0 +1,8 @@
1
+ development:
2
+ key: 54321
3
+ production:
4
+ key: 12345
5
+ test:
6
+ bucket: <%= ENV['S3_BUCKET'] %>
7
+ access_key_id: <%= ENV['S3_KEY'] %>
8
+ secret_access_key: <%= ENV['S3_SECRET'] %>
@@ -0,0 +1 @@
1
+ paperclip!
Binary file
@@ -0,0 +1,192 @@
1
+ require './test/helper'
2
+ require 'fog'
3
+
4
+ Fog.mock!
5
+
6
+ class FogTest < Test::Unit::TestCase
7
+ context "" do
8
+
9
+ context "with credentials provided in a path string" do
10
+ setup do
11
+ rebuild_model :styles => { :medium => "300x300>", :thumb => "100x100>" },
12
+ :storage => :fog,
13
+ :url => '/:attachment/:filename',
14
+ :fog_directory => "paperclip",
15
+ :fog_credentials => File.join(File.dirname(__FILE__), 'fixtures', 'fog.yml')
16
+ @dummy = Dummy.new
17
+ @dummy.avatar = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
18
+ end
19
+
20
+ should "have the proper information loading credentials from a file" do
21
+ assert_equal @dummy.avatar.fog_credentials[:provider], 'AWS'
22
+ end
23
+ end
24
+
25
+ context "with credentials provided in a File object" do
26
+ setup do
27
+ rebuild_model :styles => { :medium => "300x300>", :thumb => "100x100>" },
28
+ :storage => :fog,
29
+ :url => '/:attachment/:filename',
30
+ :fog_directory => "paperclip",
31
+ :fog_credentials => File.open(File.join(File.dirname(__FILE__), 'fixtures', 'fog.yml'))
32
+ @dummy = Dummy.new
33
+ @dummy.avatar = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
34
+ end
35
+
36
+ should "have the proper information loading credentials from a file" do
37
+ assert_equal @dummy.avatar.fog_credentials[:provider], 'AWS'
38
+ end
39
+ end
40
+
41
+ context "with default values for path and url" do
42
+ setup do
43
+ rebuild_model :styles => { :medium => "300x300>", :thumb => "100x100>" },
44
+ :storage => :fog,
45
+ :url => '/:attachment/:filename',
46
+ :fog_directory => "paperclip",
47
+ :fog_credentials => {
48
+ :provider => 'AWS',
49
+ :aws_access_key_id => 'AWS_ID',
50
+ :aws_secret_access_key => 'AWS_SECRET'
51
+ }
52
+ @dummy = Dummy.new
53
+ @dummy.avatar = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
54
+ end
55
+ should "be able to interpolate the path without blowing up" do
56
+ assert_equal File.expand_path(File.join(File.dirname(__FILE__), "../public/avatars/5k.png")),
57
+ @dummy.avatar.path
58
+ end
59
+
60
+ should "clean up file objects" do
61
+ File.stubs(:exist?).returns(true)
62
+ Paperclip::Tempfile.any_instance.expects(:close).at_least_once()
63
+ Paperclip::Tempfile.any_instance.expects(:unlink).at_least_once()
64
+
65
+ @dummy.save!
66
+ end
67
+ end
68
+
69
+ setup do
70
+ @fog_directory = 'papercliptests'
71
+
72
+ @credentials = {
73
+ :provider => 'AWS',
74
+ :aws_access_key_id => 'ID',
75
+ :aws_secret_access_key => 'SECRET'
76
+ }
77
+
78
+ @connection = Fog::Storage.new(@credentials)
79
+ @connection.directories.create(
80
+ :key => @fog_directory
81
+ )
82
+
83
+ @options = {
84
+ :fog_directory => @fog_directory,
85
+ :fog_credentials => @credentials,
86
+ :fog_host => nil,
87
+ :fog_file => {:cache_control => 1234},
88
+ :path => ":attachment/:basename.:extension",
89
+ :storage => :fog
90
+ }
91
+
92
+ rebuild_model(@options)
93
+ end
94
+
95
+ should "be extended by the Fog module" do
96
+ assert Dummy.new.avatar.is_a?(Paperclip::Storage::Fog)
97
+ end
98
+
99
+ context "when assigned" do
100
+ setup do
101
+ @file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
102
+ @dummy = Dummy.new
103
+ @dummy.avatar = @file
104
+ end
105
+
106
+ teardown do
107
+ @file.close
108
+ directory = @connection.directories.new(:key => @fog_directory)
109
+ directory.files.each {|file| file.destroy}
110
+ directory.destroy
111
+ end
112
+
113
+ context "without a bucket" do
114
+ setup do
115
+ @connection.directories.get(@fog_directory).destroy
116
+ end
117
+
118
+ should "create the bucket" do
119
+ assert @dummy.save
120
+ assert @connection.directories.get(@fog_directory)
121
+ end
122
+ end
123
+
124
+ context "with a bucket" do
125
+ should "succeed" do
126
+ assert @dummy.save
127
+ end
128
+ end
129
+
130
+ context "without a fog_host" do
131
+ setup do
132
+ rebuild_model(@options.merge(:fog_host => nil))
133
+ @dummy = Dummy.new
134
+ @dummy.avatar = StringIO.new('.')
135
+ @dummy.save
136
+ end
137
+
138
+ should "provide a public url" do
139
+ assert !@dummy.avatar.url.nil?
140
+ end
141
+ end
142
+
143
+ context "with a fog_host" do
144
+ setup do
145
+ rebuild_model(@options.merge(:fog_host => 'http://example.com'))
146
+ @dummy = Dummy.new
147
+ @dummy.avatar = StringIO.new('.')
148
+ @dummy.save
149
+ end
150
+
151
+ should "provide a public url" do
152
+ assert @dummy.avatar.url =~ /^http:\/\/example\.com\/avatars\/stringio\.txt\?\d*$/
153
+ end
154
+ end
155
+
156
+ context "with a fog_host that includes a wildcard placeholder" do
157
+ setup do
158
+ rebuild_model(
159
+ :fog_directory => @fog_directory,
160
+ :fog_credentials => @credentials,
161
+ :fog_host => 'http://img%d.example.com',
162
+ :path => ":attachment/:basename.:extension",
163
+ :storage => :fog
164
+ )
165
+ @dummy = Dummy.new
166
+ @dummy.avatar = StringIO.new('.')
167
+ @dummy.save
168
+ end
169
+
170
+ should "provide a public url" do
171
+ assert @dummy.avatar.url =~ /^http:\/\/img[0123]\.example\.com\/avatars\/stringio\.txt\?\d*$/
172
+ end
173
+ end
174
+
175
+ context "with fog_public set to false" do
176
+ setup do
177
+ rebuild_model(@options.merge(:fog_public => false))
178
+ @dummy = Dummy.new
179
+ @dummy.avatar = StringIO.new('.')
180
+ @dummy.save
181
+ end
182
+
183
+ should 'set the @fog_public instance variable to false' do
184
+ assert_equal false, @dummy.avatar.options.fog_public
185
+ assert_equal false, @dummy.avatar.fog_public
186
+ end
187
+ end
188
+
189
+ end
190
+
191
+ end
192
+ end
@@ -0,0 +1,206 @@
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
+ should "not generate from a blank filename" do
124
+ file = ""
125
+ assert_raise(Paperclip::NotIdentifiedByImageMagickError){ @geo = Paperclip::Geometry.from_file(file) }
126
+ end
127
+
128
+ should "not generate from a nil file" do
129
+ file = nil
130
+ assert_raise(Paperclip::NotIdentifiedByImageMagickError){ @geo = Paperclip::Geometry.from_file(file) }
131
+ end
132
+
133
+ should "not generate from a file with no path" do
134
+ file = mock("file", :path => "")
135
+ file.stubs(:respond_to?).with(:path).returns(true)
136
+ assert_raise(Paperclip::NotIdentifiedByImageMagickError){ @geo = Paperclip::Geometry.from_file(file) }
137
+ end
138
+
139
+ should "let us know when a command isn't found versus a processing error" do
140
+ old_path = ENV['PATH']
141
+ begin
142
+ ENV['PATH'] = ''
143
+ assert_raises(Paperclip::CommandNotFoundError) do
144
+ file = File.join(File.dirname(__FILE__), "fixtures", "5k.png")
145
+ @geo = Paperclip::Geometry.from_file(file)
146
+ end
147
+ ensure
148
+ ENV['PATH'] = old_path
149
+ end
150
+ end
151
+
152
+ [['vertical', 900, 1440, true, false, false, 1440, 900, 0.625],
153
+ ['horizontal', 1024, 768, false, true, false, 1024, 768, 1.3333],
154
+ ['square', 100, 100, false, false, true, 100, 100, 1]].each do |args|
155
+ context "performing calculations on a #{args[0]} viewport" do
156
+ setup do
157
+ @geo = Paperclip::Geometry.new(args[1], args[2])
158
+ end
159
+
160
+ should "#{args[3] ? "" : "not"} be vertical" do
161
+ assert_equal args[3], @geo.vertical?
162
+ end
163
+
164
+ should "#{args[4] ? "" : "not"} be horizontal" do
165
+ assert_equal args[4], @geo.horizontal?
166
+ end
167
+
168
+ should "#{args[5] ? "" : "not"} be square" do
169
+ assert_equal args[5], @geo.square?
170
+ end
171
+
172
+ should "report that #{args[6]} is the larger dimension" do
173
+ assert_equal args[6], @geo.larger
174
+ end
175
+
176
+ should "report that #{args[7]} is the smaller dimension" do
177
+ assert_equal args[7], @geo.smaller
178
+ end
179
+
180
+ should "have an aspect ratio of #{args[8]}" do
181
+ assert_in_delta args[8], @geo.aspect, 0.0001
182
+ end
183
+ end
184
+ end
185
+
186
+ [[ [1000, 100], [64, 64], "x64", "64x64+288+0" ],
187
+ [ [100, 1000], [50, 950], "x950", "50x950+22+0" ],
188
+ [ [100, 1000], [50, 25], "50x", "50x25+0+237" ]]. each do |args|
189
+ context "of #{args[0].inspect} and given a Geometry #{args[1].inspect} and sent transform_to" do
190
+ setup do
191
+ @geo = Paperclip::Geometry.new(*args[0])
192
+ @dst = Paperclip::Geometry.new(*args[1])
193
+ @scale, @crop = @geo.transformation_to @dst, true
194
+ end
195
+
196
+ should "be able to return the correct scaling transformation geometry #{args[2]}" do
197
+ assert_equal args[2], @scale
198
+ end
199
+
200
+ should "be able to return the correct crop transformation geometry #{args[3]}" do
201
+ assert_equal args[3], @crop
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,158 @@
1
+ require 'rubygems'
2
+ require 'tempfile'
3
+ require 'pathname'
4
+ require 'test/unit'
5
+
6
+ require 'shoulda'
7
+ require 'mocha'
8
+
9
+ require 'active_record'
10
+ require 'active_record/version'
11
+ require 'active_support'
12
+ require 'mime/types'
13
+ require 'pry'
14
+ require 'pathname'
15
+
16
+ puts "Testing against version #{ActiveRecord::VERSION::STRING}"
17
+
18
+ `ruby -e 'exit 0'` # Prime $? with a value.
19
+
20
+ begin
21
+ require 'ruby-debug'
22
+ rescue LoadError => e
23
+ puts "debugger disabled"
24
+ end
25
+
26
+ ROOT = Pathname(File.expand_path(File.join(File.dirname(__FILE__), '..')))
27
+
28
+ def silence_warnings
29
+ old_verbose, $VERBOSE = $VERBOSE, nil
30
+ yield
31
+ ensure
32
+ $VERBOSE = old_verbose
33
+ end
34
+
35
+ class Test::Unit::TestCase
36
+ def setup
37
+ silence_warnings do
38
+ Object.const_set(:Rails, stub('Rails', :root => ROOT, :env => 'test'))
39
+ end
40
+ end
41
+ end
42
+
43
+ $LOAD_PATH << File.join(ROOT, 'lib')
44
+ $LOAD_PATH << File.join(ROOT, 'lib', 'paperclip')
45
+
46
+ require File.join(ROOT, 'lib', 'paperclip.rb')
47
+
48
+ require './shoulda_macros/paperclip'
49
+
50
+ FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
51
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
52
+ ActiveRecord::Base.logger = ActiveSupport::BufferedLogger.new(File.dirname(__FILE__) + "/debug.log")
53
+ ActiveRecord::Base.establish_connection(config['test'])
54
+ Paperclip.options[:logger] = ActiveRecord::Base.logger
55
+
56
+ def reset_class class_name
57
+ ActiveRecord::Base.send(:include, Paperclip::Glue)
58
+ Object.send(:remove_const, class_name) rescue nil
59
+ klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
60
+ klass.class_eval{ include Paperclip::Glue }
61
+ klass
62
+ end
63
+
64
+ def reset_table table_name, &block
65
+ block ||= lambda { |table| true }
66
+ ActiveRecord::Base.connection.create_table :dummies, {:force => true}, &block
67
+ end
68
+
69
+ def modify_table table_name, &block
70
+ ActiveRecord::Base.connection.change_table :dummies, &block
71
+ end
72
+
73
+ def rebuild_model options = {}
74
+ ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
75
+ table.column :title, :string
76
+ table.column :other, :string
77
+ table.column :avatar_file_name, :string
78
+ table.column :avatar_content_type, :string
79
+ table.column :avatar_file_size, :integer
80
+ table.column :avatar_updated_at, :datetime
81
+ table.column :avatar_fingerprint, :string
82
+ if options.delete(:with_dimensions)
83
+ table.column :avatar_width, :integer
84
+ table.column :avatar_height, :integer
85
+ end
86
+ end
87
+ rebuild_class options
88
+ end
89
+
90
+ def rebuild_class options = {}
91
+ ActiveRecord::Base.send(:include, Paperclip::Glue)
92
+ Object.send(:remove_const, "Dummy") rescue nil
93
+ Object.const_set("Dummy", Class.new(ActiveRecord::Base))
94
+ Paperclip.reset_duplicate_clash_check!
95
+ Dummy.class_eval do
96
+ include Paperclip::Glue
97
+ has_attached_file :avatar, options
98
+ end
99
+ Dummy.reset_column_information
100
+ end
101
+
102
+ class FakeModel
103
+ attr_accessor :avatar_file_name,
104
+ :avatar_file_size,
105
+ :avatar_updated_at,
106
+ :avatar_content_type,
107
+ :avatar_fingerprint,
108
+ :id
109
+
110
+ def errors
111
+ @errors ||= []
112
+ end
113
+
114
+ def run_paperclip_callbacks name, *args
115
+ end
116
+
117
+ end
118
+
119
+ def attachment options
120
+ Paperclip::Attachment.new(:avatar, FakeModel.new, options)
121
+ end
122
+
123
+ def silence_warnings
124
+ old_verbose, $VERBOSE = $VERBOSE, nil
125
+ yield
126
+ ensure
127
+ $VERBOSE = old_verbose
128
+ end
129
+
130
+ def should_accept_dummy_class
131
+ should "accept the class" do
132
+ assert_accepts @matcher, @dummy_class
133
+ end
134
+
135
+ should "accept an instance of that class" do
136
+ assert_accepts @matcher, @dummy_class.new
137
+ end
138
+ end
139
+
140
+ def should_reject_dummy_class
141
+ should "reject the class" do
142
+ assert_rejects @matcher, @dummy_class
143
+ end
144
+
145
+ should "reject an instance of that class" do
146
+ assert_rejects @matcher, @dummy_class.new
147
+ end
148
+ end
149
+
150
+ def with_exitstatus_returning(code)
151
+ saved_exitstatus = $?.nil? ? 0 : $?.exitstatus
152
+ begin
153
+ `ruby -e 'exit #{code.to_i}'`
154
+ yield
155
+ ensure
156
+ `ruby -e 'exit #{saved_exitstatus.to_i}'`
157
+ end
158
+ end