paperclip 4.3.7 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of paperclip might be problematic. Click here for more details.

Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -9
  3. data/Appraisals +22 -6
  4. data/CONTRIBUTING.md +16 -5
  5. data/Gemfile +2 -8
  6. data/LICENSE +1 -1
  7. data/NEWS +39 -27
  8. data/README.md +123 -101
  9. data/UPGRADING +12 -9
  10. data/features/basic_integration.feature +1 -0
  11. data/features/migration.feature +0 -24
  12. data/features/step_definitions/rails_steps.rb +0 -6
  13. data/features/step_definitions/s3_steps.rb +2 -2
  14. data/gemfiles/{4.1.gemfile → 4.2.awsv2.0.gemfile} +4 -6
  15. data/gemfiles/4.2.awsv2.1.gemfile +17 -0
  16. data/gemfiles/{4.2.gemfile → 4.2.awsv2.gemfile} +1 -0
  17. data/gemfiles/5.0.awsv2.0.gemfile +17 -0
  18. data/gemfiles/5.0.awsv2.1.gemfile +17 -0
  19. data/gemfiles/{3.2.gemfile → 5.0.awsv2.gemfile} +2 -1
  20. data/lib/paperclip.rb +2 -3
  21. data/lib/paperclip/attachment.rb +12 -10
  22. data/lib/paperclip/attachment_registry.rb +2 -1
  23. data/lib/paperclip/callbacks.rb +8 -6
  24. data/lib/paperclip/content_type_detector.rb +3 -2
  25. data/lib/paperclip/errors.rb +3 -1
  26. data/lib/paperclip/glue.rb +1 -1
  27. data/lib/paperclip/has_attached_file.rb +7 -1
  28. data/lib/paperclip/helpers.rb +14 -10
  29. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +1 -1
  30. data/lib/paperclip/io_adapters/uri_adapter.rb +12 -29
  31. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  32. data/lib/paperclip/schema.rb +2 -8
  33. data/lib/paperclip/storage/fog.rb +9 -6
  34. data/lib/paperclip/storage/s3.rb +42 -40
  35. data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
  36. data/lib/paperclip/version.rb +3 -1
  37. data/lib/tasks/paperclip.rake +1 -1
  38. data/paperclip.gemspec +11 -8
  39. data/spec/paperclip/attachment_processing_spec.rb +2 -4
  40. data/spec/paperclip/attachment_registry_spec.rb +28 -0
  41. data/spec/paperclip/attachment_spec.rb +33 -10
  42. data/spec/paperclip/has_attached_file_spec.rb +24 -8
  43. data/spec/paperclip/integration_spec.rb +4 -3
  44. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +17 -8
  45. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +32 -30
  46. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
  47. data/spec/paperclip/paperclip_spec.rb +3 -33
  48. data/spec/paperclip/storage/fog_spec.rb +10 -0
  49. data/spec/paperclip/storage/s3_live_spec.rb +8 -4
  50. data/spec/paperclip/storage/s3_spec.rb +213 -156
  51. data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
  52. data/spec/paperclip/validators_spec.rb +3 -3
  53. data/spec/spec_helper.rb +3 -1
  54. data/spec/support/assertions.rb +7 -0
  55. data/spec/support/model_reconstruction.rb +9 -1
  56. data/spec/support/reporting.rb +11 -0
  57. metadata +44 -37
  58. data/cucumber/paperclip_steps.rb +0 -6
  59. data/lib/paperclip/deprecations.rb +0 -42
  60. data/lib/paperclip/locales/de.yml +0 -18
  61. data/lib/paperclip/locales/es.yml +0 -18
  62. data/lib/paperclip/locales/ja.yml +0 -18
  63. data/lib/paperclip/locales/pt-BR.yml +0 -18
  64. data/lib/paperclip/locales/zh-CN.yml +0 -18
  65. data/lib/paperclip/locales/zh-HK.yml +0 -18
  66. data/lib/paperclip/locales/zh-TW.yml +0 -18
  67. data/spec/paperclip/deprecations_spec.rb +0 -65
  68. data/spec/support/deprecations.rb +0 -9
  69. data/spec/support/rails_helpers.rb +0 -7
@@ -2,8 +2,6 @@ require 'open-uri'
2
2
 
3
3
  module Paperclip
4
4
  class UriAdapter < AbstractAdapter
