google_drive 1.0.6 → 2.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,77 +1,74 @@
1
1
  # Author: Hiroshi Ichikawa <http://gimite.net/>
2
2
  # The license of this source is "New BSD Licence"
3
3
 
4
- require "time"
5
-
6
- require "google_drive/util"
7
- require "google_drive/error"
8
- require "google_drive/worksheet"
9
- require "google_drive/acl"
10
- require "google_drive/file"
4
+ require 'time'
11
5
 
6
+ require 'google_drive/util'
7
+ require 'google_drive/error'
8
+ require 'google_drive/worksheet'
9
+ require 'google_drive/acl'
10
+ require 'google_drive/file'
12
11
 
13
12
  module GoogleDrive
14
-
15
- # A spreadsheet.
16
- #
17
- # Use methods in GoogleDrive::Session to get GoogleDrive::Spreadsheet object.
18
- class Spreadsheet < GoogleDrive::File
13
+ # A spreadsheet.
14
+ #
15
+ # Use methods in GoogleDrive::Session to get GoogleDrive::Spreadsheet object.
16
+ class Spreadsheet < GoogleDrive::File
17
+ include(Util)
19
18
 
20
- include(Util)
21
-
22
- SUPPORTED_EXPORT_FORMAT = Set.new(["xlsx", "csv", "pdf"])
19
+ SUPPORTED_EXPORT_FORMAT = Set.new(%w(xlsx csv pdf))
20
+
21
+ # Key of the spreadsheet.
22
+ def key
23
+ id
24
+ end
23
25
 
24
- # Key of the spreadsheet.
25
- def key
26
- return self.id
27
- end
28
-
29
- # URL of worksheet-based feed of the spreadsheet.
30
- def worksheets_feed_url
31
- return "https://spreadsheets.google.com/feeds/worksheets/%s/private/full" %
32
- self.id
33
- end
26
+ # URL of worksheet-based feed of the spreadsheet.
27
+ def worksheets_feed_url
28
+ 'https://spreadsheets.google.com/feeds/worksheets/%s/private/full' %
29
+ id
30
+ end
34
31
 
35
- # URL of feed used in the deprecated document list feed API.
36
- def document_feed_url
37
- return "https://docs.google.com/feeds/documents/private/full/" + CGI.escape(self.resource_id)
38
- end
32
+ # URL of feed used in the deprecated document list feed API.
33
+ def document_feed_url
34
+ 'https://docs.google.com/feeds/documents/private/full/' + CGI.escape(resource_id)
35
+ end
39
36
 
40
- # Spreadsheet feed URL of the spreadsheet.
41
- def spreadsheet_feed_url
42
- return "https://spreadsheets.google.com/feeds/spreadsheets/private/full/" + self.id
43
- end
44
-
45
- # Returns worksheets of the spreadsheet as array of GoogleDrive::Worksheet.
46
- def worksheets
47
- doc = @session.request(:get, self.worksheets_feed_url)
48
- if doc.root.name != "feed"
49
- raise(GoogleDrive::Error,
50
- "%s doesn't look like a worksheets feed URL because its root is not <feed>." %
51
- self.worksheets_feed_url)
52
- end
53
- return doc.css("entry").map(){ |e| Worksheet.new(@session, self, e) }.freeze
54
- end
55
-
56
- # Returns a GoogleDrive::Worksheet with the given title in the spreadsheet.
57
- #
58
- # Returns nil if not found. Returns the first one when multiple worksheets with the
59
- # title are found.
60
- def worksheet_by_title(title)
61
- return self.worksheets.find(){ |ws| ws.title == title }
62
- end
37
+ # Spreadsheet feed URL of the spreadsheet.
38
+ def spreadsheet_feed_url
39
+ 'https://spreadsheets.google.com/feeds/spreadsheets/private/full/' + id
40
+ end
63
41
 
64
- # Returns a GoogleDrive::Worksheet with the given gid.
65
- #
66
- # Returns nil if not found.
67
- def worksheet_by_gid(gid)
68
- gid = gid.to_s()
69
- return self.worksheets.find(){ |ws| ws.gid == gid }
70
- end
42
+ # Returns worksheets of the spreadsheet as array of GoogleDrive::Worksheet.
43
+ def worksheets
44
+ doc = @session.request(:get, worksheets_feed_url)
45
+ if doc.root.name != 'feed'
46
+ fail(GoogleDrive::Error,
47
+ "%s doesn't look like a worksheets feed URL because its root is not <feed>." %
48
+ worksheets_feed_url)
49
+ end
50
+ doc.css('entry').map { |e| Worksheet.new(@session, self, e) }.freeze
51
+ end
71
52
 
