google-spreadsheet-ruby 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|