shrine-google_drive_storage 0.1.1 → 0.2.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: 9b7fcd9c23ef5b5c97e5083d68fa883319edc155
4
- data.tar.gz: 647ed18c25768aace7c773daedc7714e5aef6309
3
+ metadata.gz: 20ce8cde9408e42b0f6760dcc15037cf42f6791d
4
+ data.tar.gz: deaa6b58b6a306508fddcff85fa2e27af192d481
5
5
  SHA512:
6
- metadata.gz: 44023b697469e030042fc1a1658959cda9dfb153bf82b51d8433737f53b900a8218b3b42191d901ee6b6fb9e43677daff99055796aa679bc71e8283b00b0a8f6
7
- data.tar.gz: b38a40f54baf375d24239cf7b47c588bda05e1f670ebf275c2dc91e70d78d56202fadee066ac44e316e5988e3329140980d7e1b1d8ce88c0aaa424b845e4744f
6
+ metadata.gz: 4ac056acfc70909e7aba8497a64d5d5903cd34d895eb9e8106a0bad783fd97a5e1075ab396f515b8681ce7ff0d11bb03ee2579d311fdcb711fc19db77a77b554
7
+ data.tar.gz: e0e1a102ac83ff4d9ea0a6def751001ba2505c36d2e3d9c9571c3ae531afa69cc46e5035bc99d7b5ae2ffa9aa07b35e5f004ffb4657bd504073e8d0ada1ce7a5
@@ -45,28 +45,20 @@ class Shrine
45
45
 
46
46
  def upload(io, id, shrine_metadata: {}, **_options)
47
47
  # uploads `io` to the location `id`
48
-
49
- @queued_for_write.each do |style, file|
50
- raise FileExists, "file \"#{path(style)}\" already exists in your Google Drive" if exists?(path(style))
51
-
52
- name, mime_type = filename_from(style), "#{ file.content_type }"
53
-
54
- file_metadata = {
55
- name: name,
56
- description: 'shrine file on google drive',
57
- mimeType: mime_type,
58
- parents: [find_public_folder]
59
- }
60
-
61
- google_api_client.create_file(
62
- file_metadata,
63
- fields: 'id',
64
- upload_source: file.binmode,
65
- content_type: file.content_type,
66
- )
67
- end
68
- after_upload
69
- @queued_for_write = {}
48
+ shrine_metadata = {
49
+ name: id,
50
+ description: 'shrine file on google drive',
51
+ mimeType: mime_type,
52
+ parents: folder_id
53
+ }
54
+
55
+ google_api_client.create_file(
56
+ shrine_metadata,
57
+ fields: 'id, name',
58
+ upload_source: io.to_io,
59
+ content_type: shrine_metadata["mime_type"]
60
+ )
61
+ message = "Uploaded file #{file.name} with Id: #{file.id}"
70
62
  end
71
63
 
72
64
  def google_api_client
@@ -83,178 +75,133 @@ class Shrine
83
75
 
84
76
  def url(id, **_options)
85
77
  # URL to the remote file, accepts options for customizing the URL
86
- if present?
87
- style = args.first.is_a?(Symbol) ? args.first : default_style
88
- options = args.last.is_a?(Hash) ? args.last : {}
89
- if style == :custom_thumb && is_valid_for_custom_thumb?
90
- custom_width = options[:width] || 220
91
- file_name = filename_from(default_style)
92
- public_url_custom_thumbnail_from(file_name, custom_width)
93
- else
94
- file_name = filename_from(style)
95
- public_url_for(file_name)
96
- end
97
- else
98
- default_image
99
- end
78
+ client = google_api_client
79
+ metadata = client.get_file(
80
+ id,
81
+ fields: 'webViewLink'
82
+ )
83
+ metadata.web_view_link
100
84
  end
101
85
 
102
- def is_valid_for_custom_thumb?
103
- content_type =~ /image/ || content_type =~ /pdf/
104
- end
105
86
 