72
- # Adds a new worksheet to the spreadsheet. Returns added GoogleDrive::Worksheet.
73
- def add_worksheet(title, max_rows = 100, max_cols = 20)
74
- xml = <<-"EOS"
53
+ # Returns a GoogleDrive::Worksheet with the given title in the spreadsheet.
54
+ #
55
+ # Returns nil if not found. Returns the first one when multiple worksheets with the
56
+ # title are found.
57
+ def worksheet_by_title(title)
58
+ worksheets.find { |ws| ws.title == title }
59
+ end
60
+
61
+ # Returns a GoogleDrive::Worksheet with the given gid.
62
+ #
63
+ # Returns nil if not found.
64
+ def worksheet_by_gid(gid)
65
+ gid = gid.to_s
66
+ worksheets.find { |ws| ws.gid == gid }
67
+ end
68
+
69
+ # Adds a new worksheet to the spreadsheet. Returns added GoogleDrive::Worksheet.
70
+ def add_worksheet(title, max_rows = 100, max_cols = 20)
71
+ xml = <<-"EOS"
75
72
  <entry xmlns='http://www.w3.org/2005/Atom'
76
73
  xmlns:gs='http://schemas.google.com/spreadsheets/2006'>
77
74
  <title>#{h(title)}</title>
@@ -79,10 +76,8 @@ module GoogleDrive
79
76
  <gs:colCount>#{h(max_cols)}</gs:colCount>
80
77
  </entry>
81
78
  EOS
82
- doc = @session.request(:post, self.worksheets_feed_url, :data => xml)
83
- return Worksheet.new(@session, self, doc.root)
84
- end
85
-
79
+ doc = @session.request(:post, worksheets_feed_url, data: xml)
80
+ Worksheet.new(@session, self, doc.root)
86
81
  end
87
-
82
+ end
88
83
  end
@@ -1,182 +1,222 @@
1
1
  # Author: Hiroshi Ichikawa <http://gimite.net/>
2
2
  # The license of this source is "New BSD Licence"
3
3
 
4
- require "cgi"
4
+ require 'cgi'
5
5
 
