google-spreadsheet-ruby 0.0.8 → 0.0.9
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 +63 -61
- data/lib/google_spreadsheet.rb +85 -75
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -1,61 +1,63 @@
|
|
1
|
-
This is a Ruby 1.8/1.9 library to read/write Google Spreadsheet.
|
2
|
-
|
3
|
-
|
4
|
-
= How to install
|
5
|
-
|
6
|
-
$ gem sources -a http://
|
7
|
-
$ sudo gem install
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
ws
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
1
|
+
This is a Ruby 1.8/1.9 library to read/write Google Spreadsheet.
|
2
|
+
|
3
|
+
|
4
|
+
= How to install
|
5
|
+
|
6
|
+
$ gem sources -a http://gemcutter.org
|
7
|
+
$ sudo gem install google-spreadsheet-ruby
|
8
|
+
|
9
|
+
Note that gimite-google-spreadsheet-ruby at gems.github.com is no longer updated, because github stopped hosting it.
|
10
|
+
|
11
|
+
|
12
|
+
= How to use
|
13
|
+
|
14
|
+
Example:
|
15
|
+
|
16
|
+
require "rubygems"
|
17
|
+
require "google_spreadsheet"
|
18
|
+
|
19
|
+
# Logs in.
|
20
|
+
session = GoogleSpreadsheet.login("username@gmail.com", "mypassword")
|
21
|
+
|
22
|
+
# First worksheet of http://spreadsheets.google.com/ccc?key=pz7XtlQC-PYx-jrVMJErTcg&hl=en
|
23
|
+
ws = session.spreadsheet_by_key("pz7XtlQC-PYx-jrVMJErTcg").worksheets[0]
|
24
|
+
|
25
|
+
# Gets content of A2 cell.
|
26
|
+
p ws[2, 1] #==> "hoge"
|
27
|
+
|
28
|
+
# Changes content of cells. Changes are not sent to the server until you call ws.save().
|
29
|
+
ws[2, 1] = "foo"
|
30
|
+
ws[2, 2] = "bar"
|
31
|
+
ws.save()
|
32
|
+
|
33
|
+
# Dumps all cells.
|
34
|
+
for row in 1..ws.num_rows
|
35
|
+
for col in 1..ws.num_cols
|
36
|
+
p ws[row, col]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Yet another way to do so.
|
41
|
+
p ws.rows #==> [["fuga", ""], ["foo", "bar]]
|
42
|
+
|
43
|
+
# Reloads the worksheet to get changes by other clients.
|
44
|
+
ws.reload()
|
45
|
+
|
46
|
+
API document: http://gimite.net/gimite/rubymess/google-spreadsheet-ruby/
|
47
|
+
|
48
|
+
|
49
|
+
= Source code
|
50
|
+
|
51
|
+
http://github.com/gimite/google-spreadsheet-ruby/tree/master
|
52
|
+
|
53
|
+
The license of this source is "New BSD Licence"
|
54
|
+
|
55
|
+
|
56
|
+
= Supported environments
|
57
|
+
|
58
|
+
Ruby 1.8.x and Ruby 1.9.x. Checked with Ruby 1.8.7 and Ruby 1.9.1.
|
59
|
+
|
60
|
+
|
61
|
+
= Author
|
62
|
+
|
63
|
+
Hiroshi Ichikawa - http://gimite.net/en/index.php?Contact
|
data/lib/google_spreadsheet.rb
CHANGED
@@ -6,6 +6,7 @@ require "set"
|
|
6
6
|
require "net/https"
|
7
7
|
require "open-uri"
|
8
8
|
require "cgi"
|
9
|
+
require "uri"
|
9
10
|
require "rubygems"
|
10
11
|
require "hpricot"
|
11
12
|
Net::HTTP.version_1_2
|
@@ -142,39 +143,12 @@ module GoogleSpreadsheet
|
|
142
143
|
# When this function returns +true+, it tries again.
|
143
144
|
attr_accessor :on_auth_fail
|
144
145
|
|
145
|
-
def
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
return http_request(:get, url, nil, auth)
|
152
|
-
end
|
153
|
-
|
154
|
-
def post(url, data, auth = :wise) #:nodoc:
|
155
|
-
response = http_request(:post, url, data, auth, {"Content-Type" => "application/atom+xml"})
|
156
|
-
return Hpricot.XML(response)
|
157
|
-
end
|
158
|
-
|
159
|
-
def put(url, data, auth = :wise) #:nodoc:
|
160
|
-
response = http_request(:put, url, data, auth, {"Content-Type" => "application/atom+xml"})
|
161
|
-
return Hpricot.XML(response)
|
162
|
-
end
|
163
|
-
|
164
|
-
def delete(url, auth = :wise) #:nodoc:
|
165
|
-
response = http_request(:delete, url, nil, auth, {"Content-Type" => "application/atom+xml"})
|
166
|
-
return Hpricot.XML(response)
|
167
|
-
end
|
168
|
-
|
169
|
-
def upload(url, ods_file, name)
|
170
|
-
response = http_request(:post, url, ods_file, :writely,
|
171
|
-
{"Content-Type" => "application/x-vnd.oasis.opendocument.spreadsheet",
|
172
|
-
"Slug" => name})
|
173
|
-
return Hpricot.XML(response)
|
174
|
-
end
|
175
|
-
|
176
|
-
def auth_header auth #:nodoc:
|
177
|
-
return {"Authorization" => "GoogleLogin auth=#{@auth_tokens[auth]}"}
|
146
|
+
def auth_header(auth) #:nodoc:
|
147
|
+
if auth == :none
|
148
|
+
return {}
|
149
|
+
else
|
150
|
+
return {"Authorization" => "GoogleLogin auth=#{@auth_tokens[auth]}"}
|
151
|
+
end
|
178
152
|
end
|
179
153
|
|
180
154
|
# Returns list of spreadsheets for the user as array of GoogleSpreadsheet::Spreadsheet.
|
@@ -186,7 +160,7 @@ module GoogleSpreadsheet
|
|
186
160
|
# session.spreadsheets("title" => "hoge")
|
187
161
|
def spreadsheets(params = {})
|
188
162
|
query = encode_query(params)
|
189
|
-
doc = get
|
163
|
+
doc = request(:get, "http://spreadsheets.google.com/feeds/spreadsheets/private/full?#{query}")
|
190
164
|
result = []
|
191
165
|
for entry in doc.search("entry")
|
192
166
|
title = as_utf8(entry.search("title").text)
|
@@ -245,45 +219,38 @@ module GoogleSpreadsheet
|
|
245
219
|
def create_spreadsheet(
|
246
220
|
title = "Untitled",
|
247
221
|
feed_url = "http://docs.google.com/feeds/documents/private/full")
|
248
|
-
|
249
222
|
xml = <<-"EOS"
|
250
223
|
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:docs="http://schemas.google.com/docs/2007">
|
251
224
|
<atom:category scheme="http://schemas.google.com/g/2005#kind"
|
252
225
|
term="http://schemas.google.com/docs/2007#spreadsheet" label="spreadsheet"/>
|
253
|
-
<atom:title>#{title}</atom:title>
|
226
|
+
<atom:title>#{h(title)}</atom:title>
|
254
227
|
</atom:entry>
|
255
228
|
EOS
|
256
229
|
|
257
|
-
doc = post
|
230
|
+
doc = request(:post, feed_url, :data => xml, :auth => :writely)
|
258
231
|
ss_url = as_utf8(doc.search(
|
259
232
|
"link[@rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']")[0]["href"])
|
260
233
|
return Spreadsheet.new(self, ss_url, title)
|
261
234
|
end
|
262
235
|
|
263
|
-
|
264
|
-
|
265
|
-
def authenticate(mail, password, auth)
|
266
|
-
params = {
|
267
|
-
"accountType" => "HOSTED_OR_GOOGLE",
|
268
|
-
"Email" => mail,
|
269
|
-
"Passwd" => password,
|
270
|
-
"service" => auth.to_s(),
|
271
|
-
"source" => "Gimite-RubyGoogleSpreadsheet-1.00",
|
272
|
-
}
|
273
|
-
response = http_request(:post,
|
274
|
-
"https://www.google.com/accounts/ClientLogin", encode_query(params), nil)
|
275
|
-
@auth_tokens[auth] = response.slice(/^Auth=(.*)$/, 1)
|
276
|
-
end
|
277
|
-
|
278
|
-
def http_request(method, url, data, auth, add_header = {})
|
236
|
+
def request(method, url, params = {}) #:nodoc:
|
279
237
|
uri = URI.parse(url)
|
238
|
+
data = params[:data]
|
239
|
+
auth = params[:auth] || :wise
|
240
|
+
if params[:header]
|
241
|
+
add_header = params[:header]
|
242
|
+
else
|
243
|
+
add_header = data ? {"Content-Type" => "application/atom+xml"} : {}
|
244
|
+
end
|
245
|
+
response_type = params[:response_type] || :xml
|
246
|
+
|
280
247
|
http = Net::HTTP.new(uri.host, uri.port)
|
281
248
|
http.use_ssl = uri.scheme == "https"
|
282
249
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
283
250
|
http.start() do
|
284
251
|
while true
|
285
252
|
path = uri.path + (uri.query ? "?#{uri.query}" : "")
|
286
|
-
header =
|
253
|
+
header = auth_header(auth).merge(add_header)
|
287
254
|
if method == :delete || method == :get
|
288
255
|
response = http.__send__(method, path, header)
|
289
256
|
else
|
@@ -298,11 +265,34 @@ module GoogleSpreadsheet
|
|
298
265
|
"Response code #{response.code} for #{method} #{url}: " +
|
299
266
|
CGI.unescapeHTML(response.body))
|
300
267
|
end
|
301
|
-
|
268
|
+
case response_type
|
269
|
+
when :xml
|
270
|
+
return Hpricot.XML(response.body)
|
271
|
+
when :raw
|
272
|
+
return response.body
|
273
|
+
else
|
274
|
+
raise("unknown params[:response_type]: %s" % response_type)
|
275
|
+
end
|
302
276
|
end
|
303
277
|
end
|
304
278
|
end
|
305
279
|
|
280
|
+
private
|
281
|
+
|
282
|
+
def authenticate(mail, password, auth)
|
283
|
+
params = {
|
284
|
+
"accountType" => "HOSTED_OR_GOOGLE",
|
285
|
+
"Email" => mail,
|
286
|
+
"Passwd" => password,
|
287
|
+
"service" => auth.to_s(),
|
288
|
+
"source" => "Gimite-RubyGoogleSpreadsheet-1.00",
|
289
|
+
}
|
290
|
+
response = request(:post,
|
291
|
+
"https://www.google.com/accounts/ClientLogin",
|
292
|
+
:data => encode_query(params), :auth => :none, :header => {}, :response_type => :raw)
|
293
|
+
@auth_tokens[auth] = response.slice(/^Auth=(.*)$/, 1)
|
294
|
+
end
|
295
|
+
|
306
296
|
end
|
307
297
|
|
308
298
|
|
@@ -338,23 +328,40 @@ module GoogleSpreadsheet
|
|
338
328
|
def tables_feed_url
|
339
329
|
return "http://spreadsheets.google.com/feeds/#{self.key}/tables"
|
340
330
|
end
|
341
|
-
|
331
|
+
|
332
|
+
# URL of feed used in document list feed API.
|
333
|
+
def document_feed_url
|
334
|
+
return "http://docs.google.com/feeds/documents/private/full/spreadsheet%3A#{self.key}"
|
335
|
+
end
|
336
|
+
|
337
|
+
# Creates copy of this spreadsheet with the given name.
|
342
338
|
def duplicate(new_name = nil)
|
343
|
-
new_name ||= "Copy of " + @title
|
339
|
+
new_name ||= (@title ? "Copy of " + @title : "Untitled")
|
344
340
|
get_url = "http://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=#{key}&exportFormat=ods"
|
345
|
-
ods = @session.
|
341
|
+
ods = @session.request(:get, get_url, :response_type => :raw)
|
346
342
|
|
347
343
|
url = "http://docs.google.com/feeds/documents/private/full"
|
348
|
-
|
349
|
-
|
344
|
+
header = {
|
345
|
+
"Content-Type" => "application/x-vnd.oasis.opendocument.spreadsheet",
|
346
|
+
"Slug" => URI.encode(new_name),
|
347
|
+
}
|
348
|
+
doc = @session.request(:post, url, :data => ods, :auth => :writely, :header => header)
|
350
349
|
ss_url = as_utf8(doc.search(
|
351
350
|
"link[@rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']")[0]["href"])
|
352
351
|
return Spreadsheet.new(@session, ss_url, title)
|
353
352
|
end
|
354
353
|
|
354
|
+
# If +permanent+ is +false+, moves the spreadsheet to the trash.
|
355
|
+
# If +permanent+ is +true+, deletes the spreadsheet permanently.
|
356
|
+
def delete(permanent = false)
|
357
|
+
@session.request(:delete,
|
358
|
+
self.document_feed_url + (permanent ? "?delete=true" : ""),
|
359
|
+
:auth => :writely, :header => {"If-Match" => "*"})
|
360
|
+
end
|
361
|
+
|
355
362
|
# Returns worksheets of the spreadsheet as array of GoogleSpreadsheet::Worksheet.
|
356
363
|
def worksheets
|
357
|
-
doc = @session.get
|
364
|
+
doc = @session.request(:get, @worksheets_feed_url)
|
358
365
|
result = []
|
359
366
|
for entry in doc.search("entry")
|
360
367
|
title = as_utf8(entry.search("title").text)
|
@@ -375,7 +382,7 @@ module GoogleSpreadsheet
|
|
375
382
|
<gs:colCount>#{h(max_cols)}</gs:colCount>
|
376
383
|
</entry>
|
377
384
|
EOS
|
378
|
-
doc = @session.post
|
385
|
+
doc = @session.request(:post, @worksheets_feed_url, :data => xml)
|
379
386
|
url = as_utf8(doc.search(
|
380
387
|
"link[@rel='http://schemas.google.com/spreadsheets/2006#cellsfeed']")[0]["href"])
|
381
388
|
return Worksheet.new(@session, self, url, title)
|
@@ -383,7 +390,7 @@ module GoogleSpreadsheet
|
|
383
390
|
|
384
391
|
# Returns list of tables in the spreadsheet.
|
385
392
|
def tables
|
386
|
-
doc = @session.get
|
393
|
+
doc = @session.request(:get, self.tables_feed_url)
|
387
394
|
return doc.search("entry").map(){ |e| Table.new(@session, e) }.freeze()
|
388
395
|
end
|
389
396
|
|
@@ -418,12 +425,12 @@ module GoogleSpreadsheet
|
|
418
425
|
#{fields}
|
419
426
|
</entry>
|
420
427
|
EOS
|
421
|
-
@session.post
|
428
|
+
@session.request(:post, @records_url, :data => xml)
|
422
429
|
end
|
423
430
|
|
424
431
|
# Returns records in the table.
|
425
432
|
def records
|
426
|
-
doc = @session.get
|
433
|
+
doc = @session.request(:get, @records_url)
|
427
434
|
return doc.search("entry").map(){ |e| Record.new(@session, e) }
|
428
435
|
end
|
429
436
|
|
@@ -542,6 +549,7 @@ module GoogleSpreadsheet
|
|
542
549
|
# Updates number of rows.
|
543
550
|
# Note that update is not sent to the server until you call save().
|
544
551
|
def max_rows=(rows)
|
552
|
+
reload() if !@cells
|
545
553
|
@max_rows = rows
|
546
554
|
@meta_modified = true
|
547
555
|
end
|
@@ -555,6 +563,7 @@ module GoogleSpreadsheet
|
|
555
563
|
# Updates number of columns.
|
556
564
|
# Note that update is not sent to the server until you call save().
|
557
565
|
def max_cols=(cols)
|
566
|
+
reload() if !@cells
|
558
567
|
@max_cols = cols
|
559
568
|
@meta_modified = true
|
560
569
|
end
|
@@ -568,6 +577,7 @@ module GoogleSpreadsheet
|
|
568
577
|
# Updates title of the worksheet.
|
569
578
|
# Note that update is not sent to the server until you call save().
|
570
579
|
def title=(title)
|
580
|
+
reload() if !@cells
|
571
581
|
@title = title
|
572
582
|
@meta_modified = true
|
573
583
|
end
|
@@ -591,10 +601,10 @@ module GoogleSpreadsheet
|
|
591
601
|
# Reloads content of the worksheets from the server.
|
592
602
|
# Note that changes you made by []= is discarded if you haven't called save().
|
593
603
|
def reload()
|
594
|
-
doc = @session.get
|
604
|
+
doc = @session.request(:get, @cells_feed_url)
|
595
605
|
@max_rows = doc.search("gs:rowCount").text.to_i()
|
596
606
|
@max_cols = doc.search("gs:colCount").text.to_i()
|
597
|
-
@title = as_utf8(doc.search("title").text)
|
607
|
+
@title = as_utf8(doc.search("/feed/title").text)
|
598
608
|
|
599
609
|
@cells = {}
|
600
610
|
@input_values = {}
|
@@ -616,7 +626,7 @@ module GoogleSpreadsheet
|
|
616
626
|
|
617
627
|
if @meta_modified
|
618
628
|
|
619
|
-
ws_doc = @session.get
|
629
|
+
ws_doc = @session.request(:get, self.worksheet_feed_url)
|
620
630
|
edit_url = ws_doc.search("link[@rel='edit']")[0]["href"]
|
621
631
|
xml = <<-"EOS"
|
622
632
|
<entry xmlns='http://www.w3.org/2005/Atom'
|
@@ -627,7 +637,7 @@ module GoogleSpreadsheet
|
|
627
637
|
</entry>
|
628
638
|
EOS
|
629
639
|
|
630
|
-
@session.put
|
640
|
+
@session.request(:put, edit_url, :data => xml)
|
631
641
|
|
632
642
|
@meta_modified = false
|
633
643
|
sent = true
|
@@ -643,7 +653,7 @@ module GoogleSpreadsheet
|
|
643
653
|
cols = @modified.map(){ |r, c| c }
|
644
654
|
url = "#{@cells_feed_url}?return-empty=true&min-row=#{rows.min}&max-row=#{rows.max}" +
|
645
655
|
"&min-col=#{cols.min}&max-col=#{cols.max}"
|
646
|
-
doc = @session.get
|
656
|
+
doc = @session.request(:get, url)
|
647
657
|
for entry in doc.search("entry")
|
648
658
|
row = entry.search("gs:cell")[0]["row"].to_i()
|
649
659
|
col = entry.search("gs:cell")[0]["col"].to_i()
|
@@ -680,7 +690,7 @@ module GoogleSpreadsheet
|
|
680
690
|
</feed>
|
681
691
|
EOS
|
682
692
|
|
683
|
-
result = @session.post
|
693
|
+
result = @session.request(:post, "#{@cells_feed_url}/batch", :data => xml)
|
684
694
|
for entry in result.search("atom:entry")
|
685
695
|
interrupted = entry.search("batch:interrupted")[0]
|
686
696
|
if interrupted
|
@@ -709,10 +719,10 @@ module GoogleSpreadsheet
|
|
709
719
|
end
|
710
720
|
|
711
721
|
# Deletes this worksheet. Deletion takes effect right away without calling save().
|
712
|
-
def delete
|
713
|
-
ws_doc = @session.get
|
722
|
+
def delete()
|
723
|
+
ws_doc = @session.request(:get, self.worksheet_feed_url)
|
714
724
|
edit_url = ws_doc.search("link[@rel='edit']")[0]["href"]
|
715
|
-
@session.delete
|
725
|
+
@session.request(:delete, edit_url)
|
716
726
|
end
|
717
727
|
|
718
728
|
# Returns true if you have changes made by []= which haven't been saved.
|
@@ -742,7 +752,7 @@ module GoogleSpreadsheet
|
|
742
752
|
</entry>
|
743
753
|
EOS
|
744
754
|
|
745
|
-
result = @session.post
|
755
|
+
result = @session.request(:post, self.spreadsheet.tables_feed_url, :data => xml)
|
746
756
|
return Table.new(@session, result)
|
747
757
|
end
|
748
758
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-spreadsheet-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hiroshi Ichikawa
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-11 00:00:00 +09:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|