5
- attr_writer :content_type
6
-
7
5
  def initialize(target)
8
6
  @target = target
9
7
  @content = download_content
@@ -11,40 +9,25 @@ module Paperclip
11
9
  @tempfile = copy_to_tempfile(@content)
12
10
  end
13
11
 
14
- private
15
-
16
- def cache_current_values
17
- self.content_type = content_type_from_content || "text/html"
12
+ attr_writer :content_type
18
13
 
19
- self.original_filename = filename_from_content_disposition ||
20
- filename_from_path ||
21
- default_filename
22
- @size = @content.size
23
- end
14
+ private
24
15
 
25
- def content_type_from_content
26
- if @content.respond_to?(:content_type)
27
- @content.content_type
28
- end
29
- end
16
+ def download_content
17
+ options = { read_timeout: Paperclip.options[:read_timeout] }.compact
30
18
 
31
- def filename_from_content_disposition
32
- if @content.meta.has_key?("content-disposition")
33
- @content.meta["content-disposition"].
34
- match(/filename="([^"]*)"/)[1]
35
- end
19
+ open(@target, **options)
36
20
  end
37
21
 
38
- def filename_from_path
39
- @target.path.split("/").last
40
- end
22
+ def cache_current_values
23
+ @original_filename = @target.path.split("/").last
24
+ @original_filename ||= "index.html"
25
+ self.original_filename = @original_filename.strip
41
26
 
42
- def default_filename
43
- "index.html"
44
- end
27
+ @content_type = @content.content_type if @content.respond_to?(:content_type)
28
+ @content_type ||= "text/html"
45
29
 
46
- def download_content
47
- open(@target)
30
+ @size = @content.size
48
31
  end
49
32
 
50
33
  def copy_to_tempfile(src)
@@ -40,9 +40,9 @@ module Paperclip
40
40
 
41
41
  def failure_message
42
42
  "#{expected_attachment}\n".tap do |message|
43
- message << accepted_types_and_failures
43
+ message << accepted_types_and_failures.to_s
44
44
  message << "\n\n" if @allowed_types.present? && @rejected_types.present?
45
- message << rejected_types_and_failures
45
+ message << rejected_types_and_failures.to_s
46
46
  end
47
47
  end
48
48
 
@@ -55,7 +55,7 @@ module Paperclip
55
55
  def accepted_types_and_failures
56
56
  if @allowed_types.present?
57
57
  "Accept content types: #{@allowed_types.join(", ")}\n".tap do |message|
58
- if @missing_allowed_types.any?
58
+ if @missing_allowed_types.present?
59
59
  message << " #{@missing_allowed_types.join(", ")} were rejected."
60
60
  else
61
61
  message << " All were accepted successfully."
@@ -66,7 +66,7 @@ module Paperclip
66
66
  def rejected_types_and_failures
67
67
  if @rejected_types.present?
68
68
  "Reject content types: #{@rejected_types.join(", ")}\n".tap do |message|
69
- if @missing_rejected_types.any?
69
+ if @missing_rejected_types.present?
70
70
  message << " #{@missing_rejected_types.join(", ")} were accepted."
71
71
  else
72
72
  message << " All were rejected successfully."
@@ -12,10 +12,7 @@ module Paperclip
12
12
  ActiveRecord::ConnectionAdapters::Table.send :include, TableDefinition
13
13
  ActiveRecord::ConnectionAdapters::TableDefinition.send :include, TableDefinition
14
14
  ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, Statements
15
-
16
- if defined?(ActiveRecord::Migration::CommandRecorder) # Rails 3.1+
17
- ActiveRecord::Migration::CommandRecorder.send :include, CommandRecorder
18
- end
15
+ ActiveRecord::Migration::CommandRecorder.send :include, CommandRecorder
19
16
  end
20
17
 
21
18
  module Statements
@@ -35,11 +32,8 @@ module Paperclip
35
32
  def remove_attachment(table_name, *attachment_names)
36
33
  raise ArgumentError, "Please specify attachment name in your remove_attachment call in your migration." if attachment_names.empty?
37
34
 
38
- options = attachment_names.extract_options!
39
-
40
35
  attachment_names.each do |attachment_name|