6
- require "google/api_client"
6
+ module GoogleDrive
7
+ module Util #:nodoc:
8
+ EXT_TO_CONTENT_TYPE = {
9
+ '.csv' => 'text/csv',
10
+ '.tsv' => 'text/tab-separated-values',
11
+ '.tab' => 'text/tab-separated-values',
12
+ '.doc' => 'application/msword',
13
+ '.docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
14
+ '.ods' => 'application/x-vnd.oasis.opendocument.spreadsheet',
15
+ '.odt' => 'application/vnd.oasis.opendocument.text',
16
+ '.rtf' => 'application/rtf',
17
+ '.sxw' => 'application/vnd.sun.xml.writer',
18
+ '.txt' => 'text/plain',
19
+ '.xls' => 'application/vnd.ms-excel',
20
+ '.xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
21
+ '.pdf' => 'application/pdf',
22
+ '.png' => 'image/png',
23
+ '.ppt' => 'application/vnd.ms-powerpoint',
24
+ '.pps' => 'application/vnd.ms-powerpoint',
25
+ '.htm' => 'text/html',
26
+ '.html' => 'text/html',
27
+ '.zip' => 'application/zip',
28
+ '.swf' => 'application/x-shockwave-flash'
29
+ }
30
+
31
+ IMPORTABLE_CONTENT_TYPE_MAP = {
32
+ 'application/x-vnd.oasis.opendocument.presentation' => 'application/vnd.google-apps.presentation',
33
+ 'text/tab-separated-values' => 'application/vnd.google-apps.spreadsheet',
34
+ 'image/jpeg' => 'application/vnd.google-apps.document',
35
+ 'image/bmp' => 'application/vnd.google-apps.document',
36
+ 'image/gif' => 'application/vnd.google-apps.document',
37
+ 'application/vnd.ms-excel.sheet.macroenabled.12' => 'application/vnd.google-apps.spreadsheet',
38
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'application/vnd.google-apps.document',
39
+ 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'application/vnd.google-apps.presentation',
40
+ 'application/vnd.ms-word.template.macroenabled.12' => 'application/vnd.google-apps.document',
41
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'application/vnd.google-apps.document',
42
+ 'image/pjpeg' => 'application/vnd.google-apps.document',
43
+ 'application/vnd.google-apps.script+text/plain' => 'application/vnd.google-apps.script',
44
+ 'application/vnd.ms-excel' => 'application/vnd.google-apps.spreadsheet',
45
+ 'application/vnd.sun.xml.writer' => 'application/vnd.google-apps.document',
46
+ 'application/vnd.ms-word.document.macroenabled.12' => 'application/vnd.google-apps.document',
47
+ 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'application/vnd.google-apps.presentation',
48
+ 'text/rtf' => 'application/vnd.google-apps.document',
49
+ 'text/plain' => 'application/vnd.google-apps.document',
50
+ 'application/vnd.oasis.opendocument.spreadsheet' => 'application/vnd.google-apps.spreadsheet',
51
+ 'application/x-vnd.oasis.opendocument.spreadsheet' => 'application/vnd.google-apps.spreadsheet',
52
+ 'image/png' => 'application/vnd.google-apps.document',
53
+ 'application/x-vnd.oasis.opendocument.text' => 'application/vnd.google-apps.document',
54
+ 'application/msword' => 'application/vnd.google-apps.document',
55
+ 'application/pdf' => 'application/vnd.google-apps.document',
56
+ 'application/json' => 'application/vnd.google-apps.script',
57
+ 'application/x-msmetafile' => 'application/vnd.google-apps.drawing',
58
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'application/vnd.google-apps.spreadsheet',
59
+ 'application/vnd.ms-powerpoint' => 'application/vnd.google-apps.presentation',
60
+ 'application/vnd.ms-excel.template.macroenabled.12' => 'application/vnd.google-apps.spreadsheet',
61
+ 'image/x-bmp' => 'application/vnd.google-apps.document',
62
+ 'application/rtf' => 'application/vnd.google-apps.document',
63
+ 'application/vnd.openxmlformats-officedocument.presentationml.template' => 'application/vnd.google-apps.presentation',
64
+ 'image/x-png' => 'application/vnd.google-apps.document',
65
+ 'text/html' => 'application/vnd.google-apps.document',
66
+ 'application/vnd.oasis.opendocument.text' => 'application/vnd.google-apps.document',
67
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'application/vnd.google-apps.presentation',
68
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'application/vnd.google-apps.spreadsheet',
69
+ 'application/vnd.google-apps.script+json' => 'application/vnd.google-apps.script',
70
+ 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'application/vnd.google-apps.presentation',
71
+ 'application/vnd.ms-powerpoint.template.macroenabled.12' => 'application/vnd.google-apps.presentation',
72
+ 'text/csv' => 'application/vnd.google-apps.spreadsheet',
73
+ 'application/vnd.oasis.opendocument.presentation' => 'application/vnd.google-apps.presentation',
74
+ 'image/jpg' => 'application/vnd.google-apps.document',
75
+ 'text/richtext' => 'application/vnd.google-apps.document',
76
+ }
77
+
78
+ module_function
79
+
80
+ def encode_query(params)
81
+ params.map { |k, v| CGI.escape(k.to_s) + '=' + CGI.escape(v.to_s) }.join('&')
82
+ end
7
83
 
84
+ def concat_url(url, piece)
85
+ (url_base, url_query) = url.split(/\?/, 2)
86
+ (piece_base, piece_query) = piece.split(/\?/, 2)
87
+ result_query = [url_query, piece_query].select { |s| s && !s.empty? }.join('&')
88
+ (url_base || '') +
89
+ (piece_base || '') +
90
+ (result_query.empty? ? '' : "?#{result_query}")
91
+ end
8
92
 
9
- module GoogleDrive
10
-
11
- module Util #:nodoc:
12
-
13
- EXT_TO_CONTENT_TYPE = {
14
- ".csv" =>"text/csv",
15
- ".tsv" =>"text/tab-separated-values",
16
- ".tab" =>"text/tab-separated-values",
17
- ".doc" =>"application/msword",
18
- ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
19
- ".ods" =>"application/x-vnd.oasis.opendocument.spreadsheet",
20
- ".odt" =>"application/vnd.oasis.opendocument.text",
21
- ".rtf" =>"application/rtf",
22
- ".sxw" =>"application/vnd.sun.xml.writer",
23
- ".txt" =>"text/plain",
24
- ".xls" =>"application/vnd.ms-excel",
25
- ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
26
- ".pdf" =>"application/pdf",
27
- ".png" =>"image/png",
28
- ".ppt" =>"application/vnd.ms-powerpoint",
29
- ".pps" =>"application/vnd.ms-powerpoint",
30
- ".htm" =>"text/html",
31
- ".html" =>"text/html",
32
- ".zip" =>"application/zip",
33
- ".swf" =>"application/x-shockwave-flash",
34
- }
35
-
36
- module_function
37
-
38
- def encode_query(params)
39
- return params.map(){ |k, v| CGI.escape(k.to_s()) + "=" + CGI.escape(v.to_s()) }.join("&")
40
- end
41
-
42
- def concat_url(url, piece)
43
- (url_base, url_query) = url.split(/\?/, 2)
44
- (piece_base, piece_query) = piece.split(/\?/, 2)
45
- result_query = [url_query, piece_query].select(){ |s| s && !s.empty? }.join("&")
46
- return (url_base || "") +
47
- (piece_base || "") +
48
- (result_query.empty? ? "" : "?#{result_query}")
49
- end
93
+ def h(str)
94
+ # Should also escape "\n" to keep it in cell contents.
95
+ CGI.escapeHTML(str.to_s).gsub(/\n/, '&#x0a;')
96
+ end
50
97
 
