shrine-google_cloud_storage 1.0.1 → 3.1.0

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
- SHA1:
3
- metadata.gz: d1076839610e614727ac6be9742ee1ec630112f7
4
- data.tar.gz: 638f6ad6360e4f65ef6db03ca5a0fbd8fa5e6c75
2
+ SHA256:
3
+ metadata.gz: 4e2812d047499cf034bc9683bef6c308ba85483e40e07f2745d8603b6d5f820b
4
+ data.tar.gz: 88260f377b2ea8f7268610467f6f4be5bfb9e03995f992abc97f5dc888ae62b1
5
5
  SHA512:
6
- metadata.gz: '01968d677153ad556ea301f30149813fee671e094ce1c2744d3fbe9ba59b8f0a85f032d7ce12ef9469c8be8809b36a96ffbb80c51b93dbb7dfe5abf7ea8ca0b2'
7
- data.tar.gz: '060239c68bea2b0bba944991ec369bd73b32c6c8c87650ba26dc9d31168092a27ace43aa01af2f7a21f445ebecae406572ed859f40d212500c8f9d0917eb8268'
6
+ metadata.gz: e0dbe54c3cb323ea666e97701690367346f71616c821e3eb5b2e6dfc128258e1127f13b026504c4d88dfbdf4448bae78a601222305a2686b96baec0512832309
7
+ data.tar.gz: '058d11b912b501fb42a2649d83d90345f0bb3090dd3f7f1adaa9ea01b71685faf723acc164d958e3639b2eecd8baa20916a5280dcf2a295f52ca50d787701fea'
data/README.md CHANGED
@@ -12,8 +12,7 @@ gem "shrine-google_cloud_storage"
12
12
 
13
13
  ## Authentication
14
14
 
