shrine-google_cloud_storage 1.0.1 → 3.1.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 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: []