41
- COLUMNS.each_pair do |column_name, column_type|
42
- column_options = options.merge(options[column_name.to_sym] || {})
36
+ COLUMNS.keys.each do |column_name|
43
37
  remove_column(table_name, "#{attachment_name}_#{column_name}")
44
38
  end
45
39
  end
@@ -170,6 +170,7 @@ module Paperclip
170
170
  log("copying #{path(style)} to local file #{local_dest_path}")
171
171
  ::File.open(local_dest_path, 'wb') do |local_file|
172
172
  file = directory.files.get(path(style))
173
+ return false unless file
173
174
  local_file.write(file.body)
174
175
  end
175
176
  rescue ::Fog::Errors::Error => e
@@ -195,10 +196,10 @@ module Paperclip
195
196
  end
196
197
 
197
198
  def host_name_for_directory
198
- if @options[:fog_directory].to_s =~ Fog::AWS_BUCKET_SUBDOMAIN_RESTRICTON_REGEX
199
- "#{@options[:fog_directory]}.s3.amazonaws.com"
199
+ if directory_name.to_s =~ Fog::AWS_BUCKET_SUBDOMAIN_RESTRICTON_REGEX
200
+ "#{directory_name}.s3.amazonaws.com"
200
201
  else
201
- "s3.amazonaws.com/#{@options[:fog_directory]}"
202
+ "s3.amazonaws.com/#{directory_name}"
202
203
  end
203
204
  end
204
205
 
@@ -224,13 +225,15 @@ module Paperclip
224
225
  end
225
226
 
226
227
  def directory
227
- dir = if @options[:fog_directory].respond_to?(:call)
228
+ @directory ||= connection.directories.new(key: directory_name)
229
+ end
230
+
231
+ def directory_name
232
+ if @options[:fog_directory].respond_to?(:call)
228
233
  @options[:fog_directory].call(self)
229
234
  else
230
235
  @options[:fog_directory]
231
236
  end
232
-
233
- @directory ||= connection.directories.new(:key => dir)
234
237
  end
235
238
 
236
239
  def scheme
@@ -4,7 +4,7 @@ module Paperclip
4
4
  # distribution. You can find out more about it at http://aws.amazon.com/s3
5
5
  #
6
6
  # To use Paperclip with S3, include the +aws-sdk+ gem in your Gemfile:
7
- # gem 'aws-sdk', '~> 1.6'
7
+ # gem 'aws-sdk'
8
8
  # There are a few S3-specific options for has_attached_file:
9
9
  # * +s3_credentials+: Takes a path, a File, a Hash or a Proc. The path (or File) must point
10
10
  # to a YAML file containing the +access_key_id+ and +secret_access_key+ that Amazon
@@ -41,7 +41,7 @@ module Paperclip
41
41
  # * +s3_permissions+: This is a String that should be one of the "canned" access
42
42
  # policies that S3 provides (more information can be found here:
43
43
  # http://docs.aws.amazon.com/AmazonS3/latest/dev/ACLOverview.html)
44
- # The default for Paperclip is :public_read.
44
+ # The default for Paperclip is public-read.
45
45
  #
46
46
  # You can set permission on a per style bases by doing the following:
47
47
  # :s3_permissions => {
@@ -61,7 +61,7 @@ module Paperclip
61
61
  # * +bucket+: This is the name of the S3 bucket that will store your files. Remember
62
62
  # that the bucket must be unique across all of Amazon S3. If the bucket does not exist
63
63
  # Paperclip will attempt to create it. The bucket name will not be interpolated.
64
- # You can define the bucket as a Proc if you want to determine it's name at runtime.
64
+ # You can define the bucket as a Proc if you want to determine its name at runtime.
65
65
  # Paperclip will call that Proc with attachment as the only argument.
66
66
  # * +s3_host_alias+: The fully-qualified domain name (FQDN) that is the alias to the
67
67
  # S3 domain of your bucket. Used with the :s3_alias_url url interpolation. See the
@@ -93,6 +93,7 @@ module Paperclip
93
93
  # S3 (strictly speaking) does not support directories, you can still use a / to
94
94
  # separate parts of your file name.
95
95
  # * +s3_host_name+: If you are using your bucket in Tokyo region etc, write host_name.
96
+ # * +s3_region+: For aws-sdk v2, s3_region is required.
96
97
  # * +s3_metadata+: These key/value pairs will be stored with the
97
98
  # object. This option works by prefixing each key with
