mbailey-paperclip 2.3.2

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 (56) hide show
  1. data/LICENSE +26 -0
  2. data/README.rdoc +179 -0
  3. data/Rakefile +76 -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 +1 -0
  8. data/lib/generators/paperclip/USAGE +8 -0
  9. data/lib/generators/paperclip/paperclip_generator.rb +31 -0
  10. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  11. data/lib/paperclip/attachment.rb +326 -0
  12. data/lib/paperclip/callback_compatability.rb +61 -0
  13. data/lib/paperclip/geometry.rb +115 -0
  14. data/lib/paperclip/interpolations.rb +108 -0
  15. data/lib/paperclip/iostream.rb +59 -0
  16. data/lib/paperclip/matchers/have_attached_file_matcher.rb +57 -0
  17. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +74 -0
  18. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +54 -0
  19. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +95 -0
  20. data/lib/paperclip/matchers.rb +33 -0
  21. data/lib/paperclip/processor.rb +49 -0
  22. data/lib/paperclip/railtie.rb +24 -0
  23. data/lib/paperclip/storage.rb +247 -0
  24. data/lib/paperclip/style.rb +90 -0
  25. data/lib/paperclip/thumbnail.rb +78 -0
  26. data/lib/paperclip/upfile.rb +52 -0
  27. data/lib/paperclip/version.rb +3 -0
  28. data/lib/paperclip.rb +397 -0
  29. data/lib/tasks/paperclip.rake +79 -0
  30. data/rails/init.rb +2 -0
  31. data/shoulda_macros/paperclip.rb +119 -0
  32. data/test/attachment_test.rb +758 -0
  33. data/test/database.yml +4 -0
  34. data/test/fixtures/12k.png +0 -0
  35. data/test/fixtures/50x50.png +0 -0
  36. data/test/fixtures/5k.png +0 -0
  37. data/test/fixtures/bad.png +1 -0
  38. data/test/fixtures/s3.yml +8 -0
  39. data/test/fixtures/text.txt +0 -0
  40. data/test/fixtures/twopage.pdf +0 -0
  41. data/test/geometry_test.rb +177 -0
  42. data/test/helper.rb +148 -0
  43. data/test/integration_test.rb +483 -0
  44. data/test/interpolations_test.rb +124 -0
  45. data/test/iostream_test.rb +78 -0
  46. data/test/matchers/have_attached_file_matcher_test.rb +24 -0
  47. data/test/matchers/validate_attachment_content_type_matcher_test.rb +37 -0
  48. data/test/matchers/validate_attachment_presence_matcher_test.rb +26 -0
  49. data/test/matchers/validate_attachment_size_matcher_test.rb +51 -0
  50. data/test/paperclip_test.rb +317 -0
  51. data/test/processor_test.rb +10 -0
  52. data/test/storage_test.rb +343 -0
  53. data/test/style_test.rb +141 -0
  54. data/test/thumbnail_test.rb +227 -0
  55. data/test/upfile_test.rb +36 -0
  56. metadata +205 -0
