google_drive 1.0.6 → 2.0.0.pre1
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/README.rdoc +3 -7
- data/doc_src/google_drive/acl.rb +13 -17
- data/lib/google_drive.rb +130 -160
- data/lib/google_drive/acl.rb +77 -93
- data/lib/google_drive/acl_entry.rb +149 -105
- data/lib/google_drive/api_client_fetcher.rb +22 -41
- data/lib/google_drive/authentication_error.rb +4 -8
- data/lib/google_drive/collection.rb +127 -149
- data/lib/google_drive/config.rb +23 -25
- data/lib/google_drive/error.rb +3 -3
- data/lib/google_drive/file.rb +215 -273
- data/lib/google_drive/list.rb +108 -113
- data/lib/google_drive/list_row.rb +65 -70
- data/lib/google_drive/response_code_error.rb +11 -16
- data/lib/google_drive/session.rb +412 -444
- data/lib/google_drive/spreadsheet.rb +62 -67
- data/lib/google_drive/util.rb +200 -160
- data/lib/google_drive/worksheet.rb +453 -469
- metadata +60 -22
data/lib/google_drive/config.rb
CHANGED
@@ -4,34 +4,32 @@
|
|
4
4
|
require 'json'
|
5
5
|
|
6
6
|
module GoogleDrive
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
instance_variable_set("@#{key}", value) if FIELDS.include?(key)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def save
|
22
|
-
::File.open(@config_path, 'w', 0600) { |f| f.write(to_json()) }
|
7
|
+
class Config #:nodoc:
|
8
|
+
FIELDS = %w(client_id client_secret scope refresh_token).freeze
|
9
|
+
attr_accessor(*FIELDS)
|
10
|
+
|
11
|
+
def initialize(config_path)
|
12
|
+
@config_path = config_path
|
13
|
+
if ::File.exist?(config_path)
|
14
|
+
JSON.parse(::File.read(config_path)).each do |key, value|
|
15
|
+
instance_variable_set("@#{key}", value) if FIELDS.include?(key)
|
23
16
|
end
|
17
|
+
end
|
18
|
+
end
|
24
19
|
|
25
|
-
|
20
|
+
def save
|
21
|
+
::File.open(@config_path, 'w', 0600) { |f| f.write(to_json) }
|
22
|
+
end
|
26
23
|
|
27
|
-
|
28
|
-
hash = {}
|
29
|
-
FIELDS.each do |field|
|
30
|
-
value = __send__(field)
|
31
|
-
hash[field] = value if value
|
32
|
-
end
|
33
|
-
return JSON.pretty_generate(hash)
|
34
|
-
end
|
24
|
+
private
|
35
25
|
|
26
|
+
def to_json
|
27
|
+
hash = {}
|
28
|
+
FIELDS.each do |field|
|
29
|
+
value = __send__(field)
|
30
|
+
hash[field] = value if value
|
31
|
+
end
|
32
|
+
JSON.pretty_generate(hash)
|
36
33
|
end
|
34
|
+
end
|
37
35
|
end
|
data/lib/google_drive/error.rb
CHANGED
data/lib/google_drive/file.rb
CHANGED
@@ -1,301 +1,243 @@
|
|
1
1
|
# Author: Hiroshi Ichikawa <http://gimite.net/>
|
2
2
|
# The license of this source is "New BSD Licence"
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
|
8
|
-
require "google_drive/util"
|
9
|
-
require "google_drive/acl"
|
4
|
+
require 'cgi'
|
5
|
+
require 'forwardable'
|
6
|
+
require 'stringio'
|
10
7
|
|
8
|
+
require 'google_drive/util'
|
9
|
+
require 'google_drive/acl'
|
11
10
|
|
12
11
|
module GoogleDrive
|
13
|
-
|
14
|
-
|
12
|
+
# A file in Google Drive, including Google Docs document/spreadsheet/presentation.
|
13
|
+
#
|
14
|
+
# Use GoogleDrive::Session#files or GoogleDrive::Session#file_by_title to
|
15
|
+
# get this object.
|
16
|
+
#
|
17
|
+
# In addition to the methods below, properties defined here are also available as attributes:
|
18
|
+
# https://developers.google.com/drive/v3/reference/files#resource
|
19
|
+
#
|
20
|
+
# e.g.,
|
21
|
+
# file.mime_type # ==> "text/plain"
|
22
|
+
class File
|
23
|
+
include(Util)
|
24
|
+
extend(Forwardable)
|
25
|
+
|
26
|
+
def initialize(session, api_file) #:nodoc:
|
27
|
+
@session = session
|
28
|
+
@api_file = api_file
|
29
|
+
@acl = nil
|
30
|
+
delegate_api_methods(self, @api_file, [:title])
|
31
|
+
end
|
32
|
+
|
33
|
+
# Wrapped Google::APIClient::Schema::Drive::V3::File object.
|
34
|
+
attr_reader(:api_file)
|
35
|
+
|
36
|
+
# Reloads file metadata such as title and acl.
|
37
|
+
def reload_metadata
|
38
|
+
@api_file = @session.drive.get_file(id, fields: '*')
|
39
|
+
@acl = Acl.new(@session, self) if @acl
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns resource_type + ":" + id.
|
43
|
+
def resource_id
|
44
|
+
'%s:%s' % [resource_type, id]
|
45
|
+
end
|
46
|
+
|
47
|
+
# URL of feed used in the deprecated document list feed API.
|
48
|
+
def document_feed_url
|
49
|
+
'https://docs.google.com/feeds/default/private/full/' + CGI.escape(resource_id)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Deprecated ACL feed URL of the file.
|
53
|
+
def acl_feed_url
|
54
|
+
document_feed_url + '/acl'
|
55
|
+
end
|
56
|
+
|
57
|
+
# The type of resourse. e.g. "document", "spreadsheet", "folder"
|
58
|
+
def resource_type
|
59
|
+
mime_type.slice(/^application\/vnd.google-apps.(.+)$/, 1) || 'file'
|
60
|
+
end
|
61
|
+
|
62
|
+
# Title of the file.
|
63
|
+
def title(params = {})
|
64
|
+
reload_metadata if params[:reload]
|
65
|
+
api_file.name
|
66
|
+
end
|
67
|
+
|
68
|
+
# URL to view/edit the file in a Web browser.
|
15
69
|
#
|
16
|
-
#
|
17
|
-
|
70
|
+
# e.g. "https://docs.google.com/file/d/xxxx/edit"
|
71
|
+
def human_url
|
72
|
+
api_file.web_view_link
|
73
|
+
end
|
74
|
+
|
75
|
+
# Content types you can specify in methods download_to_file, download_to_string,
|
76
|
+
# download_to_io .
|
18
77
|
#
|
19
|
-
#
|
20
|
-
#
|
78
|
+
# This returns zero or one file type. You may be able to download the file in other formats using
|
79
|
+
# export_as_file, export_as_string, or export_to_io.
|
80
|
+
def available_content_types
|
81
|
+
api_file.download_url ? [api_file.mime_type] : []
|
82
|
+
end
|
83
|
+
|
84
|
+
# Downloads the file to a local file. e.g.
|
85
|
+
# file.download_to_file("/path/to/hoge.txt")
|
21
86
|
#
|
22
|
-
#
|
23
|
-
|
24
|
-
|
87
|
+
# To export the file in other formats, use export_as_file.
|
88
|
+
def download_to_file(path, params = {})
|
89
|
+
@session.drive.get_file(id, download_dest: path)
|
90
|
+
end
|
25
91
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
92
|
+
# Downloads the file and returns as a String.
|
93
|
+
#
|
94
|
+
# To export the file in other formats, use export_as_string.
|
95
|
+
def download_to_string(params = {})
|
96
|
+
sio = StringIO.new
|
97
|
+
download_to_io(sio, params)
|
98
|
+
sio.string
|
99
|
+
end
|
35
100
|
|
36
|
-
|
37
|
-
|
101
|
+
# Downloads the file and writes it to +io+.
|
102
|
+
#
|
103
|
+
# To export the file in other formats, use export_to_io.
|
104
|
+
def download_to_io(io, _params = {})
|
105
|
+
@session.drive.get_file(id, download_dest: io)
|
106
|
+
end
|
38
107
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
108
|
+
# Export the file to +path+ in content type +format+.
|
109
|
+
# If +format+ is nil, it is guessed from the file name.
|
110
|
+
#
|
111
|
+
# e.g.,
|
112
|
+
# spreadsheet.export_as_file("/path/to/hoge.csv")
|
113
|
+
# spreadsheet.export_as_file("/path/to/hoge", "text/csv")
|
114
|
+
#
|
115
|
+
# If you want to download the file in the original format, use download_to_file instead.
|
116
|
+
def export_as_file(path, format = nil)
|
117
|
+
unless format
|
118
|
+
format = EXT_TO_CONTENT_TYPE[::File.extname(path).downcase]
|
119
|
+
unless format
|
120
|
+
fail(ArgumentError,
|
121
|
+
("Cannot guess format from the file name: %s\n" \
|
122
|
+
'Specify format argument explicitly.') %
|
123
|
+
path)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
export_to_dest(path, format)
|
127
|
+
end
|
49
128
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
129
|
+
# Export the file as String in content type +format+.
|
130
|
+
#
|
131
|
+
# e.g.,
|
132
|
+
# spreadsheet.export_as_string("text/csv")
|
133
|
+
#
|
134
|
+
# If you want to download the file in the original format, use download_to_string instead.
|
135
|
+
def export_as_string(format)
|
136
|
+
sio = StringIO.new
|
137
|
+
export_to_dest(sio, format)
|
138
|
+
sio.string
|
139
|
+
end
|
54
140
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
141
|
+
# Export the file to +io+ in content type +format+.
|
142
|
+
#
|
143
|
+
# If you want to download the file in the original format, use download_to_io instead.
|
144
|
+
def export_to_io(io, format)
|
145
|
+
export_to_dest(io, format)
|
146
|
+
end
|
59
147
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
148
|
+
# Updates the file with +content+.
|
149
|
+
#
|
150
|
+
# e.g.
|
151
|
+
# file.update_from_string("Good bye, world.")
|
152
|
+
def update_from_string(content, params = {})
|
153
|
+
update_from_io(StringIO.new(content), params)
|
154
|
+
end
|
64
155
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
156
|
+
# Updates the file with the content of the local file.
|
157
|
+
#
|
158
|
+
# e.g.
|
159
|
+
# file.update_from_file("/path/to/hoge.txt")
|
160
|
+
def update_from_file(path, params = {})
|
161
|
+
# Somehow it doesn't work if I specify the file name directly as upload_source.
|
162
|
+
open(path, 'rb') do |f|
|
163
|
+
update_from_io(f, params)
|
164
|
+
end
|
165
|
+
nil
|
166
|
+
end
|
69
167
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
# URL to view/edit the file in a Web browser.
|
77
|
-
#
|
78
|
-
# e.g. "https://docs.google.com/file/d/xxxx/edit"
|
79
|
-
def human_url
|
80
|
-
return self.alternate_link
|
81
|
-
end
|
82
|
-
|
83
|
-
# Content types you can specify in methods download_to_file, download_to_string,
|
84
|
-
# download_to_io .
|
85
|
-
#
|
86
|
-
# This returns zero or one file type. You may be able to download the file in other formats using
|
87
|
-
# export_as_file, export_as_string, or export_to_io. Use export_links method to get available formats
|
88
|
-
# in these methods.
|
89
|
-
def available_content_types
|
90
|
-
if self.api_file.download_url
|
91
|
-
return [self.api_file.mime_type]
|
92
|
-
else
|
93
|
-
return []
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# Downloads the file to a local file. e.g.
|
98
|
-
# file.download_to_file("/path/to/hoge.txt")
|
99
|
-
#
|
100
|
-
# To export the file in other formats, use export_as_file.
|
101
|
-
def download_to_file(path, params = {})
|
102
|
-
open(path, "wb") do |f|
|
103
|
-
download_to_io(f, params)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# Downloads the file and returns as a String.
|
108
|
-
#
|
109
|
-
# To export the file in other formats, use export_as_string.
|
110
|
-
def download_to_string(params = {})
|
111
|
-
sio = StringIO.new()
|
112
|
-
download_to_io(sio, params)
|
113
|
-
return sio.string
|
114
|
-
end
|
115
|
-
|
116
|
-
# Downloads the file and writes it to +io+.
|
117
|
-
#
|
118
|
-
# To export the file in other formats, use export_to_io.
|
119
|
-
def download_to_io(io, params = {})
|
120
|
-
if !self.api_file.download_url
|
121
|
-
raise(GoogleDrive::Error, "Downloading is not supported for this file.")
|
122
|
-
end
|
123
|
-
# TODO Use streaming if possible.
|
124
|
-
api_result = @session.execute!(:uri => self.api_file.download_url)
|
125
|
-
io.write(api_result.body)
|
126
|
-
end
|
168
|
+
# Reads content from +io+ and updates the file with the content.
|
169
|
+
def update_from_io(io, params = {})
|
170
|
+
params = { upload_source: io }.merge(params)
|
171
|
+
@session.drive.update_file(id, nil, params)
|
172
|
+
nil
|
173
|
+
end
|
127
174
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
format = EXT_TO_CONTENT_TYPE[::File.extname(path).downcase]
|
139
|
-
if !format
|
140
|
-
raise(ArgumentError,
|
141
|
-
("Cannot guess format from the file name: %s\n" +
|
142
|
-
"Specify format argument explicitly.") %
|
143
|
-
path)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
open(path, "wb") do |f|
|
147
|
-
export_to_io(f, format)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
# Export the file as String in content type +format+.
|
152
|
-
#
|
153
|
-
# e.g.,
|
154
|
-
# spreadsheet.export_as_string("text/csv")
|
155
|
-
#
|
156
|
-
# If you want to download the file in the original format, use download_to_string instead.
|
157
|
-
def export_as_string(format)
|
158
|
-
sio = StringIO.new()
|
159
|
-
export_to_io(sio, format)
|
160
|
-
return sio.string
|
161
|
-
end
|
175
|
+
# If +permanent+ is +false+, moves the file to the trash.
|
176
|
+
# If +permanent+ is +true+, deletes the file permanently.
|
177
|
+
def delete(permanent = false)
|
178
|
+
if permanent
|
179
|
+
@session.drive.delete_file(id)
|
180
|
+
else
|
181
|
+
@session.drive.update_file(id, { trashed: true }, {})
|
182
|
+
end
|
183
|
+
nil
|
184
|
+
end
|
162
185
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
if !self.export_links
|
169
|
-
raise(
|
170
|
-
GoogleDrive::Error,
|
171
|
-
"This file doesn't support exporting. You may still download the file in the " +
|
172
|
-
"original format using download_to_file, download_to_string or download_to_io.")
|
173
|
-
end
|
174
|
-
export_url = self.export_links[mime_type]
|
175
|
-
if !export_url
|
176
|
-
raise(
|
177
|
-
GoogleDrive::Error,
|
178
|
-
"This file doesn't support export with mime type %p. Supported mime types: %p" %
|
179
|
-
[mime_type, self.export_links.to_hash().keys])
|
180
|
-
end
|
181
|
-
# TODO Use streaming if possible.
|
182
|
-
api_result = @session.execute!(:uri => export_url)
|
183
|
-
io.write(api_result.body)
|
184
|
-
end
|
185
|
-
|
186
|
-
# Updates the file with +content+.
|
187
|
-
#
|
188
|
-
# e.g.
|
189
|
-
# file.update_from_string("Good bye, world.")
|
190
|
-
def update_from_string(content, params = {})
|
191
|
-
media = new_upload_io(StringIO.new(content), params)
|
192
|
-
return update_from_media(media, params)
|
193
|
-
end
|
194
|
-
|
195
|
-
# Updates the file with the content of the local file.
|
196
|
-
#
|
197
|
-
# e.g.
|
198
|
-
# file.update_from_file("/path/to/hoge.txt")
|
199
|
-
def update_from_file(path, params = {})
|
200
|
-
file_name = ::File.basename(path)
|
201
|
-
params = {:file_name => file_name}.merge(params)
|
202
|
-
media = new_upload_io(path, params)
|
203
|
-
return update_from_media(media, params)
|
204
|
-
end
|
186
|
+
# Renames title of the file.
|
187
|
+
def rename(title)
|
188
|
+
@session.drive.update_file(id, { name: title }, {})
|
189
|
+
nil
|
190
|
+
end
|
205
191
|
|
206
|
-
|
207
|
-
def update_from_io(io, params = {})
|
208
|
-
media = new_upload_io(io, params)
|
209
|
-
return update_from_media(media, params)
|
210
|
-
end
|
192
|
+
alias_method :title=, :rename
|
211
193
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
:parameters => {
|
218
|
-
"fileId" => self.id,
|
219
|
-
"uploadType" => "media",
|
220
|
-
})
|
221
|
-
return @session.wrap_api_file(api_result.data)
|
222
|
-
end
|
194
|
+
# Creates copy of this file with the given title.
|
195
|
+
def copy(title)
|
196
|
+
api_file = @session.drive.copy_file(id, { name: title }, {})
|
197
|
+
@session.wrap_api_file(api_file)
|
198
|
+
end
|
223
199
|
|
224
|
-
|
225
|
-
# If +permanent+ is +true+, deletes the file permanently.
|
226
|
-
def delete(permanent = false)
|
227
|
-
if permanent
|
228
|
-
@session.execute!(
|
229
|
-
:api_method => @session.drive.files.delete,
|
230
|
-
:parameters => {"fileId" => self.id})
|
231
|
-
else
|
232
|
-
@session.execute!(
|
233
|
-
:api_method => @session.drive.files.trash,
|
234
|
-
:parameters => {"fileId" => self.id})
|
235
|
-
end
|
236
|
-
return nil
|
237
|
-
end
|
200
|
+
alias_method :duplicate, :copy
|
238
201
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
202
|
+
# Returns GoogleDrive::Acl object for the file.
|
203
|
+
#
|
204
|
+
# With the object, you can see and modify people who can access the file.
|
205
|
+
# Modifications take effect immediately.
|
206
|
+
#
|
207
|
+
# e.g.
|
208
|
+
# # Dumps people who have access:
|
209
|
+
# for entry in file.acl
|
210
|
+
# p [entry.type, entry.email_address, entry.role]
|
211
|
+
# # => e.g. ["user", "example1@gmail.com", "owner"]
|
212
|
+
# end
|
213
|
+
#
|
214
|
+
# # Shares the file with new people:
|
215
|
+
# # NOTE: This sends email to the new people.
|
216
|
+
# file.acl.push(
|
217
|
+
# {type: "user", email_address: "example2@gmail.com", role: "reader"})
|
218
|
+
# file.acl.push(
|
219
|
+
# {type: "user", email_address: "example3@gmail.com", role: "writer"})
|
220
|
+
#
|
221
|
+
# # Changes the role of a person:
|
222
|
+
# file.acl[1].role = "writer"
|
223
|
+
#
|
224
|
+
# # Deletes an ACL entry:
|
225
|
+
# file.acl.delete(file.acl[1])
|
226
|
+
def acl(params = {})
|
227
|
+
@acl = Acl.new(@session, self) if !@acl || params[:reload]
|
228
|
+
@acl
|
229
|
+
end
|
249
230
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
"title" => title,
|
254
|
-
})
|
255
|
-
api_result = @session.execute!(
|
256
|
-
:api_method => @session.drive.files.copy,
|
257
|
-
:body_object => copied_file,
|
258
|
-
:parameters => {"fileId" => self.id})
|
259
|
-
return @session.wrap_api_file(api_result.data)
|
260
|
-
end
|
231
|
+
def inspect
|
232
|
+
"\#<%p id=%p title=%p>" % [self.class, id, title]
|
233
|
+
end
|
261
234
|
|
262
|
-
|
263
|
-
|
264
|
-
# Returns GoogleDrive::Acl object for the file.
|
265
|
-
#
|
266
|
-
# With the object, you can see and modify people who can access the file.
|
267
|
-
# Modifications take effect immediately.
|
268
|
-
#
|
269
|
-
# e.g.
|
270
|
-
# # Dumps people who have access:
|
271
|
-
# for entry in file.acl
|
272
|
-
# p [entry.scope_type, entry.scope, entry.role]
|
273
|
-
# # => e.g. ["user", "example1@gmail.com", "owner"]
|
274
|
-
# end
|
275
|
-
#
|
276
|
-
# # Shares the file with new people:
|
277
|
-
# # NOTE: This sends email to the new people.
|
278
|
-
# file.acl.push(
|
279
|
-
# {:type => "user", :value => "example2@gmail.com", :role => "reader"})
|
280
|
-
# file.acl.push(
|
281
|
-
# {:type => "user", :value => "example3@gmail.com", :role => "writer"})
|
282
|
-
#
|
283
|
-
# # Changes the role of a person:
|
284
|
-
# file.acl[1].role = "writer"
|
285
|
-
#
|
286
|
-
# # Deletes an ACL entry:
|
287
|
-
# file.acl.delete(file.acl[1])
|
288
|
-
def acl(params = {})
|
289
|
-
if !@acl || params[:reload]
|
290
|
-
@acl = Acl.new(@session, self)
|
291
|
-
end
|
292
|
-
return @acl
|
293
|
-
end
|
235
|
+
private
|
294
236
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
237
|
+
def export_to_dest(dest, format)
|
238
|
+
mime_type = EXT_TO_CONTENT_TYPE['.' + format] || format
|
239
|
+
@session.drive.export_file(id, mime_type, download_dest: dest)
|
240
|
+
nil
|
299
241
|
end
|
300
|
-
|
242
|
+
end
|
301
243
|
end
|