98
99
  # "x-amz-meta-" before sending it as a header on the object
@@ -117,21 +118,10 @@ module Paperclip
117
118
  rescue LoadError => e
118
119
  e.message << " (You may need to install the aws-sdk gem)"
119
120
  raise e
120
- end unless defined?(AWS::Core)
121
-
122
- # Overriding log formatter to make sure it return a UTF-8 string
123
- if defined?(AWS::Core::LogFormatter)
124
- AWS::Core::LogFormatter.class_eval do
125
- def summarize_hash(hash)
126
- hash.map { |key, value| ":#{key}=>#{summarize_value(value)}".force_encoding('UTF-8') }.sort.join(',')
127
- end
128
- end
129
- elsif defined?(AWS::Core::ClientLogging)
130
- AWS::Core::ClientLogging.class_eval do
131
- def sanitize_hash(hash)
132
- hash.map { |key, value| "#{sanitize_value(key)}=>#{sanitize_value(value)}".force_encoding('UTF-8') }.sort.join(',')
133
- end
134
- end
121
+ end
122
+ if Gem::Version.new(Aws::VERSION) >= Gem::Version.new(2) &&
123
+ Gem::Version.new(Aws::VERSION) <= Gem::Version.new("2.0.33")
124
+ raise LoadError, "paperclip does not support aws-sdk versions 2.0.0 - 2.0.33. Please upgrade aws-sdk to a newer version."
135
125
  end
136
126
 
137
127
  base.instance_eval do
@@ -141,7 +131,7 @@ module Paperclip
141
131
  Proc.new do |style, attachment|
142
132
  permission = (@s3_permissions[style.to_s.to_sym] || @s3_permissions[:default])
143
133
  permission = permission.call(attachment, style) if permission.respond_to?(:call)
144
- (permission == :public_read) ? 'http'.freeze : 'https'.freeze
134
+ (permission == :"public-read") ? 'http'.freeze : 'https'.freeze
145
135
  end
146
136
  @s3_metadata = @options[:s3_metadata] || {}
147
137
  @s3_headers = {}
@@ -149,7 +139,7 @@ module Paperclip
149
139
 
150
140
  @s3_storage_class = set_storage_class(@options[:s3_storage_class])
151
141
 
152
- @s3_server_side_encryption = :aes256
142
+ @s3_server_side_encryption = "AES256"
153
143
  if @options[:s3_server_side_encryption].blank?
154
144
  @s3_server_side_encryption = false
155
145
  end
@@ -182,8 +172,11 @@ module Paperclip
182
172
 
183
173
  def expiring_url(time = 3600, style_name = default_style)
184
174
  if path(style_name)
185
- base_options = { :expires => time, :secure => use_secure_protocol?(style_name) }
186
- s3_object(style_name).url_for(:read, base_options.merge(s3_url_options)).to_s
175
+ base_options = { expires_in: time }
176
+ s3_object(style_name).presigned_url(
177
+ :get,
178
+ base_options.merge(s3_url_options),
179
+ ).to_s
187
180
  else
188
181
  url(style_name)
189
182
  end
@@ -200,6 +193,13 @@ module Paperclip
200
193
  host_name || s3_credentials[:s3_host_name] || "s3.amazonaws.com".freeze
201
194
  end
202
195
 
196
+ def s3_region
197
+ region = @options[:s3_region]
198
+ region = region.call(self) if region.is_a?(Proc)
199
+
200
+ region || s3_credentials[:s3_region]
201
+ end
202
+
203
203
  def s3_host_alias
204
204
  @s3_host_alias = @options[:s3_host_alias]
205
205
  @s3_host_alias = @s3_host_alias.call(self) if @s3_host_alias.respond_to?(:call)
@@ -220,7 +220,7 @@ module Paperclip
220
220
 
221
221
  def s3_interface
222
222
  @s3_interface ||= begin
223
- config = { :s3_endpoint => s3_host_name }
223
+ config = { region: s3_region }
224
224
 
225
225
  if using_http_proxy?
226
226
 
@@ -234,7 +234,7 @@ module Paperclip
234
234
  config[:proxy_uri] = URI::HTTP.build(proxy_opts)
235
235
  end
236
236
 
237
- [:access_key_id, :secret_access_key, :credential_provider].each do |opt|
237
+ [:access_key_id, :secret_access_key, :credential_provider, :credentials].each do |opt|
238
238
  config[opt] = s3_credentials[opt] if s3_credentials[opt]