106
- # def download(id)
107
- # tempfile = Tempfile.new(["googlestorage", File.extname(id)], binmode: true)
108
- # storage_api.get_object(@bucket, object_name(id), download_dest: tempfile)
109
- # tempfile.tap(&:open)
110
- # end
87
+ def download(id)
88
+ client = google_api_client
89
+ tempfile = Tempfile.new(["googledrive", File.extname(id)], binmode: true)
90
+ client.get_file(
91
+ id,
92
+ download_dest: tempfile)
93
+ tempfile.tap(&:open)
94
+ end
111
95
 
112
96
  def open(id)
113
97
  # returns the remote file as an IO-like object
114
- if file_id.is_a? String
115
98
  client = google_api_client
116
- metadata = client.get_file(
117
- file_id,
118
- fields: 'id, name, thumbnailLink, webContentLink, webViewLink, trashed'
99
+ io = client.get_file(
100
+ id,
101
+ download_dest: StringIO.new
119
102
  )
120
- validate_metadata(metadata)
121
- metadata
122
- end
103
+ io.rewind
104
+ io
123
105
  end
124
106
 
125
- # Raises an error in case that the Google Drive API does not response
126
- # with the minimum required information.
127
- # @params [ Google::Apis::DriveV3::File ]
128
- def validate_metadata(metadata)
129
- raise 'the file id was not retrieved' if metadata.id.nil?
130
- raise 'the file name was not retrieved' if metadata.name.nil?
131
- raise 'the file web_content_link was not retrieved' if metadata.web_content_link.nil?
132
- raise 'the file web_view_link was not retrieved' if metadata.web_view_link.nil?
133
- raise 'the file trashed was not retrieved' if metadata.trashed.nil?
134
- end
135
107
 
136
108
  def exists?(id)
137
109
  # checks if the file exists on the storage
138
- return false if not present?
139
- result_id = search_for_title(path(style))
140
- if result_id.nil?
141
- false
142
- else
143
- data = metadata_by_id(result_id)
144
- !data.trashed # if trashed -> not exists
145
- end
146
- end
147
-
148
- # Gets the file metadata if it exists
149
- # in other case returns the defaul image
150
- # @param title [ String ]
151
- # @param block [ Proc ]
152
- def metadata_or_default_img_from(title, &block)
153
- searched_id = search_for_title(title) #return id if any or style
154
- if searched_id.nil? # it finds some file
155
- default_image
156
- else
157
- metadata = metadata_by_id(searched_id)
158
- yield metadata
159
- end
160
- end
161
-
162
- def default_image
163
- if @google_drive_options[:default_url] #if default image is set
164
- title = @google_drive_options[:default_url]
165
- searched_id = search_for_title(title) # id
166
- if searched_id.nil?
167
- raise 'Default image not found, please double check its name'
110
+ client = google_api_client
111
+ client.get_file(id) do |_, err|
112
+ if err
113
+ if err.status_code == 404
114
+ false
115
+ else
116
+ raise err
117
+ end
168
118
  else
169
- metadata = metadata_by_id(searched_id)
170
- effective_url_from(metadata.web_content_link)
119
+ true
171
120
  end
172
- else
173
- 'No picture' # ---- ?
174
- end
175
- end
176
-
177
- def find_public_folder
178
- if @google_drive_options[:public_folder_id].is_a? Proc
179
- instance.instance_exec(&@google_drive_options[:public_folder_id])
180
- else
181
- @google_drive_options[:public_folder_id]
182
121
  end
183
122
  end
184
123
 
185
124
  def delete(id)
186
125
  # deletes the file from the storage
187
- @queued_for_delete.each do |path|
188
- Shrine.log("Delete: #{ path }")
189
- file_id = search_for_title(path)
190
- google_api_client.delete_file(file_id) unless file_id.nil?
191
- end
192
- @queued_for_delete = []
193
- end
126
+ google_api_client.delete_file(id) unless id.nil?
194
127
 
195
- def filename_from(style)
196
- file_name = instance.instance_exec(style, &file_title)
197
- style_suffix = (style != default_style ? "_#{style}" : "")
198
- if original_extension.present? && file_name =~ /#{original_extension}$/
199
- file_name.sub(original_extension, "#{style_suffix}#{original_extension}")
200
- else
201
- file_name + style_suffix + original_extension.to_s
202
- end
203
- end
128
+ rescue Google::Apis::ClientError => e
129
+ # The object does not exist, Shrine expects us to be ok
130
+ return true if e.status_code == 404
204
131
 
205
- alias_method :path, :filename_from
132
+ raise e
133
+ end
206
134
 
207
- # Gets the public url for a passed filename
208
- # @param title [ String ]
209
- # @return [ String ] with url
210
- def public_url_for(title)
211
- metadata_or_default_img_from(title) do |metadata|
212
- # effective_url_from(metadata.web_content_link)
213
- if content_type =~ /image/
214
- custom_thumbnail_image_for(metadata.thumbnail_link, 1000)
215
- else
216
- metadata.web_view_link
135
+ def multi_delete(ids)
136
+ client = google_api_client
137
+ ids.each_slice(100) do |ids|
138
+ client.batch do |client|
139
+ ids.each do |id|
140
+ client.delete_object(id)
141
+ end
217
142
  end
218
143
  end
219
144
  end
220
145
 
221
- # Gets the public url for a passed filename
222
- # @param title [ String ]
223
- # @param custom_width [ Integer ]
224
- # @return [ String ] with url
225
- def public_url_custom_thumbnail_from(title, custom_width)
226
- metadata_or_default_img_from(title) do |metadata|
227
- custom_thumbnail_image_for(metadata.thumbnail_link, custom_width)
228
- end
146
+ def create_folder(name)
147
+ client = google_api_client
148
+ file_metadata = {
149
+ name: name,
150
+ mime_type: 'application/vnd.google-apps.folder'
151
+ }
152
+ file = client.create_file(file_metadata, fields: 'id, name')
153
+ message = "Created folder #{file.name} with folder id: #{file.id}"
154
+ end
155
+
156
+ def find_folder_id(name)
157
+ client = google_api_client
158
+ page_token = nil
159
+ begin
160
+ response = client.list_files(q: "mimeType = 'application/vnd.google-apps.folder' and name contains '#{ name }'",
161
+ spaces: 'drive',
162
+ fields:'nextPageToken, files(id, name)',
163
+ page_token: page_token)
164
+ for file in response.files
165
+ # Process change
166
+ message = "Found folder: #{file.name} ID: #{file.id}"
167
+ end
168
+ page_token = response.next_page_token
169
+ end while !page_token.nil?
170
+ end
171
+
172
+ def insert_in_folder(file_id, folder_id)
173
+ client = google_api_client
174
+ file = client.update_file(file_id,
175
+ add_parents: folder_id,
176
+ fields: 'id, name, parents')
177
+ message = "File #{file.name} with ID #{file.id} inserted into folder #{file.parents}"
178
+ end
179
+
180
+ def move_file(file_id, new_folder_id)
181
+ client = google_api_client
182
+ # Retrieve the existing parents to remove
183
+ file = client.get_file(file_id,
184
+ fields: 'parents')
185
+ previous_parents = file.parents.join(',')
186
+ # Move the file to the new folder
187
+ file = client.update_file(file_id,
188
+ add_parents: new_folder_id,
189
+ remove_parents: previous_parents,
190
+ fields: 'id, name, parents')
191
+ message = "File #{file.name} with ID #{file.id} moved to folder #{file.parents}"
192
+ end
193
+
194
+ def file_name(file_id)
195
+ client = google_api_client
196
+ metadata = client.get_file(
197
+ file_id,
198
+ fields: 'id, name'
199
+ )
200
+ metadata.name
229
201
  end
230
202
 
231
- # Retrieves the specific image with a custom size. It is resized by GDrive API if you
232
- # pass the :custom_thumb as style option. In other cases, it removes the last parameter
233
- # `=s220` which is inchaged to do the scaling process.
234
- # @param drive_thumbnail_link [ String ] with the form: https://<url value>=s220
235
- # @param custom_width [ Integer ] ex. 512
236
- # @return [ String ]
237
- def custom_thumbnail_image_for(drive_thumbnail_link, custom_width)
238
- file_url, current_width = drive_thumbnail_link.split(/=s/)
239
- "#{ file_url }=s#{ custom_width }"
240
- end
203
+ alias_method :object_name
241
204
 
242
- # TOO SLOW and PERMISSIONS ISSUES
243
- # Seems that the retrieved file url is only visible for the
244
- # user which is owner and is currently log in GDrive.
245
- #
246
- # Gets the effective url from the web content link
247
- # These are a series of steps to hack the way that GDrive API
248
- # handle its urls. It consists in catch a Google::Apis::RedirectError error
249
- # and take the correct url where is located the file.
250
- # @param driver_web_content_link [ String ]
251
- # @return [ String ]
252
- def effective_url_from(drive_web_content_link)
253
- redirect_url = drive_web_content_link.split(/&export=/)[0]
254
- google_drive.http(:get, redirect_url) do |result, err|
255
- err.header[:location].split('&continue=')[1]
256
- end
257
- end
258
205
 
259
206
  # Takes the file title/name and search it in a given folder
260
207
  # If it finds a file, return id of a file or nil
@@ -264,7 +211,7 @@ class Shrine
264
211
  raise 'You are trying to search a file with NO name' if name.nil? || name.empty?
265
212
  client = google_api_client
266
213
  result = client.list_files(page_size: 1,
267
- q: "name contains '#{ name }' and '#{ find_public_folder }' in parents",
214
+ q: "name contains '#{ name }'",
268
215
  fields: 'files(id, name)'
269
216
  )
270
217
  if result.files.length > 0
@@ -274,25 +221,6 @@ class Shrine
274
221
  end
275
222
  end
276
223
 
277
- #
278
- # Error classes
279
- #
280
-
281
- class FileExists < ArgumentError
282
- end
283
-
284
- private
285
-
286
- def file_title
287
- return @google_drive_options[:path] if @google_drive_options[:path] #path: proc
288
- eval %(proc { |style| "\#{id}_\#{#{name}.original_filename}"})
289
- end
290
-
291
- # @return [String] with the extension of file
292
- def original_extension
293
- File.extname(original_filename)
294
- end
295
-
296
224
  end
297
225
  end
298
226
  end
@@ -1,5 +1,5 @@
1
1
  module Shrine
2
2
  module GoogleDriveStorage
3
- VERSION = "0.1.1"
3
+ VERSION = "0.2.1"
4
4
  end
5
5
  end
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Scott Near"]
10
10
  spec.email = ["scott.a.near@gmail.com"]
11
11
 
12
- spec.summary = "Provides Google Cloud Storage storage for Shrine."
13
- spec.description = "Provides Google Drive Storage storage for Shrine."
12
+ spec.summary = "Provides Google Drive Storage for Shrine."
13
+ spec.description = "Provides Google Drive Storage for Shrine."
14
14
  spec.homepage = "https://github.com/verynear/shrine-google_drive_storage"
15
15
  spec.license = "MIT"
16
16
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shrine-google_drive_storage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Near
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-27 00:00:00.000000000 Z
11
+ date: 2017-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: shrine
@@ -140,7 +140,7 @@ dependencies:
140
140
  - - ">="
141
141
  - !ruby/object:Gem::Version
142
142
  version: 4.2.0
143
- description: Provides Google Drive Storage storage for Shrine.
143
+ description: Provides Google Drive Storage for Shrine.
144
144
  email:
145
145
  - scott.a.near@gmail.com
146
146
  executables:
@@ -191,5 +191,5 @@ rubyforge_project:
191
191
  rubygems_version: 2.6.10
192
192
  signing_key:
193
193
  specification_version: 4
194
- summary: Provides Google Cloud Storage storage for Shrine.
194
+ summary: Provides Google Drive Storage for Shrine.
195
195
  test_files: []