storage 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a4d8b072280f92e4e745df2bb3180fd1e8640f75
4
- data.tar.gz: 3f88505cdc2bbdcf4af9f727caab88014a226d7a
3
+ metadata.gz: 184a2c065d267a1a8c69ea2b28cb10029ed87386
4
+ data.tar.gz: 92487bed7cda01963ec791f9a97be0c7aabf0cf4
5
5
  SHA512:
6
- metadata.gz: 8045b230b182476fb49ec5491a3a03a36454bb8f268a735b4cd935bd562b0de93b27239d5b62e324bc7b591108282a4a87ce51068f1e01078ea7d98af8eadc85
7
- data.tar.gz: a91613e6bcc193464ca5b1f19ec8a820ee08f61419480e9a3cfd99b59081fb51234235863c0e65168b2d14bdc065733c432356eec34d98b3b38a6776c4a494e8
6
+ metadata.gz: 690d4ab3a737bd1d4d4cdbdefc6837604af4f7776ce9fb76cbd8243e3cec6d3c88fa4b81e621337af72d6fb930eab0cbc783c1385af58f4149e18c2e4935c461
7
+ data.tar.gz: b0b17efdf1edfa68fb8ed89daf2ddfdcf0d2478d9194c8a5ffe654f9569e95a990d676577fdaa8e265a5f753f801c5f773f97a8a57c6b4b2f5eb4da51c264ea5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- storage (0.3.0)
4
+ storage (0.3.1)
5
5
  fog
6
6
  mime-types
7
7
 
@@ -130,7 +130,9 @@ GEM
130
130
  inflecto (0.0.2)
131
131
  ipaddress (0.8.3)
132
132
  method_source (0.8.2)
133
- mime-types (2.99.1)
133
+ mime-types (3.0)
134
+ mime-types-data (~> 3.2015)
135
+ mime-types-data (3.2016.0221)
134
136
  mini_portile2 (2.0.0)
135
137
  multi_json (1.11.2)