239
239
  end
240
240
 
@@ -244,15 +244,19 @@ module Paperclip
244
244
 
245
245
  def obtain_s3_instance_for(options)
246
246
  instances = (Thread.current[:paperclip_s3_instances] ||= {})
247
- instances[options] ||= AWS::S3.new(options)
247
+ instances[options] ||= ::Aws::S3::Resource.new(options)
248
248
  end
249
249
 
250
250
  def s3_bucket
251
- @s3_bucket ||= s3_interface.buckets[bucket_name]
251
+ @s3_bucket ||= s3_interface.bucket(bucket_name)
252
+ end
253
+
254
+ def style_name_as_path(style_name)
255
+ path(style_name).sub(%r{\A/},'')
252
256
  end
253
257
 
254
258
  def s3_object style_name = default_style
255
- s3_bucket.objects[path(style_name).sub(%r{\A/},'')]
259
+ s3_bucket.object style_name_as_path(style_name)
256
260
  end
257
261
 
258
262
  def using_http_proxy?
@@ -277,7 +281,7 @@ module Paperclip
277
281
 
278
282
  def set_permissions permissions
279
283
  permissions = { :default => permissions } unless permissions.respond_to?(:merge)
280
- permissions.merge :default => (permissions[:default] || :public_read)
284
+ permissions.merge :default => (permissions[:default] || :"public-read")
281
285
  end
282
286
 
283
287
  def set_storage_class(storage_class)
@@ -297,7 +301,7 @@ module Paperclip
297
301
  else
298
302
  false
299
303
  end
300
- rescue AWS::Errors::Base => e
304
+ rescue Aws::Errors::ServiceError => e
301
305
  false
302
306
  end
303
307
 
@@ -323,7 +327,7 @@ module Paperclip
323
327
  end
324
328
 
325
329
  def create_bucket
326
- s3_interface.buckets.create(bucket_name)
330
+ s3_interface.bucket(bucket_name).create
327
331
  end
328
332
 
329
333
  def flush_writes #:nodoc:
@@ -331,11 +335,9 @@ module Paperclip
331
335
  retries = 0
332
336
  begin
333
337
  log("saving #{path(style)}")
334
- acl = @s3_permissions[style] || @s3_permissions[:default]
335
- acl = acl.call(self, style) if acl.respond_to?(:call)
336
338
  write_options = {
337
339
  :content_type => file.content_type,
338
- :acl => acl
340
+ :acl => s3_permissions(style)
339
341
  }
340
342
 
341
343
  # add storage class for this style if defined
@@ -356,11 +358,11 @@ module Paperclip
356
358
  write_options[:metadata] = @s3_metadata unless @s3_metadata.empty?
357
359
  write_options.merge!(@s3_headers)
358
360
 
359
- s3_object(style).write(file, write_options)
360
- rescue AWS::S3::Errors::NoSuchBucket
361
+ s3_object(style).upload_file(file.path, write_options)
362
+ rescue ::Aws::S3::Errors::NoSuchBucket
361
363
  create_bucket
362
364
  retry
363
- rescue AWS::S3::Errors::SlowDown
365
+ rescue ::Aws::S3::Errors::SlowDown
364
366
  retries += 1
365
367
  if retries <= 5
366
368
  sleep((2 ** retries) * 0.5)
@@ -382,8 +384,8 @@ module Paperclip
382
384
  @queued_for_delete.each do |path|
383
385
  begin
384
386
  log("deleting #{path}")
385
- s3_bucket.objects[path.sub(%r{\A/},'')].delete
386
- rescue AWS::Errors::Base => e
387
+ s3_bucket.object(path.sub(%r{\A/}, "")).delete
388
+ rescue Aws::Errors::ServiceError => e
387
389
  # Ignore this.
388
390
  end
389
391
  end
@@ -393,11 +395,11 @@ module Paperclip
393
395
  def copy_to_local_file(style, local_dest_path)
394
396
  log("copying #{path(style)} to local file #{local_dest_path}")
395
397
  ::File.open(local_dest_path, 'wb') do |local_file|
396
- s3_object(style).read do |chunk|
398
+ s3_object(style).get do |chunk|
397
399
  local_file.write(chunk)