51
- def h(str)
52
- # Should also escape "\n" to keep it in cell contents.
53
- return CGI.escapeHTML(str.to_s()).gsub(/\n/, '&#x0a;')
54
- end
55
-
56
- def construct_query(arg)
57
-
58
- case arg
59
-
60
- when String
61
- return arg
62
-
63
- when Array
64
- if arg[0].scan(/\?/).size != arg.size - 1
65
- raise(
66
- ArgumentError,
67
- "The number of placeholders doesn't match the number of arguments: %p" % [arg])
68
- end
69
- i = 1
70
- return arg[0].gsub(/\?/) do
71
- v = arg[i]
72
- i += 1
73
- case v
74
- when String
75
- "'%s'" % v.gsub(/['\\]/){ "\\" + $& }
76
- when Time
77
- "'%s'" % v.iso8601
78
- when TrueClass
79
- "true"
80
- when FalseClass
81
- "false"
82
- else
83
- raise(ArgumentError, "Expected String, Time, true or false, but got %p" % [v])
84
- end
85
- end
86
-
87
- else
88
- raise(ArgumentError, "Expected String or Array, but got %p" % [arg])
98
+ def construct_query(arg)
99
+ case arg
89
100
 
90
- end
101
+ when String
102
+ return arg
91
103
 
104
+ when Array
105
+ if arg[0].scan(/\?/).size != arg.size - 1
106
+ fail(
107
+ ArgumentError,
108
+ "The number of placeholders doesn't match the number of arguments: %p" % [arg])
92
109
  end
93
-
94
- def construct_and_query(args)
95
- return args.select(){ |a| a }.map(){ |a| "(%s)" % construct_query(a) }.join(" and ")
110
+ i = 1
111
+ return arg[0].gsub(/\?/) do
112
+ v = arg[i]
113
+ i += 1
114
+ case v
115
+ when String
116
+ "'%s'" % v.gsub(/['\\]/) { '\\' + $& }
117
+ when Time
118
+ "'%s'" % v.iso8601
119
+ when TrueClass
120
+ 'true'
121
+ when FalseClass
122
+ 'false'
123
+ else
124
+ fail(ArgumentError, 'Expected String, Time, true or false, but got %p' % [v])
125
+ end
96
126
  end
97
127
 
98
- def convert_params(params)
99
- str_params = {}
100
- for k, v in params
101
- str_params[k.to_s()] = v
102
- end
103
- old_terms = []
104
- new_params = {}
105
- for k, v in str_params
106
- case k
107
- when "q"
108
- new_params["q"] = construct_query(v)
109
- # Parameters in the old API.
110
- when "title"
111
- if str_params["title-exact"].to_s() == "true"
112
- old_terms.push(["title = ?", v])
113
- else
114
- old_terms.push(["title contains ?", v])
115
- end
116
- when "title-exact"
117
- # Skips it. It is handled above.
118
- when "opened-min"
119
- old_terms.push(["lastViewedByMeDate >= ?", v])
120
- when "opened-max"
121
- old_terms.push(["lastViewedByMeDate <= ?", v])
122
- when "edited-min"
123
- old_terms.push(["modifiedDate >= ?", v])
124
- when "edited-max"
125
- old_terms.push(["modifiedDate <= ?", v])
126
- when "owner"
127
- old_terms.push(["? in owners", v])
128
- when "writer"
129
- old_terms.push(["? in writers", v])
130
- when "reader"
131
- old_terms.push(["? in readers", v])
132
- when "showfolders"
133
- if v.to_s() == "false"
134
- old_terms.push("mimeType != 'application/vnd.google-apps.folder'")
135
- end
136
- when "showdeleted"
137
- if v.to_s() == "false"
138
- old_terms.push("trashed = false")
139
- end
140
- when "ocr", "targetLanguage", "sourceLanguage"
141
- raise(ArgumentError, "'%s' parameter is no longer supported." % k)
142
- else
143
- new_params[k] = v
144
- end
128
+ else
129
+ fail(ArgumentError, 'Expected String or Array, but got %p' % [arg])
130
+
131
+ end
132
+ end
133
+
134
+ def construct_and_query(args)
135
+ args.select { |a| a }.map { |a| '(%s)' % construct_query(a) }.join(' and ')
136
+ end
137
+
138
+ def convert_params(params)
139
+ str_params = {}
140
+ params.each do |k, v|
141
+ str_params[k.to_s] = v
142
+ end
143
+
144
+ old_terms = []
145
+ new_params = {}
146
+ str_params.each do |k, v|
147
+ case k
148
+ when 'q'
149
+ new_params[:q] = construct_query(v)
150
+
151
+ # Parameters in the old API.
152
+ when 'title'
153
+ if str_params['title-exact'].to_s == 'true'
154
+ old_terms.push(['name = ?', v])
155
+ else
156
+ old_terms.push(['name contains ?', v])
145
157
  end
146
- if !old_terms.empty?
147
- if new_params.has_key?("q")
148
- raise(ArgumentError, "Cannot specify both 'q' parameter and old query parameters.")
149
- else
150
- new_params["q"] = construct_and_query(old_terms)
151
- end
158
+ when 'title-exact'
159
+ # Skips it. It is handled above.
160
+ when 'opened-min'
161
+ old_terms.push(['lastViewedByMeDate >= ?', v])
162
+ when 'opened-max'
163
+ old_terms.push(['lastViewedByMeDate <= ?', v])
164
+ when 'edited-min'
165
+ old_terms.push(['modifiedDate >= ?', v])
166
+ when 'edited-max'
167
+ old_terms.push(['modifiedDate <= ?', v])
168
+ when 'owner'
169
+ old_terms.push(['? in owners', v])
170
+ when 'writer'
171
+ old_terms.push(['? in writers', v])
172
+ when 'reader'
173
+ old_terms.push(['? in readers', v])
174
+ when 'showfolders'
175
+ if v.to_s == 'false'
176
+ old_terms.push("mimeType != 'application/vnd.google-apps.folder'")
152
177
  end
153
- return new_params
178
+ when 'showdeleted'
179
+ old_terms.push('trashed = false') if v.to_s == 'false'
180
+ when 'ocr', 'targetLanguage', 'sourceLanguage'
181
+ fail(ArgumentError, "'%s' parameter is no longer supported." % k)
182
+ else
183
+ # e.g., 'pageToken' -> :page_token
184
+ new_key = k.
185
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
186
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
187
+ downcase.
188
+ intern
189
+ new_params[new_key] = v
154
190
  end
191
+ end
155
192
 
156
- def get_singleton_class(obj)
157
- class << obj
158
- return self
159
- end
193
+ unless old_terms.empty?
194
+ if new_params.key?(:q)
195
+ fail(ArgumentError, "Cannot specify both 'q' parameter and old query parameters.")
196
+ else
197
+ new_params[:q] = construct_and_query(old_terms)
160
198
  end
199
+ end
161
200
 
162
- def delegate_api_methods(obj, api_obj, exceptions = [])
163
- sc = get_singleton_class(obj)
164
- names = api_obj.class.keys.keys - exceptions.map(&:to_s)
165
- names.each() do |name|
166
- sc.__send__(:define_method, name) do
167
- api_obj.__send__(name)
168
- end
169
- end
170
- end
201
+ new_params
202
+ end
171
203
 
172
- def new_upload_io(path_or_io, params)
173
- content_type =
174
- params[:content_type] ||
175
- (params[:file_name] ? EXT_TO_CONTENT_TYPE[::File.extname(params[:file_name]).downcase] : nil) ||
176
- "application/octet-stream"
177
- return Google::APIClient::UploadIO.new(path_or_io, content_type)
204
+ def get_singleton_class(obj)
205
+ class << obj
206
+ return self
207
+ end
208
+ end
209
+
210
+ def delegate_api_methods(obj, api_obj, exceptions = [])
211
+ sc = get_singleton_class(obj)
212
+ names = api_obj.public_methods(false) - exceptions
213
+ names.each do |name|
214
+ if !(name.to_s =~ /=$/)
215
+ sc.__send__(:define_method, name) do
216
+ api_obj.__send__(name)
217
+ end
178
218
  end
179
-
219
+ end
180
220
  end
181
-
221
+ end
182
222
  end