136
138
  nokogiri (1.6.7.2)
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Storage
2
+
3
+ This gem provides a simple API for multiple storage backends. Supported storages: Amazon S3 and FileSystem (it uses Fog under the hood).
4
+
5
+ The storage provides only 3 methods, one for each operation: `Storage::get`, `Storage::store` and `Storage::remove`.
6
+
7
+ ## Installation
8
+
9
+ gem install storage
10
+
11
+ You can get source code at http://github.com/fnando/storage
12
+
13
+ ## Usage
14
+
15
+ ```ruby
16
+ require "storage"
17
+ ```
18
+
19
+ You basically use the same method no matter what storage strategy you're using.
20
+
21
+ ### Amazon S3
22
+
23
+ ```ruby
24
+ Storage.setup do |config|
25
+ config.strategy = :s3
26
+ config.access_key = "abcdef"
27
+ config.secret_key = "123456"
28
+ end
29
+
30
+ # Store a local file on S3.
31
+ # You can easily switch from S3 to FileSystem;
32
+ # keys that are not used by one strategy is simply ignored.
33
+ Storage.store "some/file.rb", name: "file.rb", bucket: "sample"
34
+ Storage.store File.open("some/file.rb"), name: "file.rb", bucket: "sample", public: true
35
+
36
+ # Retrieve the public url for that file
37
+ Storage.get "file.rb"
38
+ #=> http://s3.amazon.com/sample-files/file.rb
39
+
40
+ # Remove a file.
41
+ Storage.remove "file.rb"
42
+ ```
43
+
44
+ ### FileSystem
45
+
46
+ ```ruby
47
+ Storage.setup do |config|
48
+ config.strategy = :file
49
+ config.path = "some/directory"
50
+ end
51
+
52
+ # Store a file.
53
+ Storage.store "some/file.rb", name: "file.rb"
54
+ Storage.store File.open("some/file.rb"), name: "file.rb"
55
+
56
+ # Retrieve that file's path.
57
+ Storage.get "file.rb"
58
+ #=> some/directory/file.rb
59
+
60
+ # Remove a file.
61
+ Storage.remove "file.rb"
62
+ ```
63
+
64
+ ## License
65
+
66
+ (The MIT License)
67
+
68
+ Copyright © 2010:
69
+
70
+ * Nando Vieira (http://nandovieira.com)
71
+
72
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
73
+
74
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
75
+
76
+ THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -6,12 +6,12 @@ module Storage
6
6
  MissingBucket = Class.new(StandardError)
7
7
 
8
8
  def connection
9
- @connection ||= Fog::Storage.new({
10
- :provider => 'AWS',
11
- :aws_access_key_id => Storage::Config.access_key,
12
- :aws_secret_access_key => Storage::Config.secret_key,
13
- :region => Storage::Config.region
14
- })
9
+ @connection ||= Fog::Storage.new(
10
+ provider: "AWS",
11
+ aws_access_key_id: Storage::Config.access_key,
12
+ aws_secret_access_key: Storage::Config.secret_key,
13
+ region: Storage::Config.region
14
+ )
15
15
  end
16
16
 
17
17
  def prepare!
@@ -33,7 +33,7 @@ module Storage
33
33
 
34
34
  def store(file, options = {})
35
35
  object = find_object(file, options) rescue nil
36
- raise FileAlreadyExistsError if object
36
+ fail FileAlreadyExistsError if object
37
37
 
38
38
  bucket = find_bucket_or_create(options.fetch(:bucket))
39
39
  file = File.open(file, "rb") unless file.respond_to?(:read) && !file.kind_of?(Pathname)
@@ -51,28 +51,28 @@ module Storage
51
51
  end
52
52
 
53
53
  def find_bucket!(name)
54
- find_bucket(name) || raise(MissingBucket)
54
+ find_bucket(name) || fail(MissingBucket)
55
55
  end
56
56
 
57
57
  def create_bucket(name)
58
58
  connection.directories.create(
59
- :key => name,
60
- :public => false
59
+ key: name,
60
+ public: false
61
61
  )
62
62
  end
63
63
 
64
64
  def create_object(bucket, file, options)
65
- bucket.files.create({
66
- :key => options.fetch(:name),
67
- :body => file,
68
- :public => (options[:public] || options[:access] != :public_read)
69
- })
65
+ bucket.files.create(
66
+ key: options.fetch(:name),
67
+ body: file,
68
+ public: (options[:public] || options[:access] == :public_read)
69
+ )
70
70
  end
71
71
 
72
72
  def find_object(file, options = {})
73
73
  path = options.fetch(:name, file)
74
74
  bucket = find_bucket!(options.fetch(:bucket))
75
- bucket.files.get(path) || raise(MissingFileError)
75
+ bucket.files.get(path) || fail(MissingFileError)
76
76
  rescue MissingBucket
77
77
  raise MissingFileError
78
78
  end
@@ -2,7 +2,7 @@ module Storage
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 3
5
- PATCH = 0
5
+ PATCH = 1
6
6
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
7
  end
8
8
  end
@@ -22,14 +22,14 @@ describe Storage::Strategies::S3 do
22
22
  end
23
23
 
24
24
  context "general" do
25
- before do
26
- @adapter = Storage::Strategies::S3
27
- @source = RESOURCES.join("file.txt")
28
- @destiny = TMP.join("lorem.txt")
29
- @connection = double("connection")
30
- @bucket = double("bucket")
25
+ let(:adapter) { Storage::Strategies::S3 }
26
+ let(:source) { RESOURCES.join("file.txt") }
27
+ let(:destiny) { TMP.join("lorem.txt") }
28
+ let(:connection) { double("connection") }
29
+ let(:bucket) { double("bucket") }
31
30
 
32
- allow(@adapter).to receive(:connection).and_return(@connection)
31
+ before do
32
+ allow(adapter).to receive(:connection).and_return(connection)
33
33
 
34
34
  Storage.setup do |c|
35
35
  c.strategy = :s3
@@ -40,95 +40,141 @@ describe Storage::Strategies::S3 do
40
40
  end
41
41
 
42
42
  it "should save a file using file handler" do
43
- handler = File.open(@source)
43
+ handler = File.open(source)
44
44
 
45
- expect(@connection).to receive_message_chain('directories.get').with('files').and_return(@bucket)
46
- expect(@adapter).to receive_message_chain('find_object').and_return(nil)
47
- expect(@bucket).to receive_message_chain('files.create').with(:key => 'lorem.txt', :body => handler, :public => true)
45
+ setup_expectations
48
46
 
49
- Storage.store(handler, :name => "lorem.txt", :bucket => "files")
47
+ Storage.store(handler, name: "lorem.txt", bucket: "files")
50
48
  end
51
49
 
52
50
  it "should save a file using a path" do
53
- expect(@connection).to receive_message_chain('directories.get').with('files').and_return(@bucket)
54
- expect(@adapter).to receive_message_chain('find_object').and_return(nil)
55
- expect(@bucket).to receive_message_chain('files.create').with(:key => 'lorem.txt', :body => kind_of(File), :public => true)
51
+ setup_expectations
56
52
 
57
- Storage.store(@source, :name => "lorem.txt", :bucket => "files")
53
+ Storage.store(source, name: "lorem.txt", bucket: "files")
58
54
  end
59
55
 
60
56
  it "should remove an existing file" do
61
57
  object = double("object")
62
- expect(@connection).to receive_message_chain('directories.get').with('files').and_return(@bucket)
63
- expect(@bucket).to receive_message_chain('files.get').with('lorem.txt').and_return(object)
58
+
59
+ setup_bucket(bucket)
60
+ setup_object(object)
64
61
  expect(object).to receive(:destroy).and_return(true)
65
62
 
66
- expect(Storage.remove("lorem.txt", :bucket => "files")).to be_truthy
63
+ expect(Storage.remove("lorem.txt", bucket: "files")).to be_truthy
67
64
  end
68
65
 
69
- it "should raise when trying to removing an unexesting file" do
70
- expect(@connection).to receive_message_chain('directories.get').with('files').and_return(@bucket)
71
- expect(@bucket).to receive_message_chain('files.get').with('lorem.txt').and_return(nil)
66
+ it "should raise when trying to removing an nonexisting file" do
67
+ setup_bucket(bucket)
68
+ setup_get(nil)
72
69
 
73
70
  expect {
74
- Storage.remove("lorem.txt", :bucket => "files")
71
+ Storage.remove("lorem.txt", bucket: "files")
75
72
  }.to raise_error(Storage::MissingFileError)
76
73
  end
77
74
 
78
75
  it "should retrieve an existing file (public url)" do
79
- object = double("object", public_url: 'PUBLIC_URL')
80
- expect(@connection).to receive_message_chain('directories.get').with('files').and_return(@bucket)
81
- expect(@bucket).to receive_message_chain('files.get').with('lorem.txt').and_return(object)
76
+ object = double("object", public_url: "PUBLIC_URL")
77
+
78
+ setup_bucket(bucket)
79
+ setup_object(object)
82
80
 
83
- expect(Storage.get("lorem.txt", :bucket => "files")).to eq('PUBLIC_URL')
81
+ expect(Storage.get("lorem.txt", bucket: "files")).to eq("PUBLIC_URL")
84
82
  end
85
83
 
86
84
  it "should retrieve an existing file (private url)" do
87
85
  object = double("object", public_url: nil)
88
86
 
89
- expect(object).to receive_message_chain('url').with(Time.now.to_i + 3600).and_return('PRIVATE_URL')
90
- expect(@connection).to receive_message_chain('directories.get').with('files').and_return(@bucket)
91
- expect(@bucket).to receive_message_chain('files.get').with('lorem.txt').and_return(object)
87
+ expect(object).to receive_message_chain("url").with(Time.now.to_i + 3600).and_return("PRIVATE_URL")
88
+ setup_bucket(bucket)
89
+ setup_object(object)
92
90
 
93
- expect(Storage.get("lorem.txt", :bucket => "files")).to eq('PRIVATE_URL')
91
+ expect(Storage.get("lorem.txt", :bucket => "files")).to eq("PRIVATE_URL")
94
92
  end
95
93
 
96
94
  it "should raise when trying to retrieve an missing file" do
97
- expect(@connection).to receive_message_chain('directories.get').with('files').and_return(@bucket)
98
- expect(@bucket).to receive_message_chain('files.get').with('lorem.txt').and_return(nil)
95
+ setup_bucket(bucket)
96
+ setup_get(nil)
99
97
 
100
98
  expect {
101
- Storage.get("lorem.txt", :bucket => "files")
99
+ Storage.get("lorem.txt", bucket: "files")
102
100
  }.to raise_error(Storage::MissingFileError)
103
101
  end
104
102
 
105
103
  it "should raise when trying to retrieve an missing bucket" do
106
- expect(@connection).to receive_message_chain('directories.get').with('files').and_return(nil)
104
+ setup_bucket(nil)
107
105
 
108
106
  expect {
109
- Storage.get("lorem.txt", :bucket => "files")
107
+ Storage.get("lorem.txt", bucket: "files")
110
108
  }.to raise_error(Storage::MissingFileError)
111
109
  end
112
110
 
113
111
  it "should create a bucket and trying to store a file on a missing bucket" do
114
- expect(@adapter).to receive_message_chain('find_object').and_return(nil)
115
- allow(@connection).to receive_message_chain('directories.get').and_return(nil)
116
- expect(@connection).to receive_message_chain('directories.create').with(key: 'files', public: false).and_return(@bucket)
112
+ setup_object
113
+ setup_bucket(nil)
117
114
 
118
- @bucket.as_null_object
115
+ expect(connection).to receive_message_chain("directories.create").with(key: "files", public: false).and_return(bucket)
119
116
 
120
- Storage.store(@source, :name => 'lorem.txt', :bucket => "files")
117
+ bucket.as_null_object
118
+
119
+ Storage.store(source, name: "lorem.txt", bucket: "files")
121
120
  end
122
121
 
123
122
  it "should raise when saving a file that already exists" do
124
123
  object = double("object")
125
124
 
126
- expect(@connection).to receive_message_chain('directories.get').with('files').and_return(@bucket)
127
- expect(@bucket).to receive_message_chain('files.get').with('lorem.txt').and_return(object)
125
+ setup_bucket(bucket)
126
+ setup_get(object)
128
127
 
129
128
  expect {
130
- Storage.store(@source, :name => 'lorem.txt', :bucket => 'files')
129
+ Storage.store(source, name: "lorem.txt", bucket: "files")
131
130
  }.to raise_error(Storage::FileAlreadyExistsError)
132
131
  end
132
+
133
+ it "should set file permission to public" do
134
+ setup_expectations public_access: true
135
+ Storage.store(source, name: "lorem.txt", bucket: "files", public: true)
136
+ end
137
+
138
+ it "should set file permission to private (default)" do
139
+ setup_expectations public_access: false
140
+ Storage.store(source, name: "lorem.txt", bucket: "files")
141
+ end
142
+
143
+ it "should set file permission to private" do
144
+ setup_expectations public_access: false
145
+ Storage.store(source, name: "lorem.txt", bucket: "files", public: false)
146
+ end
147
+
148
+ it "should set file permission to private (access option)" do
149
+ setup_expectations public_access: false
150
+ Storage.store(source, name: "lorem.txt", bucket: "files", access: :private)
151
+ end
152
+
153
+ it "should set file permission to public (access option)" do
154
+ setup_expectations public_access: true
155
+ Storage.store(source, name: "lorem.txt", bucket: "files", access: :public_read)
156
+ end
157
+
158
+ def setup_bucket(bucket)
159
+ allow(connection).to receive_message_chain("directories.get").with("files").and_return(bucket)
160
+ end
161
+
162
+ def setup_object(object = nil)
163
+ expect(adapter).to receive_message_chain("find_object").and_return(object)
164
+ end
165
+
166
+ def setup_create(public_access)
167
+ expect(bucket).to receive_message_chain("files.create").with(key: "lorem.txt", body: kind_of(File), public: public_access)
168
+ end
169
+
170
+ def setup_get(object)
171
+ expect(bucket).to receive_message_chain("files.get").with("lorem.txt").and_return(object)
172
+ end
173
+
174
+ def setup_expectations(the_bucket: bucket, object: nil, public_access: false)
175
+ setup_bucket(the_bucket)
176
+ setup_object(object)
177
+ setup_create(public_access)
178
+ end
133
179
  end
134
180
  end
data/storage.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
 
13
13
  s.files = `git ls-files`.split("\n")
14
14
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map {|f| File.basename(f) }
16
16
  s.require_paths = ["lib"]
17
17
 
18
18
  s.add_dependency "fog"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: storage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-02 00:00:00.000000000 Z
11
+ date: 2016-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fog
@@ -78,7 +78,7 @@ files:
78
78
  - ".rspec"
79
79
  - Gemfile
80
80
  - Gemfile.lock
81
- - README.rdoc
81
+ - README.md
82
82
  - Rakefile
83
83
  - lib/storage.rb
84
84
  - lib/storage/config.rb
data/README.rdoc DELETED
@@ -1,71 +0,0 @@
1
- = Storage
2
-
3
- This gem provides a simple API for multiple storage backends. Supported storages: Amazon S3 and FileSystem.
4
-
5
- The storage provides only 3 methods, one for each operation: <tt>Storage::get</tt>, <tt>Storage::store</tt> and <tt>Storage::remove</tt>.
6
-
7
- == Installation
8
-
9
- sudo gem install storage
10
-
11
- You can get source code at http://github.com/fnando/storage
12
-
13
- == Usage
14
-
15
- require "rubygems"
16
- require "storage"
17
-
18
- You basically use the same method no matter what storage strategy you're using.
19
-
20
- === Amazon S3
21
-
22
- Storage.setup do |config|
23
- config.strategy = :s3
24
- config.access_key = "abcdef"
25
- config.secret_key = "123456"
26
- end
27
-
28
- # Store a local file on S3.
29
- # You can easily switch from S3 to FileSystem; keys that are not used by one strategy is
30
- # simply ignored.
31
- Storage.store "some/file.rb", :name => "file.rb", :bucket => "sample"
32
- Storage.store File.open("some/file.rb"), :name => "file.rb", :bucket => "sample"
33
-
34
- # Retrieve the public url for that file
35
- Storage.get "file.rb"
36
- #=> http://s3.amazon.com/sample-files/file.rb
37
-
38
- # Remove a file.
39
- Storage.remove "file.rb"
40
-
41
- === FileSystem
42
-
43
- Storage.setup do |config|
44
- config.strategy = :file
45
- config.path = "some/directory"
46
- end
47
-
48
- # Store a file.
49
- Storage.store "some/file.rb", :name => "file.rb"
50
- Storage.store File.open("some/file.rb"), :name => "file.rb"
51
-
52
- # Retrieve that file's path.
53
- Storage.get "file.rb"
54
- #=> some/directory/file.rb
55
-
56
- # Remove a file.
57
- Storage.remove "file.rb"
58
-
59
- == License
60
-
61
- (The MIT License)
62
-
63
- Copyright © 2010:
64
-
65
- * Nando Vieira (http://simplesideias.com.br)
66
-
67
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
68
-
69
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
70
-
71
- THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.