398
400
  end
399
401
  end
400
- rescue AWS::Errors::Base => e
402
+ rescue Aws::Errors::ServiceError => e
401
403
  warn("#{e} - cannot copy #{path(style)} to local file #{local_dest_path}")
402
404
  false
403
405
  end
@@ -71,13 +71,7 @@ module Paperclip
71
71
  end
72
72
 
73
73
  def human_size(size)
74
- if defined?(ActiveSupport::NumberHelper) # Rails 4.0+
75
- ActiveSupport::NumberHelper.number_to_human_size(size)
76
- else
77
- storage_units_format = I18n.translate(:'number.human.storage_units.format', :locale => options[:locale], :raise => true)
78
- unit = I18n.translate(:'number.human.storage_units.units.byte', :locale => options[:locale], :count => size.to_i, :raise => true)
79
- storage_units_format.gsub(/%n/, size.to_i.to_s).gsub(/%u/, unit).html_safe
80
- end
74
+ ActiveSupport::NumberHelper.number_to_human_size(size)
81
75
  end
82
76
 
83
77
  def min_value_in_human_size(record)
@@ -1,3 +1,5 @@
1
1
  module Paperclip
2
- VERSION = "4.3.7".freeze unless defined? Paperclip::VERSION
2
+ unless defined?(Paperclip::VERSION)
3
+ VERSION = "5.0.0".freeze
4
+ end
3
5
  end
@@ -18,7 +18,7 @@ module Paperclip
18
18
  raise "Class #{klass.name} has no attachments specified"
19
19
  end
20
20
 
21
- if !name.blank? && attachment_names.map(&:to_s).include?(name.to_s)
21
+ if name.present? && attachment_names.map(&:to_s).include?(name.to_s)
22
22
  [ name ]
23
23
  else
24
24
  attachment_names
data/paperclip.gemspec CHANGED
@@ -17,26 +17,29 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
+ if File.exist?('UPGRADING')
21
+ s.post_install_message = File.read("UPGRADING")
22
+ end
23
+
20
24
  s.requirements << "ImageMagick"
21
- s.required_ruby_version = ">= 1.9.2"
25
+ s.required_ruby_version = ">= 2.1.0"
22
26
 
23
- s.add_dependency('activemodel', '>= 3.2.0')
24
- s.add_dependency('activesupport', '>= 3.2.0')
27
+ s.add_dependency('activemodel', '>= 4.2.0')
28
+ s.add_dependency('activesupport', '>= 4.2.0')
25
29
  s.add_dependency('cocaine', '~> 0.5.5')
26
30
  s.add_dependency('mime-types')
27
- s.add_dependency('mimemagic', '0.3.0')
31
+ s.add_dependency('mimemagic', '~> 0.3.0')
28
32
 
29
- s.add_development_dependency('activerecord', '>= 3.2.0')
33
+ s.add_development_dependency('activerecord', '>= 4.2.0')
30
34
  s.add_development_dependency('shoulda')
31
35
  s.add_development_dependency('rspec', '~> 3.0')
32
36
  s.add_development_dependency('appraisal')
33
37
  s.add_development_dependency('mocha')
34
- s.add_development_dependency('aws-sdk', '>= 1.5.7', "<= 2.0")
38
+ s.add_development_dependency('aws-sdk', '>= 2.0.34', '< 3.0')
35
39
  s.add_development_dependency('bourne')
36
40
  s.add_development_dependency('cucumber', '~> 1.3.18')
37
41
  s.add_development_dependency('aruba', '~> 0.9.0')
38
42
  s.add_development_dependency('nokogiri')
39
- # Ruby version < 1.9.3 can't install capybara > 2.0.3.
40
43
  s.add_development_dependency('capybara')
41
44
  s.add_development_dependency('bundler')
42
45
  s.add_development_dependency('fog-aws')
@@ -45,7 +48,7 @@ Gem::Specification.new do |s|
45
48
  s.add_development_dependency('rake')
46
49
  s.add_development_dependency('fakeweb')
47
50
  s.add_development_dependency('railties')
48
- s.add_development_dependency('actionmailer', '>= 3.2.0')
51
+ s.add_development_dependency('actionmailer', '>= 4.2.0')
49
52
  s.add_development_dependency('generator_spec')
50
53
  s.add_development_dependency('timecop')
51
54
  end