@@ -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
data/rails/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'paperclip/railtie'
2
+ Paperclip::Railtie.insert
@@ -0,0 +1,119 @@
1
+ require 'paperclip/matchers'
2
+ require 'action_controller'
3
+
4
+ module Paperclip
5
+ # =Paperclip Shoulda Macros
6
+ #
7
+ # These macros are intended for use with shoulda, and will be included into
8
+ # your tests automatically. All of the macros use the standard shoulda
9
+ # assumption that the name of the test is based on the name of the model
10
+ # you're testing (that is, UserTest is the test for the User model), and
11
+ # will load that class for testing purposes.
12
+ module Shoulda
13
+ include Matchers
14
+ # This will test whether you have defined your attachment correctly by
15
+ # checking for all the required fields exist after the definition of the
16
+ # attachment.
17
+ def should_have_attached_file name
18
+ klass = self.name.gsub(/Test$/, '').constantize
19
+ matcher = have_attached_file name
20
+ should matcher.description do
21
+ assert_accepts(matcher, klass)
22
+ end
23
+ end
24
+
25
+ # Tests for validations on the presence of the attachment.
26
+ def should_validate_attachment_presence name
27
+ klass = self.name.gsub(/Test$/, '').constantize
28
+ matcher = validate_attachment_presence name
29
+ should matcher.description do
30
+ assert_accepts(matcher, klass)
31
+ end
32
+ end
33
+
34
+ # Tests that you have content_type validations specified. There are two
35
+ # options, :valid and :invalid. Both accept an array of strings. The
36
+ # strings should be a list of content types which will pass and fail
37
+ # validation, respectively.
38
+ def should_validate_attachment_content_type name, options = {}
39
+ klass = self.name.gsub(/Test$/, '').constantize
40
+ valid = [options[:valid]].flatten
41
+ invalid = [options[:invalid]].flatten
42
+ matcher = validate_attachment_content_type(name).allowing(valid).rejecting(invalid)
43
+ should matcher.description do
44
+ assert_accepts(matcher, klass)
45
+ end
46
+ end
47
+
48
+ # Tests to ensure that you have file size validations turned on. You
49
+ # can pass the same options to this that you can to
50
+ # validate_attachment_file_size - :less_than, :greater_than, and :in.
51
+ # :less_than checks that a file is less than a certain size, :greater_than
52
+ # checks that a file is more than a certain size, and :in takes a Range or
53
+ # Array which specifies the lower and upper limits of the file size.
54
+ def should_validate_attachment_size name, options = {}
55
+ klass = self.name.gsub(/Test$/, '').constantize
56
+ min = options[:greater_than] || (options[:in] && options[:in].first) || 0
57
+ max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
58
+ range = (min..max)
59
+ matcher = validate_attachment_size(name).in(range)
60
+ should matcher.description do
61
+ assert_accepts(matcher, klass)
62
+ end
63
+ end
64
+
65
+ # Stubs the HTTP PUT for an attachment using S3 storage.
66
+ #
67
+ # @example
68
+ # stub_paperclip_s3('user', 'avatar', 'png')
69
+ def stub_paperclip_s3(model, attachment, extension)
70
+ definition = model.gsub(" ", "_").classify.constantize.
71
+ attachment_definitions[attachment.to_sym]
72
+
73
+ path = "http://s3.amazonaws.com/:id/#{definition[:path]}"
74
+ path.gsub!(/:([^\/\.]+)/) do |match|
75
+ "([^\/\.]+)"
76
+ end
77
+
78
+ begin
79
+ FakeWeb.register_uri(:put, Regexp.new(path), :body => "OK")
80
+ rescue NameError
81
+ raise NameError, "the stub_paperclip_s3 shoulda macro requires the fakeweb gem."
82
+ end
83
+ end
84
+
85
+ # Stub S3 and return a file for attachment. Best with Factory Girl.
86
+ # Uses a strict directory convention:
87
+ #
88
+ # features/support/paperclip
89
+ #
90
+ # This method is used by the Paperclip-provided Cucumber step:
91
+ #
92
+ # When I attach a "demo_tape" "mp3" file to a "band" on S3
93
+ #
94
+ # @example
95
+ # Factory.define :band_with_demo_tape, :parent => :band do |band|
96
+ # band.demo_tape { band.paperclip_fixture("band", "demo_tape", "png") }
97
+ # end
98
+ def paperclip_fixture(model, attachment, extension)
99
+ stub_paperclip_s3(model, attachment, extension)
100
+ base_path = File.join(File.dirname(__FILE__), "..", "..",
101
+ "features", "support", "paperclip")
102
+ File.new(File.join(base_path, model, "#{attachment}.#{extension}"))
103
+ end
104
+ end
105
+ end
106
+
107
+ if defined?(ActionController::Integration::Session)
108
+ class ActionController::Integration::Session #:nodoc:
109
+ include Paperclip::Shoulda
110
+ end
111
+ end
112
+
113
+ class Factory
114
+ include Paperclip::Shoulda #:nodoc:
115
+ end
116
+
117
+ class Test::Unit::TestCase #:nodoc:
118
+ extend Paperclip::Shoulda
119
+ end