15
- The GCS plugin uses Google's [Project and Credential Lookup]. Please check
16
- documentation for the various ways to provide credentials.
15
+ The GCS plugin uses the `google-cloud-storage` gem. Please refer to [its documentation for setting up authentication](http://googleapis.github.io/google-cloud-ruby/docs/google-cloud-storage/latest/file.AUTHENTICATION.html).
17
16
 
18
17
  ## Usage
19
18
 
@@ -96,5 +95,4 @@ GCS_DEBUG=true
96
95
  [MIT](http://opensource.org/licenses/MIT)
97
96
 
98
97
  [Google Cloud Storage]: https://cloud.google.com/storage/
99
- [Shrine]: https://github.com/janko-m/shrine
100
- [Project and Credential Lookup]: http://googlecloudplatform.github.io/google-cloud-ruby/#/docs/google-cloud-storage/master/guides/authentication#projectandcredentiallookup
98
+ [Shrine]: https://github.com/shrinerb/shrine
@@ -10,7 +10,7 @@ class Shrine
10
10
  # Initialize a Shrine::Storage for GCS allowing for auto-discovery of the Google::Cloud::Storage client.
11
11
  # @param [String] project Provide if not using auto discovery
12
12
  # @see http://googlecloudplatform.github.io/google-cloud-ruby/#/docs/google-cloud-storage/v1.6.0/guides/authentication#environmentvariables for information on discovery
13
- def initialize(project: nil, bucket:, prefix: nil, host: nil, default_acl: nil, object_options: {})
13
+ def initialize(project: nil, bucket:, prefix: nil, host: nil, default_acl: nil, object_options: {}, credentials: nil)
14
14
  @project = project
15
15
  @bucket = bucket
16
16
  @prefix = prefix
@@ -18,6 +18,7 @@ class Shrine
18
18
  @default_acl = default_acl
19
19
  @object_options = object_options
20
20
  @storage = nil
21
+ @credentials = credentials
21
22
  end
22
23
 
23
24
  # If the file is an UploadFile from GCS, issues a copy command, otherwise it uploads a file.
@@ -29,8 +30,13 @@ class Shrine
29
30
  file = existing_file.copy(
30
31
  @bucket, # dest_bucket_or_path - the bucket to copy the file to
31
32
  object_name(id), # dest_path - the path to copy the file to in the given bucket
32
- acl: @default_acl
33
+ acl: options.fetch(:acl) { @default_acl }
33
34
  ) do |f|
35
+ # Workaround a bug in File#copy where the content-type is not copied if you provide a block
36
+ # See https://github.com/renchap/shrine-google_cloud_storage/issues/36
37
+ # See https://github.com/googleapis/google-cloud-ruby/issues/4254
38
+ f.content_type = existing_file.content_type
39
+
34
40
  # update the additional options
35
41
  @object_options.merge(options).each_pair do |key, value|
36
42
  f.send("#{key}=", value)
@@ -38,21 +44,25 @@ class Shrine
38
44
  end
39
45
  file
40
46
  else
41
- get_bucket.create_file(
42
- prepare_io(io), # file - IO object, or IO-ish object like StringIO
43
- object_name(id), # path
44
- @object_options.merge(
45
- content_type: shrine_metadata["mime_type"],
46
- acl: @default_acl
47
- ).merge(options)
48
- )
47
+ with_file(io) do |file|
48
+ file_options = @object_options.merge(
49
+ content_type: shrine_metadata["mime_type"],
50
+ acl: options.fetch(:acl) { @default_acl }
51
+ ).merge(options)
52
+
53
+ get_bucket.create_file(
54
+ file,
55
+ object_name(id), # path
56
+ **file_options
57
+ )
58
+ end
49
59
  end
50
60
  end
51
61
 
52
62
  # URL to the remote file, accepts options for customizing the URL
53
63
  def url(id, **options)
54
64
  if options.key? :expires
55
- signed_url = storage.signed_url(@bucket, object_name(id), options)
65
+ signed_url = storage.signed_url(@bucket, object_name(id), **options)
56
66
  signed_url.gsub!(/storage.googleapis.com\/#{@bucket}/, @host) if @host
57
67
  signed_url
58
68
  else
@@ -61,31 +71,27 @@ class Shrine
61
71
  end
62
72
  end
63
73
 
64
- # Downloads the file from GCS, and returns a `Tempfile`.
65
- def download(id)
66
- tempfile = Tempfile.new(["googlestorage", File.extname(id)], binmode: true)
67
- get_file(id).download tempfile.path
68
- tempfile.tap(&:open)
69
- end
70
-
71
74
  # Opens the remote file and returns it as `Down::ChunkedIO` object.
72
75
  # @return [Down::ChunkedIO] object
73
76
  # @see https://github.com/janko-m/down#downchunkedio
74
- def open(id)
77
+ def open(id, rewindable: true, **options)
75
78
  file = get_file(id)
76
79
 
80
+ raise Shrine::FileNotFound, "file #{id.inspect} not found on storage" unless file
81
+
77
82
  # create enumerator which lazily yields chunks of downloaded content
78
83
  chunks = Enumerator.new do |yielder|
79
84
  # trick to get google client to stream the download
80
85
  proc_io = ProcIO.new { |data| yielder << data }
81
- file.download(proc_io, verify: :none)
86
+ file.download(proc_io, verify: :none, **options)
82
87
  end
83
88
 
84
89
  # wrap chunks in an IO-like object which downloads when needed
85
90
  Down::ChunkedIO.new(
86
- chunks: chunks,
87
- size: file.size,
88
- data: { file: file }
91
+ chunks: chunks,
92
+ size: file.size,
93
+ rewindable: rewindable,
94
+ data: { file: file },
89
95
  )
90
96
  end
91
97
 
@@ -99,31 +105,36 @@ class Shrine
99
105
  # deletes the file from the storage
100
106
  def delete(id)
101
107
  file = get_file(id)
102
- file.delete unless file.nil?
108
+ delete_file(file) unless file.nil?
103
109
  end
104
110
 
105
- # Otherwise deletes all objects from the storage.
106
- def clear!
111
+ # deletes all objects from the storage
112
+ # If block is givem, deletes only objects for which
113
+ # the block evaluates to true.
114
+ #
115
+ # clear!
116
+ # # or
117
+ # clear! { |file| file.updated_at < 1.week.ago }
118
+ def clear!(&block)
107
119
  prefix = "#{@prefix}/" if @prefix
108
120
  files = get_bucket.files prefix: prefix
109
- batch_delete(files.lazy.map(&:name))
121
+
110
122
  loop do
111
- break if !files.next?
112
- batch_delete(files.next.lazy.map(&:name))
123
+ files.each { |file| delete_file(file) if block.nil? || block.call(file) }
124
+ files = files.next or break
113
125
  end
114
126
  end
115
127
 
128
+ # returns request data (:method, :url, and :headers) for direct uploads
116
129
  def presign(id, **options)
130
+ url = storage.signed_url(@bucket, object_name(id), method: "PUT", **options)
131
+
117
132
  headers = {}
118
133
  headers["Content-Type"] = options[:content_type] if options[:content_type]
119
134
  headers["Content-MD5"] = options[:content_md5] if options[:content_md5]
120
135
  headers.merge!(options[:headers]) if options[:headers]
121
136
 
122
- OpenStruct.new(
123
- url: storage.signed_url(@bucket, object_name(id), method: "PUT", **options),
124
- fields: {},
125
- headers: headers
126
- )
137
+ { method: :put, url: url, headers: headers }
127
138
  end
128
139
 
129
140
  def object_name(id)
@@ -142,11 +153,13 @@ class Shrine
142
153
 
143
154
  # @see http://googlecloudplatform.github.io/google-cloud-ruby/#/docs/google-cloud-storage/v1.6.0/guides/authentication
144
155
  def storage
145
- @storage ||= if @project.nil?
146
- Google::Cloud::Storage.new
147
- else
148
- Google::Cloud::Storage.new(project: @project)
149
- end
156
+ return @storage if @storage
157
+
158
+ opts = {}
159
+ opts[:project] = @project if @project
160
+ opts[:credentials] = @credentials if @credentials
161
+
162
+ @storage = Google::Cloud::Storage.new(**opts)
150
163
  end
151
164
 
152
165
  def copyable?(io)
@@ -155,27 +168,20 @@ class Shrine
155
168
  # TODO: add a check for the credentials
156
169
  end
157
170
 
158
- # Google cloud storage client only accepts IO|IOString|Tempfile instances
159
- # or else it will raise a "Google::Apis::ClientError, 'Invalid upload source"
160
- #
161
- # We need to convert our file to an IO.
162
- j
163
- # see:
164
- # https://github.com/google/google-api-ruby-client/blob/1c2cf5d57fd5e606c03f2aecab88469f46b8f3b2/lib/google/apis/core/upload.rb#L77
165
- def prepare_io(io)
166
- if io.respond_to?(:to_io)
167
- io.to_io
168
- elsif io.respond_to?(:tempfile)
169
- io.tempfile
171
+ def with_file(io)
172
+ if io.respond_to?(:tempfile) # ActionDispatch::Http::UploadedFile
173
+ yield io.tempfile
170
174
  else
171
- io
175
+ Shrine.with_file(io) { |file| yield file }
172
176
  end
173
177
  end
174
178
 
175
- def batch_delete(object_names)
176
- bucket = get_bucket
177
- object_names.each do |name|
178
- bucket.file(name).delete
179
+ # deletes file with ignoring NotFoundError
180
+ def delete_file(file)
181
+ begin
182
+ file.delete
183
+ rescue Google::Cloud::NotFoundError
184
+ # we're fine if the file was already deleted
179
185
  end
180
186
  end
181
187
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = "shrine-google_cloud_storage"
3
- gem.version = "1.0.1"
3
+ gem.version = "3.1.0"
4
4
 
5
5
  gem.required_ruby_version = ">= 2.1"
6
6
 
@@ -13,11 +13,11 @@ Gem::Specification.new do |gem|
13
13
  gem.files = Dir["README.md", "LICENSE.txt", "lib/**/*.rb", "shrine-google_cloud_storage.gemspec"]
14
14
  gem.require_path = "lib"
15
15
 
16
- gem.add_dependency "shrine", "~> 2.0"
16
+ gem.add_dependency "shrine", "~> 3.0"
17
17
  gem.add_dependency "google-cloud-storage", "~> 1.6"
18
18
 
19
19
  gem.add_development_dependency "rake"
20
20
  gem.add_development_dependency "minitest"
21
21
  gem.add_development_dependency "dotenv"
22
- gem.add_development_dependency "http", "~> 3.0"
22
+ gem.add_development_dependency "http", "~> 4.0"
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shrine-google_cloud_storage
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Renaud Chaput
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-13 00:00:00.000000000 Z
11
+ date: 2021-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: shrine
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '3.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '3.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: google-cloud-storage
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,15 +86,15 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '3.0'
89
+ version: '4.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '3.0'
97
- description:
96
+ version: '4.0'
97
+ description:
98
98
  email:
99
99
  - renchap@gmail.com
100
100
  executables: []
@@ -108,7 +108,7 @@ homepage: https://github.com/renchap/shrine-google_cloud_storage
108
108
  licenses:
109
109
  - MIT
110
110
  metadata: {}
111
- post_install_message:
111
+ post_install_message:
112
112
  rdoc_options: []
113
113
  require_paths:
114
114
  - lib
@@ -123,9 +123,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  requirements: []
126
- rubyforge_project:
127
- rubygems_version: 2.6.14
128
- signing_key:
126
+ rubygems_version: 3.2.15
127
+ signing_key:
129
128
  specification_version: 4
130
129
  summary: Provides Google Cloud Storage storage for Shrine.
131
130
  test_files: []