attachs 0.3.0
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +98 -0
- data/Rakefile +34 -0
- data/app/controllers/attachs/presets_controller.rb +17 -0
- data/config/locales/en.yml +8 -0
- data/config/locales/es.yml +8 -0
- data/config/routes.rb +5 -0
- data/lib/attachs.rb +16 -0
- data/lib/attachs/active_record/base.rb +145 -0
- data/lib/attachs/engine.rb +7 -0
- data/lib/attachs/magick/image.rb +85 -0
- data/lib/attachs/railtie.rb +20 -0
- data/lib/attachs/storages/local.rb +61 -0
- data/lib/attachs/storages/s3.rb +77 -0
- data/lib/attachs/types/file.rb +113 -0
- data/lib/attachs/types/image.rb +40 -0
- data/lib/attachs/validators/attachment_content_type_validator.rb +11 -0
- data/lib/attachs/validators/attachment_presence_validator.rb +9 -0
- data/lib/attachs/validators/attachment_size_validator.rb +27 -0
- data/lib/attachs/validators/base.rb +13 -0
- data/lib/attachs/version.rb +5 -0
- data/lib/generators/attachs/s3/config_generator.rb +13 -0
- data/lib/generators/attachs/s3/templates/s3.yml +16 -0
- data/lib/tasks/attachs_tasks.rake +71 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/all_attached.rb +16 -0
- data/test/dummy/app/models/file_attached.rb +3 -0
- data/test/dummy/app/models/image_attached.rb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +29 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20130820222342_create_file_attacheds.rb +9 -0
- data/test/dummy/db/migrate/20130820222355_create_image_attacheds.rb +9 -0
- data/test/dummy/db/migrate/20130820222534_create_all_attacheds.rb +19 -0
- data/test/dummy/db/schema.rb +44 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +28 -0
- data/test/dummy/log/test.log +8545 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/public/uploads/files/file.txt +1 -0
- data/test/dummy/public/uploads/images/big/image.jpg +0 -0
- data/test/dummy/public/uploads/images/original/image.jpg +0 -0
- data/test/dummy/public/uploads/images/small/image.jpg +0 -0
- data/test/dummy/test/fixtures/file.txt +1 -0
- data/test/dummy/test/fixtures/file_big.txt +1 -0
- data/test/dummy/test/fixtures/file_empty.txt +1 -0
- data/test/dummy/test/fixtures/image.jpg +0 -0
- data/test/dummy/test/fixtures/image_big.jpg +0 -0
- data/test/dummy/test/fixtures/image_empty.jpg +0 -0
- data/test/local_file_record_test.rb +20 -0
- data/test/local_file_string_test.rb +23 -0
- data/test/local_file_upload_test.rb +30 -0
- data/test/local_generate_test.rb +25 -0
- data/test/local_image_record_test.rb +25 -0
- data/test/local_image_string_test.rb +34 -0
- data/test/local_image_upload_test.rb +27 -0
- data/test/local_records_test.rb +52 -0
- data/test/local_validators_test.rb +71 -0
- data/test/s3_file_record_tes.rb +21 -0
- data/test/s3_file_string_tes.rb +24 -0
- data/test/s3_file_upload_tes.rb +31 -0
- data/test/s3_image_record_tes.rb +26 -0
- data/test/s3_image_string_tes.rb +31 -0
- data/test/s3_image_upload_tes.rb +28 -0
- data/test/s3_records_tes.rb +56 -0
- data/test/s3_validators_tes.rb +72 -0
- data/test/test_helper.rb +49 -0
- metadata +250 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Attachs
|
|
2
|
+
class Railtie < Rails::Railtie
|
|
3
|
+
|
|
4
|
+
config.attachs = ActiveSupport::OrderedOptions.new
|
|
5
|
+
config.attachs.presets = {}
|
|
6
|
+
config.attachs.default_presets = []
|
|
7
|
+
config.attachs.default_validations = {}
|
|
8
|
+
config.attachs.base_url = ''
|
|
9
|
+
config.attachs.storage = :local
|
|
10
|
+
|
|
11
|
+
initializer 'attachs' do
|
|
12
|
+
::ActiveRecord::Base.send :include, Attachs::ActiveRecord::Base
|
|
13
|
+
if config.attachs.storage == :s3
|
|
14
|
+
require 'aws-sdk'
|
|
15
|
+
Attachs::Storages::S3.config = YAML.load_file(Rails.root.join('config', 's3.yml'))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Attachs
|
|
2
|
+
module Storages
|
|
3
|
+
class Local
|
|
4
|
+
|
|
5
|
+
def initialize(default)
|
|
6
|
+
@tmp = (Rails.env.test? and !default)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def exists?(path)
|
|
10
|
+
::File.exists? realpath(path)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def size(path)
|
|
14
|
+
::File.size realpath(path)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def url(path)
|
|
18
|
+
::File.join Rails.application.config.attachs.base_url, path
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def store(upload, path)
|
|
22
|
+
create_dir realpath(path)
|
|
23
|
+
upload.rewind # Hack to avoid empty files
|
|
24
|
+
::File.open(realpath(path), 'wb') do |file|
|
|
25
|
+
while chunk = upload.read(16 * 1024)
|
|
26
|
+
file.write(chunk)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def delete(path)
|
|
32
|
+
::File.delete realpath(path)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def magick(source, output, upload)
|
|
36
|
+
create_dir realpath(output)
|
|
37
|
+
yield Attachs::Magick::Image.new(realpath(source), realpath(output))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
protected
|
|
41
|
+
|
|
42
|
+
def tmp?
|
|
43
|
+
@tmp == true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def realpath(path)
|
|
47
|
+
base_path.join path
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def base_path
|
|
51
|
+
Rails.root.join tmp? ? 'tmp' : 'public'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def create_dir(path)
|
|
55
|
+
dir = base_path.join('uploads', path).dirname
|
|
56
|
+
FileUtils.mkdir_p dir unless ::File.directory? dir
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module Attachs
|
|
2
|
+
module Storages
|
|
3
|
+
class S3
|
|
4
|
+
|
|
5
|
+
cattr_accessor :config
|
|
6
|
+
|
|
7
|
+
def initialize(default)
|
|
8
|
+
if (Rails.env.test? and !default)
|
|
9
|
+
env = 'test'
|
|
10
|
+
elsif default
|
|
11
|
+
env = 'production'
|
|
12
|
+
else
|
|
13
|
+
env = Rails.env
|
|
14
|
+
end
|
|
15
|
+
config = self.class.config[env]
|
|
16
|
+
AWS.config access_key_id: config['access_key_id'], secret_access_key: config['secret_access_key']
|
|
17
|
+
@bucket = AWS::S3.new.buckets[config['bucket']]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def exists?(path)
|
|
21
|
+
object(path).exists?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def size(path)
|
|
25
|
+
object(path).content_length
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def url(path)
|
|
29
|
+
base_url = Rails.application.config.attachs.base_url
|
|
30
|
+
base_url.present? ? ::File.join(base_url, path) : object(path).public_url(secure: false)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def store(upload, path)
|
|
34
|
+
bucket.objects.create(path, Pathname.new(upload.path)).acl = :public_read
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def delete(path)
|
|
38
|
+
object(path).delete
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def magick(source, output, upload)
|
|
42
|
+
if cache[source].blank?
|
|
43
|
+
if upload.present?
|
|
44
|
+
cache[source] = upload.path
|
|
45
|
+
else
|
|
46
|
+
remote = create_tmp_file
|
|
47
|
+
remote.binmode
|
|
48
|
+
object(source).read { |chunk| remote.write(chunk) }
|
|
49
|
+
remote.close
|
|
50
|
+
remote.open
|
|
51
|
+
cache[source] = remote.path
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
tmp = create_tmp_file
|
|
55
|
+
yield Attachs::Magick::Image.new(cache[source], tmp.path)
|
|
56
|
+
store tmp, output
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
protected
|
|
60
|
+
|
|
61
|
+
attr_reader :bucket
|
|
62
|
+
|
|
63
|
+
def create_tmp_file
|
|
64
|
+
Tempfile.new('s3')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def cache
|
|
68
|
+
@cache ||= {}
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def object(path)
|
|
72
|
+
bucket.objects[path]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module Attachs
|
|
2
|
+
module Types
|
|
3
|
+
class File
|
|
4
|
+
|
|
5
|
+
def initialize(source, options={})
|
|
6
|
+
if source.is_a? ActionDispatch::Http::UploadedFile or source.is_a? Rack::Test::UploadedFile
|
|
7
|
+
@upload = source
|
|
8
|
+
@stored = false
|
|
9
|
+
@default = false
|
|
10
|
+
@storage = build_storage(:local)
|
|
11
|
+
elsif source.is_a? String
|
|
12
|
+
@upload = false
|
|
13
|
+
@filename = source
|
|
14
|
+
@stored = true
|
|
15
|
+
@default = false
|
|
16
|
+
@storage = build_storage
|
|
17
|
+
elsif options.has_key? :default
|
|
18
|
+
@upload = false
|
|
19
|
+
@filename = options[:default]
|
|
20
|
+
@stored = true
|
|
21
|
+
@default = true
|
|
22
|
+
@storage = build_storage
|
|
23
|
+
end
|
|
24
|
+
@deleted = false
|
|
25
|
+
@options = options
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def default?
|
|
29
|
+
@default == true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def stored?
|
|
33
|
+
@stored == true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def deleted?
|
|
37
|
+
@deleted == true
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def exists?(*args)
|
|
41
|
+
return false if deleted?
|
|
42
|
+
storage.exists? path(*args)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def size(*args)
|
|
46
|
+
return 0 if deleted?
|
|
47
|
+
storage.size path(*args)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def extname
|
|
51
|
+
return nil if deleted?
|
|
52
|
+
@extname ||= ::File.extname(filename)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def filename
|
|
56
|
+
return nil if deleted?
|
|
57
|
+
@filename ||= "#{(Time.now.to_f * 10000000).to_i}#{::File.extname upload.original_filename}".downcase
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def path(*args)
|
|
61
|
+
return nil if deleted?
|
|
62
|
+
stored? ? destination_path(*args) : upload.path
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def url(*args)
|
|
66
|
+
return nil if deleted? or not stored?
|
|
67
|
+
storage.url path(*args)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def store
|
|
71
|
+
if not stored? and upload?
|
|
72
|
+
@storage = build_storage
|
|
73
|
+
storage.store upload, destination_path
|
|
74
|
+
yield if block_given?
|
|
75
|
+
@stored = true
|
|
76
|
+
@deleted = false
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def delete
|
|
81
|
+
if not default? and stored? and exists?
|
|
82
|
+
storage.delete path
|
|
83
|
+
yield if block_given?
|
|
84
|
+
@storage = build_storage(:local) if upload?
|
|
85
|
+
@stored = false
|
|
86
|
+
@deleted = true
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
protected
|
|
91
|
+
|
|
92
|
+
attr_reader :upload, :storage, :options
|
|
93
|
+
|
|
94
|
+
def build_storage(type=nil)
|
|
95
|
+
type ||= Rails.application.config.attachs.storage
|
|
96
|
+
Attachs::Storages.const_get(type.to_s.classify).new default?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def upload?
|
|
100
|
+
upload.present?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def destination_path(*args)
|
|
104
|
+
::File.join 'uploads', store_path(*args), filename
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def store_path(*args)
|
|
108
|
+
'files'
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Attachs
|
|
2
|
+
module Types
|
|
3
|
+
class Image < File
|
|
4
|
+
|
|
5
|
+
def presets
|
|
6
|
+
Rails.application.config.attachs.default_presets | (options[:presets] || [])
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def store
|
|
10
|
+
super { presets.each { |name| generate_preset name } if presets.any? }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def delete
|
|
14
|
+
super { presets.each { |name| storage.delete path(name) if exists?(name) } if presets.any? }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def generate_preset(name)
|
|
18
|
+
storage.magick destination_path, destination_path(name), upload do |image|
|
|
19
|
+
settings = Rails.application.config.attachs.presets[name]
|
|
20
|
+
if settings.respond_to? :call
|
|
21
|
+
settings.call image
|
|
22
|
+
else
|
|
23
|
+
image.send "resize_to_#{settings[:method] || 'fill'}", settings[:width], settings[:height]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete_preset(name)
|
|
29
|
+
storage.delete path(name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
protected
|
|
33
|
+
|
|
34
|
+
def store_path(*args)
|
|
35
|
+
::File.join('images', (args[0] ? args[0].to_s.gsub('_', '-') : 'original'))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class AttachmentContentTypeValidator < Attachs::Validators::Base
|
|
2
|
+
|
|
3
|
+
def validate_each(record, attribute, value)
|
|
4
|
+
if value.present? and not value.default?
|
|
5
|
+
unless options[:in].include? value.extname.from(1)
|
|
6
|
+
add_error record, attribute, 'errors.messages.attachment_content_type', types: options[:in].to_sentence
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class AttachmentSizeValidator < Attachs::Validators::Base
|
|
2
|
+
include ActionView::Helpers::NumberHelper
|
|
3
|
+
|
|
4
|
+
def validate_each(record, attribute, value)
|
|
5
|
+
if value.present? and not value.default?
|
|
6
|
+
if options.has_key? :in
|
|
7
|
+
unless options[:in].include? value.size
|
|
8
|
+
add_error record, attribute, 'attachment_size_in', min: number_to_human_size(options[:in].begin), max: number_to_human_size(options[:in].end)
|
|
9
|
+
end
|
|
10
|
+
else
|
|
11
|
+
if options.has_key? :less_than and value.size > options[:less_than]
|
|
12
|
+
add_error record, attribute, 'attachment_size_less_than', count: number_to_human_size(options[:less_than])
|
|
13
|
+
end
|
|
14
|
+
if options.has_key? :greater_than and value.size < options[:greater_than]
|
|
15
|
+
add_error record, attribute, 'attachment_size_greater_than', count: number_to_human_size(options[:greater_than])
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
protected
|
|
22
|
+
|
|
23
|
+
def add_error(record, attribute, type, options)
|
|
24
|
+
super(record, attribute, "errors.messages.#{type}", options)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
development:
|
|
3
|
+
bucket: development-bucket
|
|
4
|
+
access_key_id: development_access_key_id
|
|
5
|
+
secret_access_key: development_secret_access_key
|
|
6
|
+
|
|
7
|
+
test:
|
|
8
|
+
bucket: test-bucket
|
|
9
|
+
access_key_id: test_access_key_id
|
|
10
|
+
secret_access_key: test_secret_access_key
|
|
11
|
+
|
|
12
|
+
production:
|
|
13
|
+
bucket: production-bucket
|
|
14
|
+
access_key_id: production_access_key_id
|
|
15
|
+
secret_access_key: production_secret_access_key
|
|
16
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Attachs
|
|
2
|
+
module Task
|
|
3
|
+
|
|
4
|
+
def self.iterate_images
|
|
5
|
+
model = ENV['MODEL'].classify.constantize
|
|
6
|
+
presets = ENV['PRESETS'].split(',').map(&:to_sym)
|
|
7
|
+
model.find_each do |record|
|
|
8
|
+
model.attachments.each do |attr, options|
|
|
9
|
+
if options[:type] == :image
|
|
10
|
+
presets.each do |preset|
|
|
11
|
+
image = record.send(attr)
|
|
12
|
+
yield image, preset
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
namespace :uploads do
|
|
23
|
+
|
|
24
|
+
namespace :presets do
|
|
25
|
+
desc 'Refresh preset'
|
|
26
|
+
task refresh: :clean do
|
|
27
|
+
Attachs::Task.iterate_images do |image, preset|
|
|
28
|
+
puts "Generating preset #{image.url(preset)}."
|
|
29
|
+
image.generate_preset preset
|
|
30
|
+
end
|
|
31
|
+
puts "Presets refreshed successfully."
|
|
32
|
+
end
|
|
33
|
+
desc 'Clean preset'
|
|
34
|
+
task clean: :environment do
|
|
35
|
+
Attachs::Task.iterate_images do |image, preset|
|
|
36
|
+
puts "Deleting preset #{image.url(preset)}."
|
|
37
|
+
image.delete_preset preset
|
|
38
|
+
end
|
|
39
|
+
puts "Presets cleaned successfully."
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
namespace :s3 do
|
|
44
|
+
namespace :buckets do
|
|
45
|
+
desc 'Create buckets'
|
|
46
|
+
task :create do
|
|
47
|
+
config = YAML.load_file(Rails.root.join('config', 's3.yml'))
|
|
48
|
+
config.each do |env, options|
|
|
49
|
+
require 'aws-sdk'
|
|
50
|
+
AWS.config access_key_id: options['access_key_id'], secret_access_key: options['secret_access_key']
|
|
51
|
+
bucket = options['bucket']
|
|
52
|
+
begin
|
|
53
|
+
AWS::S3.new.buckets.create bucket
|
|
54
|
+
rescue AWS::S3::Errors::InvalidAccessKeyId
|
|
55
|
+
puts "Invalid credentials in #{env} environment."
|
|
56
|
+
next
|
|
57
|
+
rescue AWS::S3::Errors::BucketAlreadyExists
|
|
58
|
+
puts "Bucket #{bucket} already exists."
|
|
59
|
+
next
|
|
60
|
+
rescue AWS::S3::Errors::BucketAlreadyOwnedByYou
|
|
61
|
+
puts "You already own bucket #{bucket}."
|
|
62
|
+
next
|
|
63
|
+
end
|
|
64
|
+
puts "Bucket #{bucket} created successfully."
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|