google_drive 0.3.0 → 0.3.1
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.
- data/README.rdoc +2 -0
- data/lib/google_drive.rb +7 -1
- data/lib/google_drive/collection.rb +103 -17
- data/lib/google_drive/file.rb +51 -12
- data/lib/google_drive/list.rb +4 -0
- data/lib/google_drive/list_row.rb +4 -0
- data/lib/google_drive/oauth2_fetcher.rb +2 -2
- data/lib/google_drive/session.rb +34 -10
- data/lib/google_drive/spreadsheet.rb +1 -2
- data/lib/google_drive/util.rb +13 -1
- data/lib/google_drive/worksheet.rb +34 -4
- metadata +37 -11
data/README.rdoc
CHANGED
data/lib/google_drive.rb
CHANGED
@@ -29,7 +29,10 @@ module GoogleDrive
|
|
29
29
|
# :authorize_url => "/o/oauth2/auth")
|
30
30
|
# auth_url = client.auth_code.authorize_url(
|
31
31
|
# :redirect_uri => "http://example.com/",
|
32
|
-
#
|
32
|
+
# :scope =>
|
33
|
+
# "https://docs.google.com/feeds/ " +
|
34
|
+
# "https://docs.googleusercontent.com/ " +
|
35
|
+
# "https://spreadsheets.google.com/feeds/")
|
33
36
|
# # Redirect the user to auth_url and get authorization code from redirect URL.
|
34
37
|
# auth_token = client.auth_code.get_token(
|
35
38
|
# authorization_code, :redirect_uri => "http://example.com/")
|
@@ -42,6 +45,9 @@ module GoogleDrive
|
|
42
45
|
# access_token = access_token.refresh!
|
43
46
|
# session = GoogleDrive.login_with_oauth(access_token)
|
44
47
|
#
|
48
|
+
# If your app is not a Web app, use "urn:ietf:wg:oauth:2.0:oob" as redirect_url. Then
|
49
|
+
# authorization code is shown after authorization.
|
50
|
+
#
|
45
51
|
# OAuth1 code example:
|
46
52
|
#
|
47
53
|
# 1) First generate OAuth consumer object with key and secret for your site by registering site
|
@@ -8,21 +8,45 @@ require "google_drive/spreadsheet"
|
|
8
8
|
|
9
9
|
module GoogleDrive
|
10
10
|
|
11
|
-
# Use GoogleDrive::Session#
|
12
|
-
|
11
|
+
# Use GoogleDrive::Session#root_collection, GoogleDrive::Collection#subcollections,
|
12
|
+
# or GoogleDrive::Session#collection_by_url to get GoogleDrive::Collection object.
|
13
|
+
class Collection < GoogleDrive::File
|
13
14
|
|
14
15
|
include(Util)
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
#:nodoc:
|
18
|
+
ROOT_URL = "#{DOCS_BASE_URL}/folder%3Aroot"
|
19
|
+
|
20
|
+
alias collection_feed_url document_feed_url
|
21
|
+
|
22
|
+
def contents_url
|
23
|
+
if self.root?
|
24
|
+
# The root collection doesn't have document feed.
|
25
|
+
return concat_url(ROOT_URL, "/contents")
|
26
|
+
else
|
27
|
+
return self.document_feed_entry.css(
|
28
|
+
"content[type='application/atom+xml;type=feed']")[0]["src"]
|
29
|
+
end
|
19
30
|
end
|
20
31
|
|
21
|
-
|
32
|
+
# Title of the collection.
|
33
|
+
#
|
34
|
+
# Set <tt>params[:reload]</tt> to true to force reloading the title.
|
35
|
+
def title(params = {})
|
36
|
+
if self.root?
|
37
|
+
# The root collection doesn't have document feed.
|
38
|
+
return nil
|
39
|
+
else
|
40
|
+
return super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def resource_id
|
45
|
+
return self.root? ? nil : super
|
46
|
+
end
|
22
47
|
|
23
48
|
# Adds the given GoogleDrive::File to the collection.
|
24
49
|
def add(file)
|
25
|
-
contents_url = concat_url(@collection_feed_url, "/contents")
|
26
50
|
header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
|
27
51
|
xml = <<-"EOS"
|
28
52
|
<entry xmlns="http://www.w3.org/2005/Atom">
|
@@ -30,25 +54,87 @@ module GoogleDrive
|
|
30
54
|
</entry>
|
31
55
|
EOS
|
32
56
|
@session.request(
|
33
|
-
:post, contents_url, :data => xml, :header => header, :auth => :writely)
|
57
|
+
:post, self.contents_url, :data => xml, :header => header, :auth => :writely)
|
34
58
|
return nil
|
35
59
|
end
|
36
60
|
|
37
|
-
#
|
38
|
-
def
|
39
|
-
contents_url = concat_url(@collection_feed_url, "/contents")
|
61
|
+
# Creates a sub-collection with given title. Returns GoogleDrive::Collection object.
|
62
|
+
def create_subcollection(title)
|
40
63
|
header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
|
41
|
-
|
42
|
-
|
64
|
+
xml = <<-EOS
|
65
|
+
<entry xmlns="http://www.w3.org/2005/Atom">
|
66
|
+
<category scheme="http://schemas.google.com/g/2005#kind"
|
67
|
+
term="http://schemas.google.com/docs/2007#folder"/>
|
68
|
+
<title>#{h(title)}</title>
|
69
|
+
</entry>
|
70
|
+
EOS
|
71
|
+
doc = @session.request(
|
72
|
+
:post, contents_url, :data => xml, :header => header, :auth => :writely)
|
73
|
+
return @session.entry_element_to_file(doc)
|
43
74
|
end
|
44
|
-
|
75
|
+
|
76
|
+
# Removes the given GoogleDrive::File from the collection.
|
77
|
+
def remove(file)
|
78
|
+
url = to_v3_url("#{contents_url}/#{file.resource_id}")
|
79
|
+
@session.request(:delete, url, :auth => :writely, :header => {"If-Match" => "*"})
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns true if this is a root collection
|
83
|
+
def root?
|
84
|
+
self.document_feed_url == ROOT_URL
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns all the files (including spreadsheets, documents, subcollections) in the collection.
|
88
|
+
#
|
89
|
+
# You can specify query parameters described at
|
90
|
+
# https://developers.google.com/google-apps/documents-list/#getting_a_list_of_documents_and_files
|
91
|
+
#
|
92
|
+
# e.g.
|
93
|
+
#
|
94
|
+
# # Gets all the files in collection, including subcollections.
|
95
|
+
# collection.files
|
96
|
+
#
|
97
|
+
# # Gets only files with title "hoge".
|
98
|
+
# collection.files("title" => "hoge", "title-exact" => "true")
|
99
|
+
def files(params = {})
|
100
|
+
return files_with_type(nil, params)
|
101
|
+
end
|
102
|
+
|
103
|
+
alias contents files
|
104
|
+
|
45
105
|
# Returns all the spreadsheets in the collection.
|
46
|
-
def spreadsheets
|
47
|
-
return
|
106
|
+
def spreadsheets(params = {})
|
107
|
+
return files_with_type("spreadsheet", params)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns all the Google Docs documents in the collection.
|
111
|
+
def documents(params = {})
|
112
|
+
return files_with_type("document", params)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns all its subcollections.
|
116
|
+
def subcollections(params = {})
|
117
|
+
return files_with_type("folder", params)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns its subcollection whose title exactly matches +title+ as GoogleDrive::Collection.
|
121
|
+
# Returns nil if not found. If multiple collections with the +title+ are found, returns
|
122
|
+
# one of them.
|
123
|
+
def subcollection_by_title(title)
|
124
|
+
return subcollections("title" => title, "title-exact" => "true")[0]
|
48
125
|
end
|
49
126
|
|
50
|
-
|
127
|
+
private
|
51
128
|
|
129
|
+
def files_with_type(type, params = {})
|
130
|
+
contents_url = self.contents_url
|
131
|
+
contents_url = concat_url(contents_url, "/-/#{type}") if type
|
132
|
+
contents_url = concat_url(contents_url, "?" + encode_query(params))
|
133
|
+
header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
|
134
|
+
doc = @session.request(:get, contents_url, :header => header, :auth => :writely)
|
135
|
+
return doc.css("feed > entry").map(){ |e| @session.entry_element_to_file(e) }
|
136
|
+
end
|
137
|
+
|
52
138
|
end
|
53
139
|
|
54
140
|
end
|
data/lib/google_drive/file.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
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
5
|
require "stringio"
|
5
6
|
|
6
7
|
require "google_drive/util"
|
@@ -17,11 +18,24 @@ module GoogleDrive
|
|
17
18
|
|
18
19
|
include(Util)
|
19
20
|
|
20
|
-
def initialize(session,
|
21
|
+
def initialize(session, entry_or_url) #:nodoc:
|
21
22
|
@session = session
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
if !entry_or_url
|
24
|
+
# TODO Delete this after editing spreadsheet.rb.
|
25
|
+
@document_feed_entry = nil
|
26
|
+
@document_feed_url = entry_or_url
|
27
|
+
elsif entry_or_url.is_a?(String)
|
28
|
+
@document_feed_entry = nil
|
29
|
+
@document_feed_url = entry_or_url
|
30
|
+
else
|
31
|
+
@document_feed_entry = entry_or_url
|
32
|
+
# This is usually equal to the URL in <link rel="self">. But the URL in
|
33
|
+
# <link rel="self"> in collection feed is e.g.
|
34
|
+
# https://docs.google.com/feeds/default/private/full/folder%3Aroot/contents/folder%3Axxx
|
35
|
+
# and deletion of the URL doesn't delete the file itself.
|
36
|
+
# So we construct the URL here using resource ID instead.
|
37
|
+
@document_feed_url = "%s/%s" % [DOCS_BASE_URL, CGI.escape(self.resource_id)]
|
38
|
+
end
|
25
39
|
@acl = nil
|
26
40
|
end
|
27
41
|
|
@@ -29,10 +43,32 @@ module GoogleDrive
|
|
29
43
|
attr_reader(:document_feed_url)
|
30
44
|
|
31
45
|
# <entry> element of document list feed as Nokogiri::XML::Element.
|
32
|
-
|
33
|
-
|
46
|
+
#
|
47
|
+
# Set <tt>params[:reload]</tt> to true to force reloading the feed.
|
48
|
+
def document_feed_entry(params = {})
|
49
|
+
if !@document_feed_entry || params[:reload]
|
50
|
+
@document_feed_entry =
|
51
|
+
@session.request(:get, self.document_feed_url, :auth => :writely).css("entry")[0]
|
52
|
+
end
|
53
|
+
return @document_feed_entry
|
54
|
+
end
|
55
|
+
|
56
|
+
# Resource ID.
|
57
|
+
def resource_id
|
58
|
+
return self.document_feed_entry.css("gd|resourceId").text
|
59
|
+
end
|
60
|
+
|
61
|
+
# The type of resourse. e.g. "document", "spreadsheet", "folder"
|
62
|
+
def resource_type
|
63
|
+
return self.resource_id.split(/:/)[0]
|
64
|
+
end
|
65
|
+
|
34
66
|
# Title of the file.
|
35
|
-
|
67
|
+
#
|
68
|
+
# Set <tt>params[:reload]</tt> to true to force reloading the title.
|
69
|
+
def title(params = {})
|
70
|
+
return document_feed_entry(params).css("title").text
|
71
|
+
end
|
36
72
|
|
37
73
|
# URL to view/edit the file in a Web browser.
|
38
74
|
#
|
@@ -50,7 +86,7 @@ module GoogleDrive
|
|
50
86
|
return orig_acl_feed_url
|
51
87
|
when %r{^https?://docs.google.com/feeds/acl/private/full/([^\?]*)(\?.*)?$}
|
52
88
|
# URL of old API version. Converts to v3 URL.
|
53
|
-
return "
|
89
|
+
return "#{DOCS_BASE_URL}/#{$1}/acl"
|
54
90
|
else
|
55
91
|
raise(GoogleDrive::Error,
|
56
92
|
"ACL feed URL is in unknown format: #{orig_acl_feed_url}")
|
@@ -149,8 +185,9 @@ module GoogleDrive
|
|
149
185
|
# If +permanent+ is +false+, moves the file to the trash.
|
150
186
|
# If +permanent+ is +true+, deletes the file permanently.
|
151
187
|
def delete(permanent = false)
|
152
|
-
|
153
|
-
|
188
|
+
url = to_v3_url(self.document_feed_url)
|
189
|
+
url = concat_url(url, "?delete=true") if permanent
|
190
|
+
@session.request(:delete, url,
|
154
191
|
:auth => :writely, :header => {"If-Match" => "*"})
|
155
192
|
end
|
156
193
|
|
@@ -180,7 +217,7 @@ module GoogleDrive
|
|
180
217
|
# With the object, you can see and modify people who can access the file.
|
181
218
|
# Modifications take effect immediately.
|
182
219
|
#
|
183
|
-
# Set <tt>params[:reload]</tt> to true to force reloading the
|
220
|
+
# Set <tt>params[:reload]</tt> to true to force reloading the data.
|
184
221
|
#
|
185
222
|
# e.g.
|
186
223
|
# # Dumps people who have access:
|
@@ -209,7 +246,9 @@ module GoogleDrive
|
|
209
246
|
end
|
210
247
|
|
211
248
|
def inspect
|
212
|
-
|
249
|
+
fields = {:document_feed_url => self.document_feed_url}
|
250
|
+
fields[:title] = self.title if @document_feed_entry
|
251
|
+
return "\#<%p %s>" % [self.class, fields.map(){ |k, v| "%s=%p" % [k, v] }.join(", ")]
|
213
252
|
end
|
214
253
|
|
215
254
|
end
|
data/lib/google_drive/list.rb
CHANGED
@@ -97,6 +97,10 @@ module GoogleDrive
|
|
97
97
|
return @worksheet[index + 2, key_to_col(key)]
|
98
98
|
end
|
99
99
|
|
100
|
+
def numeric_value(index, key) #:nodoc:
|
101
|
+
return @worksheet.numeric_value(index + 2, key_to_col(key))
|
102
|
+
end
|
103
|
+
|
100
104
|
def set(index, key, value) #:nodoc:
|
101
105
|
@worksheet[index + 2, key_to_col(key)] = value
|
102
106
|
end
|
@@ -35,9 +35,9 @@ module GoogleDrive
|
|
35
35
|
|
36
36
|
def request_raw(method, url, data, extra_header, auth)
|
37
37
|
if method == :delete || method == :get
|
38
|
-
raw_res = @oauth2_token.request(method, url, {:
|
38
|
+
raw_res = @oauth2_token.request(method, url, {:headers => extra_header})
|
39
39
|
else
|
40
|
-
raw_res = @oauth2_token.request(method, url, {:
|
40
|
+
raw_res = @oauth2_token.request(method, url, {:headers => extra_header, :body => data})
|
41
41
|
end
|
42
42
|
return Response.new(raw_res)
|
43
43
|
end
|
data/lib/google_drive/session.rb
CHANGED
@@ -112,12 +112,14 @@ module GoogleDrive
|
|
112
112
|
# You can specify query parameters described at
|
113
113
|
# https://developers.google.com/google-apps/documents-list/#getting_a_list_of_documents_and_files
|
114
114
|
#
|
115
|
+
# files doesn't return collections unless "showfolders" => true is specified.
|
116
|
+
#
|
115
117
|
# e.g.
|
116
118
|
# session.files
|
117
119
|
# session.files("title" => "hoge", "title-exact" => "true")
|
118
120
|
def files(params = {})
|
119
121
|
url = concat_url(
|
120
|
-
"
|
122
|
+
"#{DOCS_BASE_URL}?v=3", "?" + encode_query(params))
|
121
123
|
doc = request(:get, url, :auth => :writely)
|
122
124
|
return doc.css("feed > entry").map(){ |e| entry_element_to_file(e) }
|
123
125
|
end
|
@@ -200,7 +202,25 @@ module GoogleDrive
|
|
200
202
|
def worksheet_by_url(url)
|
201
203
|
return Worksheet.new(self, nil, url)
|
202
204
|
end
|
203
|
-
|
205
|
+
|
206
|
+
# Returns the root collection.
|
207
|
+
def root_collection
|
208
|
+
return Collection.new(self, Collection::ROOT_URL)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Returns the top-level collections (direct children of the root collection).
|
212
|
+
def collections
|
213
|
+
return self.root_collection.subcollections
|
214
|
+
end
|
215
|
+
|
216
|
+
# Returns a top-level collection whose title exactly matches +title+ as
|
217
|
+
# GoogleDrive::Collection.
|
218
|
+
# Returns nil if not found. If multiple collections with the +title+ are found, returns
|
219
|
+
# one of them.
|
220
|
+
def collection_by_title(title)
|
221
|
+
return self.root_collection.subcollection_by_title(title)
|
222
|
+
end
|
223
|
+
|
204
224
|
# Returns GoogleDrive::Collection with given +url+.
|
205
225
|
# You must specify either of:
|
206
226
|
# - URL of the page you get when you go to https://docs.google.com/ with your browser and
|
@@ -219,7 +239,7 @@ module GoogleDrive
|
|
219
239
|
if ["docs.google.com", "drive.google.com"].include?(uri.host) &&
|
220
240
|
uri.fragment =~ /^folders\/(.+)$/
|
221
241
|
# Looks like a URL of human-readable collection page. Converts to collection feed URL.
|
222
|
-
url = "
|
242
|
+
url = "#{DOCS_BASE_URL}/folder%3A#{$1}"
|
223
243
|
end
|
224
244
|
return Collection.new(self, url)
|
225
245
|
end
|
@@ -289,7 +309,7 @@ module GoogleDrive
|
|
289
309
|
# Uploads a file. Reads content from +io+.
|
290
310
|
# Returns a GoogleSpreadsheet::File object.
|
291
311
|
def upload_from_io(io, title = "Untitled", params = {})
|
292
|
-
doc = request(:get, "
|
312
|
+
doc = request(:get, "#{DOCS_BASE_URL}?v=3",
|
293
313
|
:auth => :writely)
|
294
314
|
initial_url = doc.css(
|
295
315
|
"link[rel='http://schemas.google.com/g/2005#resumable-create-media']")[0]["href"]
|
@@ -352,13 +372,17 @@ module GoogleDrive
|
|
352
372
|
end
|
353
373
|
|
354
374
|
def entry_element_to_file(entry) #:nodoc:
|
375
|
+
type, resource_id = entry.css("gd|resourceId").text.split(/:/)
|
355
376
|
title = entry.css("title").text
|
356
|
-
|
357
|
-
"
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
377
|
+
case type
|
378
|
+
when "folder"
|
379
|
+
return Collection.new(self, entry)
|
380
|
+
when "spreadsheet"
|
381
|
+
worksheets_feed_link = entry.css(
|
382
|
+
"link[rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']")[0]
|
383
|
+
return Spreadsheet.new(self, worksheets_feed_link["href"], title)
|
384
|
+
else
|
385
|
+
return GoogleDrive::File.new(self, entry)
|
362
386
|
end
|
363
387
|
end
|
364
388
|
|
@@ -103,7 +103,6 @@ module GoogleDrive
|
|
103
103
|
# Creates copy of this spreadsheet with the given title.
|
104
104
|
def duplicate(new_title = nil)
|
105
105
|
new_title ||= (self.title ? "Copy of " + self.title : "Untitled")
|
106
|
-
post_url = "https://docs.google.com/feeds/default/private/full/"
|
107
106
|
header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
|
108
107
|
xml = <<-"EOS"
|
109
108
|
<entry xmlns='http://www.w3.org/2005/Atom'>
|
@@ -112,7 +111,7 @@ module GoogleDrive
|
|
112
111
|
</entry>
|
113
112
|
EOS
|
114
113
|
doc = @session.request(
|
115
|
-
:post,
|
114
|
+
:post, DOCS_BASE_URL, :data => xml, :header => header, :auth => :writely)
|
116
115
|
ss_url = doc.css(
|
117
116
|
"link[rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']")[0]["href"]
|
118
117
|
return Spreadsheet.new(@session, ss_url, new_title)
|
data/lib/google_drive/util.rb
CHANGED
@@ -7,6 +7,9 @@ require "cgi"
|
|
7
7
|
module GoogleDrive
|
8
8
|
|
9
9
|
module Util #:nodoc:
|
10
|
+
|
11
|
+
# The beginning of Doc List API URL that is used in all requests (version 3).
|
12
|
+
DOCS_BASE_URL = "https://docs.google.com/feeds/default/private/full"
|
10
13
|
|
11
14
|
EXT_TO_CONTENT_TYPE = {
|
12
15
|
".csv" =>"text/csv",
|
@@ -45,7 +48,16 @@ module GoogleDrive
|
|
45
48
|
(piece_base || "") +
|
46
49
|
(result_query.empty? ? "" : "?#{result_query}")
|
47
50
|
end
|
48
|
-
|
51
|
+
|
52
|
+
# Returns a URL with added version parameter ("?v=3") if needed.
|
53
|
+
def to_v3_url(url)
|
54
|
+
if url =~ %r{docs.google.com/feeds/default/private/} && !(url =~ /[?&]v=3/)
|
55
|
+
return concat_url(url, "?v=3")
|
56
|
+
else
|
57
|
+
return url
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
49
61
|
def h(str)
|
50
62
|
return CGI.escapeHTML(str.to_s())
|
51
63
|
end
|
@@ -26,6 +26,7 @@ module GoogleDrive
|
|
26
26
|
|
27
27
|
@cells = nil
|
28
28
|
@input_values = nil
|
29
|
+
@numeric_values = nil
|
29
30
|
@modified = Set.new()
|
30
31
|
@list = nil
|
31
32
|
|
@@ -86,6 +87,7 @@ module GoogleDrive
|
|
86
87
|
reload() if !@cells
|
87
88
|
@cells[[row, col]] = value
|
88
89
|
@input_values[[row, col]] = value
|
90
|
+
@numeric_values[[row, col]] = nil
|
89
91
|
@modified.add([row, col])
|
90
92
|
self.max_rows = row if row > @max_rows
|
91
93
|
self.max_cols = col if col > @max_cols
|
@@ -116,6 +118,25 @@ module GoogleDrive
|
|
116
118
|
return @input_values[[row, col]] || ""
|
117
119
|
end
|
118
120
|
|
121
|
+
# Returns the numeric value of the cell. Arguments must be either
|
122
|
+
# (row number, column number) or cell name. Top-left cell is [1, 1].
|
123
|
+
#
|
124
|
+
# e.g.
|
125
|
+
# worksheet[1, 3] #=> "3,0" # it depends on locale, currency...
|
126
|
+
# worksheet.numeric_value(1, 3) #=> 3.0
|
127
|
+
#
|
128
|
+
# Returns nil if the cell is empty or contains non-number.
|
129
|
+
#
|
130
|
+
# If you modify the cell, its numeric_value is nil until you call save() and reload().
|
131
|
+
#
|
132
|
+
# For details, see:
|
133
|
+
# https://developers.google.com/google-apps/spreadsheets/#working_with_cell-based_feeds
|
134
|
+
def numeric_value(*args)
|
135
|
+
(row, col) = parse_cell_args(args)
|
136
|
+
reload() if !@cells
|
137
|
+
return @numeric_values[[row, col]]
|
138
|
+
end
|
139
|
+
|
119
140
|
# Row number of the bottom-most non-empty row.
|
120
141
|
def num_rows
|
121
142
|
reload() if !@cells
|
@@ -176,8 +197,9 @@ module GoogleDrive
|
|
176
197
|
end
|
177
198
|
|
178
199
|
# An array of spreadsheet rows. Each row contains an array of
|
179
|
-
# columns. Note that resulting array is 0-origin so
|
180
|
-
#
|
200
|
+
# columns. Note that resulting array is 0-origin so:
|
201
|
+
#
|
202
|
+
# worksheet.rows[0][0] == worksheet[1, 1]
|
181
203
|
def rows(skip = 0)
|
182
204
|
nc = self.num_cols
|
183
205
|
result = ((1 + skip)..self.num_rows).map() do |row|
|
@@ -197,12 +219,15 @@ module GoogleDrive
|
|
197
219
|
|
198
220
|
@cells = {}
|
199
221
|
@input_values = {}
|
222
|
+
@numeric_values = {}
|
200
223
|
doc.css("feed > entry").each() do |entry|
|
201
224
|
cell = entry.css("gs|cell")[0]
|
202
225
|
row = cell["row"].to_i()
|
203
226
|
col = cell["col"].to_i()
|
204
227
|
@cells[[row, col]] = cell.inner_text
|
205
228
|
@input_values[[row, col]] = cell["inputValue"]
|
229
|
+
numeric_value = cell["numericValue"]
|
230
|
+
@numeric_values[[row, col]] = numeric_value ? numeric_value.to_f() : nil
|
206
231
|
end
|
207
232
|
@modified.clear()
|
208
233
|
@meta_modified = false
|
@@ -433,10 +458,15 @@ module GoogleDrive
|
|
433
458
|
if args.size == 1 && args[0].is_a?(String)
|
434
459
|
return cell_name_to_row_col(args[0])
|
435
460
|
elsif args.size == 2 && args[0].is_a?(Integer) && args[1].is_a?(Integer)
|
436
|
-
|
461
|
+
if args[0] >= 1 && args[1] >= 1
|
462
|
+
return args
|
463
|
+
else
|
464
|
+
raise(ArgumentError,
|
465
|
+
"Row/col must be >= 1 (1-origin), but are %d/%d" % [args[0], args[1]])
|
466
|
+
end
|
437
467
|
else
|
438
468
|
raise(ArgumentError,
|
439
|
-
"Arguments must be either one String or two Integer's, but are %p" % args)
|
469
|
+
"Arguments must be either one String or two Integer's, but are %p" % [args])
|
440
470
|
end
|
441
471
|
end
|
442
472
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google_drive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -27,10 +27,21 @@ dependencies:
|
|
27
27
|
version: 1.5.2
|
28
28
|
type: :runtime
|
29
29
|
prerelease: false
|
30
|
-
version_requirements:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ! '>='
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 1.4.4
|
36
|
+
- - ! '!='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 1.5.1
|
39
|
+
- - ! '!='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 1.5.2
|
31
42
|
- !ruby/object:Gem::Dependency
|
32
43
|
name: oauth
|
33
|
-
requirement:
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
34
45
|
none: false
|
35
46
|
requirements:
|
36
47
|
- - ! '>='
|
@@ -38,10 +49,15 @@ dependencies:
|
|
38
49
|
version: 0.3.6
|
39
50
|
type: :runtime
|
40
51
|
prerelease: false
|
41
|
-
version_requirements:
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 0.3.6
|
42
58
|
- !ruby/object:Gem::Dependency
|
43
59
|
name: oauth2
|
44
|
-
requirement:
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
45
61
|
none: false
|
46
62
|
requirements:
|
47
63
|
- - ! '>='
|
@@ -49,10 +65,15 @@ dependencies:
|
|
49
65
|
version: 0.5.0
|
50
66
|
type: :runtime
|
51
67
|
prerelease: false
|
52
|
-
version_requirements:
|
68
|
+
version_requirements: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.5.0
|
53
74
|
- !ruby/object:Gem::Dependency
|
54
75
|
name: rake
|
55
|
-
requirement:
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
56
77
|
none: false
|
57
78
|
requirements:
|
58
79
|
- - ! '>='
|
@@ -60,7 +81,12 @@ dependencies:
|
|
60
81
|
version: 0.8.0
|
61
82
|
type: :development
|
62
83
|
prerelease: false
|
63
|
-
version_requirements:
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.8.0
|
64
90
|
description: A library to read/write files/spreadsheets in Google Drive/Docs.
|
65
91
|
email:
|
66
92
|
- gimite+github@gmail.com
|
@@ -114,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
140
|
version: '0'
|
115
141
|
requirements: []
|
116
142
|
rubyforge_project:
|
117
|
-
rubygems_version: 1.8.
|
143
|
+
rubygems_version: 1.8.23
|
118
144
|
signing_key:
|
119
145
|
specification_version: 3
|
120
146
|
summary: A library to read/write files/spreadsheets in Google Drive/Docs.
|