attachie 1.0.0 → 1.1.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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +27 -0
- data/CHANGELOG.md +18 -0
- data/README.md +1 -0
- data/lib/attachie.rb +4 -0
- data/lib/attachie/fake_driver.rb +42 -16
- data/lib/attachie/file_driver.rb +8 -0
- data/lib/attachie/s3_driver.rb +4 -0
- data/lib/attachie/version.rb +1 -1
- data/spec/attachie/fake_driver_spec.rb +23 -0
- data/spec/attachie/file_driver_spec.rb +16 -0
- data/spec/attachie/s3_driver_spec.rb +18 -1
- data/spec/attachie_spec.rb +17 -1
- metadata +5 -5
- data/.travis.yml +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e46dfdb8f2b5d9b94594ca38b5d72b3164a7659ce165f6e5f328ee72275ee5a
|
4
|
+
data.tar.gz: d88df51754ce79dc3f716b0e5ccbd7fc4853bde2b92dbf75a85bc65dbb5b83ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f92ec31c86801736cdc8cd6c2cd7265ed6054d48e796d3961c00490b1e8a79cdfaeefddc4746c2d3d714e0659f95ab0e1873331b3d6835acf0eaf47ed9dca4f
|
7
|
+
data.tar.gz: 2495f460854161a8e241c67babb8bd7eb72bf63bbaabd04b867a195e106207e6fbd5701c687acf8909bac241adecc25e32e571660d904ccebc32b3edd287d327
|
@@ -0,0 +1,27 @@
|
|
1
|
+
name: test
|
2
|
+
on: [push, pull_request]
|
3
|
+
jobs:
|
4
|
+
build:
|
5
|
+
runs-on: ubuntu-latest
|
6
|
+
strategy:
|
7
|
+
matrix:
|
8
|
+
ruby: ['2.5', '2.6', '2.7']
|
9
|
+
services:
|
10
|
+
fake-s3:
|
11
|
+
image: lphoward/fake-s3
|
12
|
+
ports:
|
13
|
+
- 4569:4569
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v1
|
16
|
+
- uses: actions/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: ${{ matrix.ruby }}
|
19
|
+
- uses: actions/cache@v1
|
20
|
+
id: cache
|
21
|
+
with:
|
22
|
+
path: vendor/bundler
|
23
|
+
key: ${{ hashFiles('Gemfile.lock') }}-${{ matrix.ruby }}
|
24
|
+
- run: |
|
25
|
+
gem install bundler
|
26
|
+
bundle install --path=vendor/bundler
|
27
|
+
bundle exec rspec
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# CHANGELOG
|
2
|
+
|
3
|
+
## 1.1.2
|
4
|
+
### Fixed
|
5
|
+
* Make `FakeDriver` thread-safe
|
6
|
+
* Sort objects in `FakeDriver#list` by key
|
7
|
+
|
8
|
+
## 1.1.1
|
9
|
+
### Fixed
|
10
|
+
* Use `mkdir_p` in `FileDriver#download`
|
11
|
+
|
12
|
+
## 1.1.0
|
13
|
+
### Added
|
14
|
+
* Added a download method to download files to a specific path
|
15
|
+
|
16
|
+
## 1.0.1
|
17
|
+
### Fixed
|
18
|
+
* dup list result in FakeDriver before iterating
|
data/README.md
CHANGED
data/lib/attachie.rb
CHANGED
data/lib/attachie/fake_driver.rb
CHANGED
@@ -32,22 +32,28 @@ module Attachie
|
|
32
32
|
end
|
33
33
|
|
34
34
|
class FakeDriver
|
35
|
+
include MonitorMixin
|
36
|
+
|
35
37
|
class ItemNotFound < StandardError; end
|
36
38
|
|
37
39
|
def list(bucket, prefix: nil)
|
38
40
|
return enum_for(:list, bucket, prefix: prefix) unless block_given?
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
+
synchronize do
|
43
|
+
objects(bucket).sort { |a, b| a[0] <=> b[0] }.each do |key, _|
|
44
|
+
yield key if prefix.nil? || key.start_with?(prefix)
|
45
|
+
end
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
45
49
|
def info(name, bucket)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
synchronize do
|
51
|
+
{
|
52
|
+
last_modified: nil,
|
53
|
+
content_length: objects(bucket)[name].size,
|
54
|
+
content_type: MIME::Types.of(name).first&.to_s
|
55
|
+
}
|
56
|
+
end
|
51
57
|
end
|
52
58
|
|
53
59
|
def presigned_post(name, bucket, options = {})
|
@@ -55,40 +61,60 @@ module Attachie
|
|
55
61
|
end
|
56
62
|
|
57
63
|
def store(name, data_or_io, bucket, options = {})
|
58
|
-
|
64
|
+
synchronize do
|
65
|
+
objects(bucket)[name] = data_or_io.respond_to?(:read) ? data_or_io.read : data_or_io
|
66
|
+
end
|
59
67
|
end
|
60
68
|
|
61
69
|
def store_multipart(name, bucket, options = {}, &block)
|
62
|
-
|
70
|
+
synchronize do
|
71
|
+
objects(bucket)[name] = FakeMultipartUpload.new(name, bucket, options, &block).data
|
72
|
+
end
|
63
73
|
end
|
64
74
|
|
65
75
|
def exists?(name, bucket)
|
66
|
-
|
76
|
+
synchronize do
|
77
|
+
objects(bucket).key?(name)
|
78
|
+
end
|
67
79
|
end
|
68
80
|
|
69
81
|
def delete(name, bucket)
|
70
|
-
|
82
|
+
synchronize do
|
83
|
+
objects(bucket).delete(name)
|
84
|
+
end
|
71
85
|
end
|
72
86
|
|
73
87
|
def value(name, bucket)
|
74
|
-
|
88
|
+
synchronize do
|
89
|
+
raise(ItemNotFound) unless objects(bucket).key?(name)
|
75
90
|
|
76
|
-
|
91
|
+
objects(bucket)[name]
|
92
|
+
end
|
77
93
|
end
|
78
94
|
|
95
|
+
def download(name, bucket, path)
|
96
|
+
content = value(name, bucket)
|
97
|
+
|
98
|
+
open(path, "wb") { |stream| stream.write(content) }
|
99
|
+
end
|
100
|
+
|
79
101
|
def temp_url(name, bucket, options = {})
|
80
102
|
"https://example.com/#{bucket}/#{name}?signature=signature&expires=expires"
|
81
103
|
end
|
82
104
|
|
83
105
|
def flush
|
84
|
-
|
106
|
+
synchronize do
|
107
|
+
@objects = {}
|
108
|
+
end
|
85
109
|
end
|
86
110
|
|
87
111
|
private
|
88
112
|
|
89
113
|
def objects(bucket)
|
90
|
-
|
91
|
-
|
114
|
+
synchronize do
|
115
|
+
@objects ||= {}
|
116
|
+
@objects[bucket] ||= {}
|
117
|
+
end
|
92
118
|
end
|
93
119
|
end
|
94
120
|
end
|
data/lib/attachie/file_driver.rb
CHANGED
@@ -89,6 +89,14 @@ module Attachie
|
|
89
89
|
File.binread path_for(name, bucket)
|
90
90
|
end
|
91
91
|
|
92
|
+
def download(name, bucket, dest_path)
|
93
|
+
path = path_for(name, bucket)
|
94
|
+
|
95
|
+
FileUtils.mkdir_p File.dirname(path)
|
96
|
+
|
97
|
+
FileUtils.cp(path, dest_path)
|
98
|
+
end
|
99
|
+
|
92
100
|
def delete(name, bucket)
|
93
101
|
path = path_for(name, bucket)
|
94
102
|
|
data/lib/attachie/s3_driver.rb
CHANGED
@@ -114,6 +114,10 @@ module Attachie
|
|
114
114
|
s3_resource.bucket(bucket).object(name).get.body.read.force_encoding(Encoding::BINARY)
|
115
115
|
end
|
116
116
|
|
117
|
+
def download(name, bucket, path)
|
118
|
+
s3_resource.bucket(bucket).object(name).download_file(path)
|
119
|
+
end
|
120
|
+
|
117
121
|
def delete(name, bucket)
|
118
122
|
s3_resource.bucket(bucket).object(name).delete
|
119
123
|
end
|
data/lib/attachie/version.rb
CHANGED
@@ -21,6 +21,14 @@ RSpec.describe Attachie::FakeDriver do
|
|
21
21
|
|
22
22
|
expect(driver.list("bucket1", prefix: "object").to_a).to eq(["object1", "object2"])
|
23
23
|
end
|
24
|
+
|
25
|
+
it "sorts the objects by key" do
|
26
|
+
driver.store("object2", "blob", "bucket")
|
27
|
+
driver.store("object1", "blob", "bucket")
|
28
|
+
driver.store("object3", "blob", "bucket")
|
29
|
+
|
30
|
+
expect(driver.list("bucket").to_a).to eq(["object1", "object2", "object3"])
|
31
|
+
end
|
24
32
|
end
|
25
33
|
|
26
34
|
describe "#store" do
|
@@ -32,6 +40,21 @@ RSpec.describe Attachie::FakeDriver do
|
|
32
40
|
end
|
33
41
|
end
|
34
42
|
|
43
|
+
describe "#download" do
|
44
|
+
it "downloads the blob to the specified path" do
|
45
|
+
tempfile = Tempfile.new
|
46
|
+
|
47
|
+
begin
|
48
|
+
driver.store("name", "blob", "bucket")
|
49
|
+
driver.download("name", "bucket", tempfile.path)
|
50
|
+
|
51
|
+
expect(tempfile.read).to eq("blob")
|
52
|
+
ensure
|
53
|
+
tempfile.close(true)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
35
58
|
describe "#store_multipart" do
|
36
59
|
it "stores a blob via multipart upload" do
|
37
60
|
driver.store_multipart("name", "bucket") do |upload|
|
@@ -23,6 +23,22 @@ RSpec.describe Attachie::FileDriver do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
describe "#download" do
|
27
|
+
it "downloads the blob to the specified path" do
|
28
|
+
tempfile = Tempfile.new
|
29
|
+
|
30
|
+
begin
|
31
|
+
driver.store("name", "blob", "bucket")
|
32
|
+
driver.download("name", "bucket", tempfile.path)
|
33
|
+
|
34
|
+
expect(tempfile.read).to eq("blob")
|
35
|
+
ensure
|
36
|
+
driver.delete("name", "bucket")
|
37
|
+
tempfile.close(true)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
26
42
|
describe" #store_multipart" do
|
27
43
|
it "stores a blob via multipart upload" do
|
28
44
|
begin
|
@@ -7,6 +7,7 @@ RSpec.describe Attachie::S3Driver do
|
|
7
7
|
access_key_id: "access_key_id",
|
8
8
|
secret_access_key: "secret_access_key",
|
9
9
|
endpoint: "http://localhost:4569",
|
10
|
+
force_path_style: true,
|
10
11
|
region: "us-east-1"
|
11
12
|
))
|
12
13
|
end
|
@@ -40,6 +41,22 @@ RSpec.describe Attachie::S3Driver do
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
44
|
+
describe "#download" do
|
45
|
+
it "downloads the blob to the specified path" do
|
46
|
+
tempfile = Tempfile.new
|
47
|
+
|
48
|
+
begin
|
49
|
+
driver.store("name", "blob", "bucket")
|
50
|
+
driver.download("name", "bucket", tempfile.path)
|
51
|
+
|
52
|
+
expect(tempfile.read).to eq("blob")
|
53
|
+
ensure
|
54
|
+
driver.delete("name", "bucket")
|
55
|
+
tempfile.close(true)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
43
60
|
describe "#store_multipart" do
|
44
61
|
it "stores a blob via multipart upload" do
|
45
62
|
begin
|
@@ -82,7 +99,7 @@ RSpec.describe Attachie::S3Driver do
|
|
82
99
|
fields: hash_including("key" => "path/to/object"),
|
83
100
|
headers: {},
|
84
101
|
method: "post",
|
85
|
-
url: "http://
|
102
|
+
url: "http://localhost:4569/bucket"
|
86
103
|
)
|
87
104
|
end
|
88
105
|
|
data/spec/attachie_spec.rb
CHANGED
@@ -37,7 +37,7 @@ RSpec.describe TestModel do
|
|
37
37
|
|
38
38
|
it "correctly uses the driver" do
|
39
39
|
test_model = TestModel.new(filename: "blob.txt")
|
40
|
-
test_model.file(:large).store
|
40
|
+
test_model.file(:large).store("blob")
|
41
41
|
|
42
42
|
expect(test_model.file(:large).value).to eq("blob")
|
43
43
|
end
|
@@ -54,6 +54,22 @@ RSpec.describe TestModel do
|
|
54
54
|
expect(test_model.updated_at).to be_nil
|
55
55
|
end
|
56
56
|
|
57
|
+
describe "#download" do
|
58
|
+
it "downloads the file to the specified path" do
|
59
|
+
tempfile = Tempfile.new
|
60
|
+
|
61
|
+
begin
|
62
|
+
test_model = TestModel.new(filename: "blob.txt")
|
63
|
+
test_model.file(:large).store("blob")
|
64
|
+
test_model.file(:large).download(tempfile.path)
|
65
|
+
|
66
|
+
expect(tempfile.read).to eq("blob")
|
67
|
+
ensure
|
68
|
+
tempfile.close(true)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
57
73
|
describe "#info" do
|
58
74
|
it "returns info about the attachment" do
|
59
75
|
test_model = TestModel.new(filename: "blob.txt")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attachie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Vetter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-s3
|
@@ -129,8 +129,9 @@ executables: []
|
|
129
129
|
extensions: []
|
130
130
|
extra_rdoc_files: []
|
131
131
|
files:
|
132
|
+
- ".github/workflows/test.yml"
|
132
133
|
- ".gitignore"
|
133
|
-
-
|
134
|
+
- CHANGELOG.md
|
134
135
|
- Gemfile
|
135
136
|
- LICENSE.txt
|
136
137
|
- README.md
|
@@ -168,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
169
|
- !ruby/object:Gem::Version
|
169
170
|
version: '0'
|
170
171
|
requirements: []
|
171
|
-
|
172
|
-
rubygems_version: 2.7.3
|
172
|
+
rubygems_version: 3.0.3
|
173
173
|
signing_key:
|
174
174
|
specification_version: 4
|
175
175
|
summary: Declarative and flexible attachments
|