attachie 1.0.0 → 1.1.2

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
  SHA256:
3
- metadata.gz: 2a6322baba1a72a9869ed2cb50a2f58a890fed49a5b1fbfb57c6e358dfcce4b2
4
- data.tar.gz: 7e95e247cf920af92fd51d32b21bf2d0a82a59af022cacc1343a2bb71612d5b7
3
+ metadata.gz: 1e46dfdb8f2b5d9b94594ca38b5d72b3164a7659ce165f6e5f328ee72275ee5a
4
+ data.tar.gz: d88df51754ce79dc3f716b0e5ccbd7fc4853bde2b92dbf75a85bc65dbb5b83ae
5
5
  SHA512:
6
- metadata.gz: ef797be58fb2573636f3cfc9de41fc1484cc8f6357488e7d1699ed5288a79b3c2ca0a51795ab825ce8941f05c69986dd84dd05b1861493ef74c8cc1afb5a1cd6
7
- data.tar.gz: e986a15bc1a7781d4d60f620949582ae455c0dc6374c818930c7990a430bc9cbc4740d14cb2b0a60865769c084b7bc5bbce9c55f5aa1cabb0a10790704767745
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
@@ -70,6 +70,7 @@ user.avatar(:icon).delete
70
70
  user.avatar(:icon).exists?
71
71
  user.avatar(:icon).value
72
72
  user.avatar(:icon).temp_url(expires_in: 2.days) # Must be supported by the driver
73
+ user.avator(:icon).download("/path/to/destination")
73
74
  ```
74
75
 
75
76
  ## Drivers
data/lib/attachie.rb CHANGED
@@ -59,6 +59,10 @@ module Attachie
59
59
  option(:driver).store(path, data_or_io, container, opts)
60
60
  end
61
61
 
62
+ def download(dest_path)
63
+ option(:driver).download(path, container, dest_path)
64
+ end
65
+
62
66
  def info
63
67
  option(:driver).info(path, container)
64
68
  end
@@ -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
- objects(bucket).each do |key, _|
41
- yield key if prefix.nil? || key.start_with?(prefix)
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
- last_modified: nil,
48
- content_length: objects(bucket)[name].size,
49
- content_type: MIME::Types.of(name).first&.to_s
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
- objects(bucket)[name] = data_or_io.respond_to?(:read) ? data_or_io.read : data_or_io
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
- objects(bucket)[name] = FakeMultipartUpload.new(name, bucket, options, &block).data
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
- objects(bucket).key?(name)
76
+ synchronize do
77
+ objects(bucket).key?(name)
78
+ end
67
79
  end
68
80
 
69
81
  def delete(name, bucket)
70
- objects(bucket).delete(name)
82
+ synchronize do
83
+ objects(bucket).delete(name)
84
+ end
71
85
  end
72
86
 
73
87
  def value(name, bucket)
74
- raise(ItemNotFound) unless objects(bucket).key?(name)
88
+ synchronize do
89
+ raise(ItemNotFound) unless objects(bucket).key?(name)
75
90
 
76
- objects(bucket)[name]
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
- @objects = {}
106
+ synchronize do
107
+ @objects = {}
108
+ end
85
109
  end
86
110
 
87
111
  private
88
112
 
89
113
  def objects(bucket)
90
- @objects ||= {}
91
- @objects[bucket] ||= {}
114
+ synchronize do
115
+ @objects ||= {}
116
+ @objects[bucket] ||= {}
117
+ end
92
118
  end
93
119
  end
94
120
  end
@@ -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
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Attachie
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.2"
3
3
  end
@@ -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://bucket.localhost:4569"
102
+ url: "http://localhost:4569/bucket"
86
103
  )
87
104
  end
88
105
 
@@ -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 "blob"
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.0.0
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: 2019-11-13 00:00:00.000000000 Z
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
- - ".travis.yml"
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
- rubyforge_project:
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
data/.travis.yml DELETED
@@ -1,13 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.3.3
5
- addons:
6
- hosts:
7
- - bucket.localhost
8
- before_install:
9
- - docker-compose up -d
10
- - sleep 10
11
- install:
12
- - travis_retry bundle install
13
- script: rspec