google-cells 0.3.0 → 0.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8e91eb8141cc97ad38d072e1986b3de439b103fd
4
- data.tar.gz: 1e5513c4d68f3a6f399530e376ad01ef85a5006d
3
+ metadata.gz: 562c83d9136da18270e06e2b59079fb85d6b1b5f
4
+ data.tar.gz: 23c9dc41aac3e3e8032e2817ef18aaac9675ade2
5
5
  SHA512:
6
- metadata.gz: bfbe733459648d1e428206fdd530383a6a24d8ddb91b3de3404f398f108fd7d0ca4230ae74b94a5ee52a4517e7b12c7a4b57b8a607ef34b79522e44c52e41cb0
7
- data.tar.gz: 967e8491a166307e0ca3a09e4edbee55c0d53f9c9fa16cedad097fad35dbc4ed1f47e479fcb072cd79da23f8f049bec46915dcd935725292bb7bfeb579586292
6
+ metadata.gz: 2de7ae17f127033ecdba6480b9197822637222c3e3f7ca643f9506be96de8e02ff90b938ef27d873742e31edc5b22de4e7e475628a8856927e5cc50d7857315c
7
+ data.tar.gz: 1254f82ec850e4c60539d381ef11057bc7d62fceab4fc9b39329cb2b51a4337442c39f71e9fa8b5b1b43cfad112293e85b51232c17faa0c7615bc96f7ead5a98
@@ -0,0 +1,11 @@
1
+ ---
2
+ rules:
3
+ ignore:
4
+ - missing_class_documentation
5
+ - missing_method_documentation
6
+ - space_between_curly_brace_and_pipe_missing
7
+ - space_inside_closing_curly_brace_missing
8
+ - space_inside_opening_curly_brace_missing
9
+ - space_missing_after_hash_sign
10
+ - space_missing_inside_closing_curly_brace
11
+ - space_missing_inside_opening_curly_brace
@@ -1,3 +1,10 @@
1
+ Version 0.4.0
2
+ =========================
3
+
4
+ + Added pages to sinatra web flow example
5
+ + Added Spreadsheet#revisions
6
+ + Added Revision class and Revision.list
7
+
1
8
  Version 0.3.0
2
9
  =========================
3
10
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- google-cells (0.2.1)
4
+ google-cells (0.3.1.pre)
5
5
  google-api-client (~> 0.7, >= 0.7.1)
6
6
  nokogiri (~> 1.6, >= 1.6.1)
7
7
 
data/README.md CHANGED
@@ -8,25 +8,39 @@ Add this line to your application's Gemfile:
8
8
 
9
9
  gem 'google_cells'
10
10
 
11
- And then execute:
11
+ ## Configuration
12
12
 
13
- $ bundle
13
+ Sign up for the Drive API in the [Google developer console](https://console.developers.google.com/project).
14
14
 
15
- Or install it yourself as:
15
+ __Oauth 2 Web Flow__
16
16
 
17
- $ gem install google_cells
17
+ For a web application using the oauth 2 web flow, configure GoogleCells with your client id and secret.
18
18
 
19
- ## Usage
19
+ ```ruby
20
+ GoogleCells.configure do |config|
21
+ config.client_id = 'my-client-id'
22
+ config.client_secret = 'my-client-secret'
23
+ end
24
+ ```
25
+
26
+ __Oauth 2 Service Account__
27
+
28
+ For background processing using a service account, configure GoogleCells with your account email, path to your key file, and key secret.
20
29
 
21
30
  ```ruby
22
- # configure with Google Service account keys
23
31
  GoogleCells.configure do |config|
24
32
  config.service_account_email = 'my_service_account@email.here'
25
33
  config.key_file = File.dirname(__FILE__) +
26
34
  '/path/to/private-key.file/from/Google'
27
35
  config.key_secret = 'notasecret'
28
36
  end
37
+ ```
38
+
39
+ See "examples" directory for implementations of both the web flow and service account in sinatra. To use the examples, add config files with your auth info. to /tmp.
29
40
 
41
+ ## Usage
42
+
43
+ ```ruby
30
44
  # list all spreadsheets in account
31
45
  files = GoogleCells::Spreadsheet.list
32
46
  files.each do |s|
@@ -2,6 +2,7 @@ require 'sinatra/base'
2
2
 
3
3
  module App
4
4
  class Routes < ::Sinatra::Base
5
+
5
6
  get '/' do
6
7
  @spreadsheets = GoogleCells::Spreadsheet.list
7
8
  @spreadsheets.sort_by!{|s| s.updated_at}
@@ -10,12 +11,85 @@ module App
10
11
  if @spreadsheets.empty?
11
12
  text << "Nothing here."
12
13
  else
13
- text << "<% for s in @spreadsheets %>"
14
- text << "<br/><%= s.updated_at %> -- <a href=\"https://docs.google.com/"
15
- text << "spreadsheet/ccc?key=<%= s.key %>\"><%= s.title %></a>"
16
- text << "<% end %>"
14
+ @spreadsheets.each do |s|
15
+ text << "<br/>#{s.updated_at} --"
16
+ text << "<a href=\"/spreadsheets/#{s.key}\">#{s.title}</a>"
17
+ end
18
+ end
19
+ erb text
20
+ end
21
+
22
+ get '/spreadsheets/:spreadsheet_id' do
23
+ _load_spreadsheet
24
+ @spreadsheet = GoogleCells::Spreadsheet.get(params[:spreadsheet_id])
25
+ text = "<h1>Spreadsheet: #{@spreadsheet.title}</h1>"
26
+ worksheets = @spreadsheet.worksheets
27
+ worksheets.each_with_index do |ws, i|
28
+ text << "<b>Worksheet #{i}</b>"
29
+ text << "<br/><a href=\"/spreadsheets/#{@spreadsheet.key}/worksheets/#{i
30
+ }\">#{ws.title}</a>"
31
+ text << "<br/><a href=\"/spreadsheets/#{@spreadsheet.key}/revisions\">"+
32
+ "Revisions</a>"
33
+ end
34
+ erb text
35
+ end
36
+
37
+ get "/spreadsheets/:spreadsheet_id/revisions" do
38
+ _load_spreadsheet
39
+ text = "<h1>#{@spreadsheet.title}</h1>"
40
+ @spreadsheet.revisions.each do |r|
41
+ text << "Revision ##{r.id}"
42
+ text << "<ul>"
43
+ text << "<li>Updated: #{r.updated_at}</li>"
44
+ text << "<li>Etag: #{r.etag}</li>"
45
+ text << "<li>Author name: #{r.author.name}</li>"
46
+ text << "<li>Author email: #{r.author.email}</li>"
47
+ text << "</ul>"
48
+ end
49
+ erb text
50
+ end
51
+
52
+ get '/spreadsheets/:spreadsheet_id/worksheets/:worksheet_num' do
53
+ _load_spreadsheet
54
+ @worksheet = @spreadsheet.worksheets[params[:worksheet_num].to_i]
55
+ text = "<style>table td{ border-style:solid; border-width:1px;}</style>"
56
+ text << "<h1>#{@spreadsheet.title}</h1>"
57
+ text << "Worksheet #{@worksheet.title} (Showing first 5 rows):"
58
+ text << "<table>"
59
+ @worksheet.rows.from(1).to(5).each do |row|
60
+ text << "<tr><td>"
61
+ text << row.cells.map(&:value).join('</td><td>')
62
+ text << "</td></tr>"
17
63
  end
64
+ text << "<form action=\"/spreadsheets/" + params[:spreadsheet_id] +
65
+ "/worksheets/" + params[:worksheet_num] + "/scramble\" method=\"post\">"
66
+ text << "<button type=\"submit\">Scramble!</button>"
67
+ text << "</form>"
18
68
  erb text
19
69
  end
70
+
71
+ post '/spreadsheets/:spreadsheet_id/worksheets/:worksheet_num/scramble' do
72
+ _load_spreadsheet
73
+ @worksheet = @spreadsheet.worksheets[params[:worksheet_num].to_i]
74
+ cached_array = @worksheet.rows.from(1).to(5).all.dup
75
+ @worksheet.rows.from(1).to(5).each do |row|
76
+ row.cells.each do |c|
77
+ scramble_row = cached_array[rand(cached_array.length)]
78
+ scramble_cell = scramble_row.cells[rand(scramble_row.cells.length)]
79
+ c.input_value = scramble_cell.value
80
+ end
81
+ end
82
+ @worksheet.save!
83
+
84
+ path = "/spreadsheets/" + params[:spreadsheet_id] + "/worksheets/" +
85
+ params[:worksheet_num].to_i.to_s
86
+ redirect to(path)
87
+ end
88
+
89
+ private
90
+
91
+ def _load_spreadsheet
92
+ @spreadsheet = GoogleCells::Spreadsheet.get(params[:spreadsheet_id])
93
+ end
20
94
  end
21
95
  end
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["jmthrower@gmail.com"]
11
11
  spec.summary = %q{Google Spreadsheets API wrapper}
12
12
  spec.description = %q{An intuitive Google Spreadsheets API wrapper}
13
- spec.homepage = ""
13
+ spec.homepage = "https://github.com/jmthrower/google-cells"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
@@ -13,6 +13,7 @@ require "google_cells/folder"
13
13
  require "google_cells/row"
14
14
  require "google_cells/spreadsheet"
15
15
  require "google_cells/worksheet"
16
+ require "google_cells/revision"
16
17
  require "google_cells/version"
17
18
 
18
19
  module GoogleCells
@@ -48,23 +48,28 @@ module GoogleCells
48
48
  cells = []
49
49
  each_entry(worksheet.cells_uri, 'return-empty' => 'true',
50
50
  'min-row' => start.to_s, 'max-row' => last.to_s) do |entry|
51
- gscell = entry.css("gs|cell")[0]
52
- cell = Cell.new(
53
- id: entry.css("id").text,
54
- title: entry.css("title").text,
55
- value: gscell.inner_text,
56
- row: gscell["row"].to_i,
57
- col: gscell["col"].to_i,
58
- edit_url: entry.css("link[rel='edit']")[0]["href"],
59
- input_value: gscell["inputValue"],
60
- numeric_value: gscell["numericValue"],
61
- worksheet: self.worksheet
62
- )
51
+ args = parse_from_entry(entry)
52
+ cell = Cell.new(args)
63
53
  cells[cell.row - start] ||= []
64
54
  cells[cell.row - start][cell.col - 1] = cell
65
55
  end
66
56
  cells
67
57
  end
68
58
  end
59
+
60
+ def parse_from_entry(entry)
61
+ gscell = entry.css("gs|cell")[0]
62
+ {
63
+ id: entry.css("id").text,
64
+ title: entry.css("title").text,
65
+ value: gscell.inner_text,
66
+ row: gscell["row"].to_i,
67
+ col: gscell["col"].to_i,
68
+ edit_url: entry.css("link[rel='edit']")[0]["href"],
69
+ input_value: gscell["inputValue"],
70
+ numeric_value: gscell["numericValue"],
71
+ worksheet: self.worksheet
72
+ }
73
+ end
69
74
  end
70
75
  end
@@ -0,0 +1,43 @@
1
+ module GoogleCells
2
+ class Revision < GoogleCells::GoogleObject
3
+ extend UrlHelper
4
+ extend Fetcher
5
+
6
+ @permanent_attributes = [ :id, :updated_at, :spreadsheet_key, :etag,
7
+ :author ]
8
+ define_accessors
9
+
10
+ class << self
11
+
12
+ def list(key)
13
+ revisions = []
14
+ res = request(:get, self.revisions_uri(key))
15
+ JSON.parse(res.body)['items'].each do |entry|
16
+ args = parse_from_entry(entry)
17
+ revisions << Revision.new(args.merge(spreadsheet_key: key))
18
+ end
19
+ revisions.sort{|a,b| a.updated_at <=> b.updated_at}
20
+ end
21
+ end
22
+
23
+ def spreadsheet
24
+ @spreadsheet ||= Spreadsheet.get(self.spreadsheet_key)
25
+ end
26
+
27
+ private
28
+
29
+ def self.parse_from_entry(entry)
30
+ author = entry['lastModifyingUser']
31
+ { id: entry['id'],
32
+ updated_at: entry['modifiedDate'],
33
+ etag: entry['etag'],
34
+ author: (author.nil? ? nil : Author.new(
35
+ name: author['displayName'],
36
+ email: author['emailAddress']
37
+ ))
38
+ }
39
+ end
40
+ end
41
+ end
42
+
43
+
@@ -99,6 +99,10 @@ module GoogleCells
99
99
  define_method(m){|args| self.class.send(m, self.key, args) }
100
100
  end
101
101
 
102
+ %w( worksheets_uri revisions_uri ).each do |m|
103
+ define_method(m){ self.class.send(m, self.key) }
104
+ end
105
+
102
106
  def unsubscribe(params)
103
107
  self.class.unsubscribe(params)
104
108
  end
@@ -110,7 +114,7 @@ module GoogleCells
110
114
  def copy(opts={})
111
115
  self.class.copy(self.key, opts)
112
116
  end
113
-
117
+
114
118
  def enfold(folder_key)
115
119
  return true if @folders && @folders.select{|f| f.key == folder_key}.first
116
120
  body = {'id' => self.key}.to_json
@@ -159,11 +163,19 @@ module GoogleCells
159
163
  return @worksheets
160
164
  end
161
165
 
166
+ def revisions
167
+ @revisions ||= Revision.list(self.key).map do |r|
168
+ r.instance_variable_set(:@spreadsheet, self)
169
+ r
170
+ end
171
+ end
172
+
162
173
  private
163
174
 
164
175
  def self.parse_from_entry(entry, key=nil)
165
- key ||= entry.css("link").select{|el| el['rel'] == 'alternate'}.
166
- first['href'][/key=.+/][4..-1]
176
+ url ||= entry.css("link").select{|el| el['rel'] == 'alternate'}.
177
+ first['href']
178
+ key = url[/key=.+/] ? url[/key=.+/][4..-1] : url[/[^\/]{44}/]
167
179
  { title: entry.css("title").first.text,
168
180
  key: key,
169
181
  updated_at: entry.css("updated").first.text,
@@ -173,7 +185,5 @@ module GoogleCells
173
185
  )
174
186
  }
175
187
  end
176
-
177
- def worksheets_uri; self.class.worksheets_uri(key); end
178
188
  end
179
189
  end
@@ -33,5 +33,9 @@ module GoogleCells
33
33
  def unwatch_uri
34
34
  "https://www.googleapis.com/drive/v2/channels/stop"
35
35
  end
36
+
37
+ def revisions_uri(key)
38
+ "https://www.googleapis.com/drive/v2/files/#{key}/revisions"
39
+ end
36
40
  end
37
41
  end
@@ -1,3 +1,3 @@
1
1
  module GoogleCells
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -13,8 +13,6 @@ module GoogleCells
13
13
  GoogleCells::CellSelector::RowSelector.new(self)
14
14
  end
15
15
 
16
- class UpdateError < StandardError ; end
17
-
18
16
  def save!
19
17
  return if @changed_cells.nil? || @changed_cells.empty?
20
18
  batch_url = concat_url(cells_uri, "/batch")
@@ -22,16 +20,7 @@ module GoogleCells
22
20
  "Content-Type" => "application/atom+xml", "If-Match" => "*"})
23
21
  doc = Nokogiri.parse(response.body)
24
22
 
25
- for entry in doc.css("atom|entry")
26
- interrupted = entry.css("batch|interrupted")[0]
27
- if interrupted
28
- raise(UpdateError, "Update failed: %s" % interrupted["reason"])
29
- end
30
- if !(entry.css("batch|status").first["code"] =~ /^2/)
31
- raise(UpdateError, "Update failed for cell %s: %s" %
32
- [entry.css("atom|id").text, entry.css("batch|status")[0]["reason"]])
33
- end
34
- end
23
+ doc.css("atom|entry").each{|entry| check_entry_for_errors!(entry) }
35
24
  @changed_cells = {}
36
25
  true
37
26
  end
@@ -44,6 +33,24 @@ module GoogleCells
44
33
 
45
34
  private
46
35
 
36
+ class UpdateError < StandardError ; end
37
+
38
+ def check_entry_for_errors!(entry)
39
+ check_for_batch_error!(entry)
40
+ check_for_cell_error!(entry)
41
+ end
42
+
43
+ def check_for_batch_error!(entry)
44
+ return unless entry.css("batch|interrupted")[0]
45
+ raise UpdateError, "Update failed: #{interrupted["reason"]}"
46
+ end
47
+
48
+ def check_for_cell_error!(entry)
49
+ return if (entry.css("batch|status").first["code"] =~ /^2/)
50
+ raise UpdateError, "Update failed for cell #{entry.css("atom|id").text
51
+ }: #{entry.css("batch|status").first["reason"]}"
52
+ end
53
+
47
54
  def to_xml
48
55
  xml = <<-EOS
49
56
  <feed xmlns="http://www.w3.org/2005/Atom"
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe GoogleCells::Revision do
4
+
5
+ it { should respond_to(:etag) }
6
+ it { should respond_to(:id) }
7
+ it { should respond_to(:updated_at) }
8
+ it { should respond_to(:spreadsheet_key) }
9
+ it { should respond_to(:spreadsheet) }
10
+ it { should respond_to(:author) }
11
+
12
+ let(:revisions) do
13
+ VCR.use_cassette('google_cells/revisions/list') do |c|
14
+ GoogleCells::Revision.list('1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls')
15
+ end
16
+ end
17
+
18
+ describe ".list" do
19
+
20
+ it "returns a list of revisions" do
21
+ revisions.count.should eq 3
22
+ revisions.first.class.should eq GoogleCells::Revision
23
+ end
24
+
25
+ it "returns revisions with attributes" do
26
+ r = revisions.last
27
+ r.id.should eq "22"
28
+ r.etag.should be
29
+ r.updated_at.should be
30
+ r.spreadsheet_key.should be
31
+ end
32
+
33
+ it "returns revisions with author info" do
34
+ r = revisions.last
35
+ r.author.class.should eq GoogleCells::Author
36
+ r.author.name.should eq "Jessica Thrower"
37
+ end
38
+ end
39
+ end
@@ -168,4 +168,22 @@ describe GoogleCells::Spreadsheet do
168
168
  its(:spreadsheet){ should eq @s }
169
169
  end
170
170
  end
171
+
172
+ describe "#revisions" do
173
+
174
+ before(:each) do
175
+ @s, @revisions = VCR.use_cassette('google_cells/revisions/list') do |c|
176
+ s = GoogleCells::Spreadsheet.get('1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls')
177
+ [ s, s.revisions ]
178
+ end
179
+ end
180
+
181
+ it "returns a list of revisions" do
182
+ @revisions.each{|r| r.class.should eq GoogleCells::Revision}
183
+ end
184
+
185
+ it "assigns self as spreadsheet" do
186
+ @revisions.first.spreadsheet.should eq @s
187
+ end
188
+ end
171
189
  end
@@ -0,0 +1,321 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://accounts.google.com/o/oauth2/token
6
+ body:
7
+ encoding: ASCII-8BIT
8
+ string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiIxOTQ1Nzg3NTQyOTVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvZHJpdmUgaHR0cHM6Ly9zcHJlYWRzaGVldHMuZ29vZ2xlLmNvbS9mZWVkcyIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTQxMDk4MjgyMCwiaWF0IjoxNDEwOTgyNzAwfQ.avYzPBBLtJvRpJQbLLsjdlo3aIaPQEhI7wW9q_dH-TdS3awfeXwgvRU6CjAXfcTh2ZulYOmXHLGdbGi9yjOEMIvuMm2Y517n-0Xg0mn1VMn2rndAbvm7zJG4Y821tiiKAk1qT2vqIW-0UX2jLq7DrSdpw-3yLLQCk9z4rR2msmY
9
+ headers:
10
+ Cache-Control:
11
+ - no-store
12
+ Content-Type:
13
+ - application/x-www-form-urlencoded
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ User-Agent:
19
+ - Ruby
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Cache-Control:
28
+ - no-cache, no-store, max-age=0, must-revalidate
29
+ Pragma:
30
+ - no-cache
31
+ Expires:
32
+ - Fri, 01 Jan 1990 00:00:00 GMT
33
+ Date:
34
+ - Wed, 17 Sep 2014 19:39:17 GMT
35
+ Content-Disposition:
36
+ - attachment; filename="json.txt"; filename*=UTF-8''json.txt
37
+ X-Content-Type-Options:
38
+ - nosniff
39
+ X-Frame-Options:
40
+ - SAMEORIGIN
41
+ X-Xss-Protection:
42
+ - 1; mode=block
43
+ Server:
44
+ - GSE
45
+ Alternate-Protocol:
46
+ - 443:quic,p=0.002
47
+ Transfer-Encoding:
48
+ - chunked
49
+ body:
50
+ encoding: UTF-8
51
+ string: |-
52
+ {
53
+ "access_token" : "ya29.gwBcjNQcvY0B_wF2vd20vP1IzD4g6bcs8I6qBtAws33xbT4gVZenXzR4",
54
+ "token_type" : "Bearer",
55
+ "expires_in" : 3600
56
+ }
57
+ http_version:
58
+ recorded_at: Wed, 17 Sep 2014 19:39:20 GMT
59
+ - request:
60
+ method: get
61
+ uri: https://spreadsheets.google.com/feeds/worksheets/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/private/full
62
+ body:
63
+ encoding: UTF-8
64
+ string: ''
65
+ headers:
66
+ User-Agent:
67
+ - |-
68
+ GoogleCells App/0.0.3 google-api-ruby-client/0.7.1 Mac OS X/10.8.5
69
+ (gzip)
70
+ Accept-Encoding:
71
+ - gzip
72
+ Content-Type:
73
+ - ''
74
+ Authorization:
75
+ - Bearer ya29.gwBcjNQcvY0B_wF2vd20vP1IzD4g6bcs8I6qBtAws33xbT4gVZenXzR4
76
+ Cache-Control:
77
+ - no-store
78
+ Accept:
79
+ - "*/*"
80
+ response:
81
+ status:
82
+ code: 200
83
+ message: OK
84
+ headers:
85
+ Content-Type:
86
+ - application/atom+xml; charset=UTF-8
87
+ X-Robots-Tag:
88
+ - noindex, nofollow, nosnippet
89
+ Expires:
90
+ - Wed, 17 Sep 2014 19:39:18 GMT
91
+ Date:
92
+ - Wed, 17 Sep 2014 19:39:18 GMT
93
+ Cache-Control:
94
+ - private, max-age=0, must-revalidate, no-transform
95
+ Vary:
96
+ - Accept, X-GData-Authorization, GData-Version
97
+ Gdata-Version:
98
+ - '1.0'
99
+ Last-Modified:
100
+ - Wed, 17 Sep 2014 16:41:55 GMT
101
+ Set-Cookie:
102
+ - NID=67=X4bLgTBUXCP_rCFz169PAVJfXHIBE7bliTFfe9sa7kdsRBiImWUx5TOnriyJv9QxNJtzOuF-NYF7faxM13_YOT7_bAKQ3xs0kbpFK0uVG2zbr_fOckZvYNEEAOoBYBLn;Domain=.google.com;Path=/;Expires=Thu,
103
+ 19-Mar-2015 19:39:18 GMT;HttpOnly
104
+ P3p:
105
+ - CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657
106
+ for more info."
107
+ X-Content-Type-Options:
108
+ - nosniff
109
+ X-Frame-Options:
110
+ - SAMEORIGIN
111
+ X-Xss-Protection:
112
+ - 1; mode=block
113
+ Server:
114
+ - GSE
115
+ Alternate-Protocol:
116
+ - 443:quic,p=0.002
117
+ Transfer-Encoding:
118
+ - chunked
119
+ body:
120
+ encoding: ASCII-8BIT
121
+ string: "<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom'
122
+ xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gs='http://schemas.google.com/spreadsheets/2006'><id>https://spreadsheets.google.com/feeds/worksheets/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/private/full</id><updated>2014-09-17T16:41:55.998Z</updated><category
123
+ scheme='http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#worksheet'/><title
124
+ type='text'>Scrambler</title><link rel='alternate' type='application/atom+xml'
125
+ href='https://docs.google.com/spreadsheets/d/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/edit'/><link
126
+ rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/worksheets/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/private/full'/><link
127
+ rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/worksheets/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/private/full'/><link
128
+ rel='self' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/worksheets/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/private/full'/><author><name>jmthrower</name><email>jmthrower@gmail.com</email></author><openSearch:totalResults>1</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><entry><id>https://spreadsheets.google.com/feeds/worksheets/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/private/full/od6</id><updated>2014-09-17T16:41:55.998Z</updated><category
129
+ scheme='http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#worksheet'/><title
130
+ type='text'>Sheet1</title><content type='text'>Sheet1</content><link rel='http://schemas.google.com/spreadsheets/2006#listfeed'
131
+ type='application/atom+xml' href='https://spreadsheets.google.com/feeds/list/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/od6/private/full'/><link
132
+ rel='http://schemas.google.com/spreadsheets/2006#cellsfeed' type='application/atom+xml'
133
+ href='https://spreadsheets.google.com/feeds/cells/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/od6/private/full'/><link
134
+ rel='http://schemas.google.com/visualization/2008#visualizationApi' type='application/atom+xml'
135
+ href='https://docs.google.com/spreadsheets/d/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/gviz/tq?gid=0'/><link
136
+ rel='http://schemas.google.com/spreadsheets/2006#exportcsv' type='text/csv'
137
+ href='https://docs.google.com/spreadsheets/d/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/export?gid=0&amp;format=csv'/><link
138
+ rel='self' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/worksheets/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/private/full/od6'/><link
139
+ rel='edit' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/worksheets/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/private/full/od6/-u3c64m'/><gs:colCount>26</gs:colCount><gs:rowCount>1000</gs:rowCount></entry></feed>"
140
+ http_version:
141
+ recorded_at: Wed, 17 Sep 2014 19:39:21 GMT
142
+ - request:
143
+ method: post
144
+ uri: https://accounts.google.com/o/oauth2/token
145
+ body:
146
+ encoding: ASCII-8BIT
147
+ string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiIxOTQ1Nzg3NTQyOTVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvZHJpdmUgaHR0cHM6Ly9zcHJlYWRzaGVldHMuZ29vZ2xlLmNvbS9mZWVkcyIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTQxMDk4MjgyMSwiaWF0IjoxNDEwOTgyNzAxfQ.FzSbYnrTHJDGliLQh90QojBrqdXYiEj1PoOoF6qye8SJqnC0hJpaHz6yLlkOSuz1oLnd33n5o72HWx_SDgC7QhvLYd0XTLSvH5aJmXsnAHuOfk8OH4Go1qQ5IK-SoCDb5rOx108iUwk7cJmQOkoqUu_G1Q-0e-BNpK_uM2kOtcs
148
+ headers:
149
+ Cache-Control:
150
+ - no-store
151
+ Content-Type:
152
+ - application/x-www-form-urlencoded
153
+ Accept-Encoding:
154
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
155
+ Accept:
156
+ - "*/*"
157
+ User-Agent:
158
+ - Ruby
159
+ response:
160
+ status:
161
+ code: 200
162
+ message: OK
163
+ headers:
164
+ Content-Type:
165
+ - application/json; charset=utf-8
166
+ Cache-Control:
167
+ - no-cache, no-store, max-age=0, must-revalidate
168
+ Pragma:
169
+ - no-cache
170
+ Expires:
171
+ - Fri, 01 Jan 1990 00:00:00 GMT
172
+ Date:
173
+ - Wed, 17 Sep 2014 19:39:18 GMT
174
+ Content-Disposition:
175
+ - attachment; filename="json.txt"; filename*=UTF-8''json.txt
176
+ X-Content-Type-Options:
177
+ - nosniff
178
+ X-Frame-Options:
179
+ - SAMEORIGIN
180
+ X-Xss-Protection:
181
+ - 1; mode=block
182
+ Server:
183
+ - GSE
184
+ Alternate-Protocol:
185
+ - 443:quic,p=0.002
186
+ Transfer-Encoding:
187
+ - chunked
188
+ body:
189
+ encoding: UTF-8
190
+ string: |-
191
+ {
192
+ "access_token" : "ya29.gwBa_rkOu6-RPL02c3HGaXlzjijzNNpPYcib4EWESrKpflkQ1IvFqadZ",
193
+ "token_type" : "Bearer",
194
+ "expires_in" : 3600
195
+ }
196
+ http_version:
197
+ recorded_at: Wed, 17 Sep 2014 19:39:21 GMT
198
+ - request:
199
+ method: get
200
+ uri: https://www.googleapis.com/drive/v2/files/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/revisions
201
+ body:
202
+ encoding: UTF-8
203
+ string: ''
204
+ headers:
205
+ User-Agent:
206
+ - |-
207
+ GoogleCells App/0.0.3 google-api-ruby-client/0.7.1 Mac OS X/10.8.5
208
+ (gzip)
209
+ Accept-Encoding:
210
+ - gzip
211
+ Content-Type:
212
+ - ''
213
+ Authorization:
214
+ - Bearer ya29.gwBa_rkOu6-RPL02c3HGaXlzjijzNNpPYcib4EWESrKpflkQ1IvFqadZ
215
+ Cache-Control:
216
+ - no-store
217
+ Accept:
218
+ - "*/*"
219
+ response:
220
+ status:
221
+ code: 200
222
+ message: OK
223
+ headers:
224
+ Expires:
225
+ - Wed, 17 Sep 2014 19:39:19 GMT
226
+ Date:
227
+ - Wed, 17 Sep 2014 19:39:19 GMT
228
+ Cache-Control:
229
+ - private, max-age=0, must-revalidate, no-transform
230
+ Etag:
231
+ - '"fk0AzBEIhUhhdZ8fZzKcL1hA5NE/UbACniW4urK-t2Y7dXz39-QEUmo"'
232
+ Content-Type:
233
+ - application/json; charset=UTF-8
234
+ X-Content-Type-Options:
235
+ - nosniff
236
+ X-Frame-Options:
237
+ - SAMEORIGIN
238
+ X-Xss-Protection:
239
+ - 1; mode=block
240
+ Server:
241
+ - GSE
242
+ Alternate-Protocol:
243
+ - 443:quic,p=0.002
244
+ Transfer-Encoding:
245
+ - chunked
246
+ body:
247
+ encoding: ASCII-8BIT
248
+ string: |
249
+ {
250
+ "kind": "drive#revisionList",
251
+ "etag": "\"fk0AzBEIhUhhdZ8fZzKcL1hA5NE/UbACniW4urK-t2Y7dXz39-QEUmo\"",
252
+ "selfLink": "https://www.googleapis.com/drive/v2/files/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/revisions",
253
+ "items": [
254
+ {
255
+ "kind": "drive#revision",
256
+ "etag": "\"fk0AzBEIhUhhdZ8fZzKcL1hA5NE/sk9oekelD-LBkfg0rhoacOecSzw\"",
257
+ "id": "20",
258
+ "selfLink": "https://www.googleapis.com/drive/v2/files/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/revisions/20",
259
+ "mimeType": "application/vnd.google-apps.spreadsheet",
260
+ "modifiedDate": "2014-09-17T01:04:05.746Z",
261
+ "published": false,
262
+ "exportLinks": {
263
+ "text/csv": "https://docs.google.com/spreadsheets/export?id=1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls&revision=20&exportFormat=csv",
264
+ "application/pdf": "https://docs.google.com/spreadsheets/export?id=1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls&revision=20&exportFormat=pdf",
265
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "https://docs.google.com/spreadsheets/export?id=1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls&revision=20&exportFormat=xlsx"
266
+ },
267
+ "lastModifyingUserName": "Jessica Thrower",
268
+ "lastModifyingUser": {
269
+ "kind": "drive#user",
270
+ "displayName": "Jessica Thrower",
271
+ "isAuthenticatedUser": false,
272
+ "permissionId": "13045974993929539071"
273
+ }
274
+ },
275
+ {
276
+ "kind": "drive#revision",
277
+ "etag": "\"fk0AzBEIhUhhdZ8fZzKcL1hA5NE/3ETJvOaepc7o1UQqNDcjQaZVPnI\"",
278
+ "id": "21",
279
+ "selfLink": "https://www.googleapis.com/drive/v2/files/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/revisions/21",
280
+ "mimeType": "application/vnd.google-apps.spreadsheet",
281
+ "modifiedDate": "2014-09-17T16:38:52.598Z",
282
+ "published": false,
283
+ "exportLinks": {
284
+ "text/csv": "https://docs.google.com/spreadsheets/export?id=1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls&revision=21&exportFormat=csv",
285
+ "application/pdf": "https://docs.google.com/spreadsheets/export?id=1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls&revision=21&exportFormat=pdf",
286
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "https://docs.google.com/spreadsheets/export?id=1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls&revision=21&exportFormat=xlsx"
287
+ },
288
+ "lastModifyingUserName": "Jessica Thrower",
289
+ "lastModifyingUser": {
290
+ "kind": "drive#user",
291
+ "displayName": "Jessica Thrower",
292
+ "isAuthenticatedUser": false,
293
+ "permissionId": "13045974993929539071"
294
+ }
295
+ },
296
+ {
297
+ "kind": "drive#revision",
298
+ "etag": "\"fk0AzBEIhUhhdZ8fZzKcL1hA5NE/Gq0bxnYVnrDNhA06pIfOugTK3ss\"",
299
+ "id": "22",
300
+ "selfLink": "https://www.googleapis.com/drive/v2/files/1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls/revisions/22",
301
+ "mimeType": "application/vnd.google-apps.spreadsheet",
302
+ "modifiedDate": "2014-09-17T16:41:55.998Z",
303
+ "published": false,
304
+ "exportLinks": {
305
+ "text/csv": "https://docs.google.com/spreadsheets/export?id=1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls&revision=22&exportFormat=csv",
306
+ "application/pdf": "https://docs.google.com/spreadsheets/export?id=1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls&revision=22&exportFormat=pdf",
307
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "https://docs.google.com/spreadsheets/export?id=1ZRAzPpO--MiXWcIbU_V7YdMlxNZ62hfp4U2HYjis1ls&revision=22&exportFormat=xlsx"
308
+ },
309
+ "lastModifyingUserName": "Jessica Thrower",
310
+ "lastModifyingUser": {
311
+ "kind": "drive#user",
312
+ "displayName": "Jessica Thrower",
313
+ "isAuthenticatedUser": false,
314
+ "permissionId": "07253403460171579496"
315
+ }
316
+ }
317
+ ]
318
+ }
319
+ http_version:
320
+ recorded_at: Wed, 17 Sep 2014 19:39:22 GMT
321
+ recorded_with: VCR 2.8.0
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cells
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jessica Megan Thrower
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-19 00:00:00.000000000 Z
11
+ date: 2014-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-api-client
@@ -146,6 +146,7 @@ extensions: []
146
146
  extra_rdoc_files: []
147
147
  files:
148
148
  - ".gitignore"
149
+ - ".pullreview.yml"
149
150
  - ".ruby-gemset"
150
151
  - ".ruby-version"
151
152
  - CHANGELOG.md
@@ -167,6 +168,7 @@ files:
167
168
  - lib/google_cells/folder.rb
168
169
  - lib/google_cells/google_object.rb
169
170
  - lib/google_cells/reader.rb
171
+ - lib/google_cells/revision.rb
170
172
  - lib/google_cells/row.rb
171
173
  - lib/google_cells/spreadsheet.rb
172
174
  - lib/google_cells/url_helper.rb
@@ -178,6 +180,7 @@ files:
178
180
  - spec/google_cells/fetcher_spec.rb
179
181
  - spec/google_cells/google_object_spec.rb
180
182
  - spec/google_cells/reader_spec.rb
183
+ - spec/google_cells/revision_spec.rb
181
184
  - spec/google_cells/spreadsheet_spec.rb
182
185
  - spec/google_cells/url_helper_spec.rb
183
186
  - spec/google_cells/worksheet_spec.rb
@@ -188,6 +191,7 @@ files:
188
191
  - spec/vcr_cassettes/google_cells/cell_selector/find_each/selection.yml
189
192
  - spec/vcr_cassettes/google_cells/fetcher.yml
190
193
  - spec/vcr_cassettes/google_cells/reader.yml
194
+ - spec/vcr_cassettes/google_cells/revisions/list.yml
191
195
  - spec/vcr_cassettes/google_cells/spreadsheet/cell_selector/worksheet.yml
192
196
  - spec/vcr_cassettes/google_cells/spreadsheet/copy.yml
193
197
  - spec/vcr_cassettes/google_cells/spreadsheet/copy/content.yml
@@ -198,7 +202,7 @@ files:
198
202
  - spec/vcr_cassettes/google_cells/spreadsheet/worksheets.yml
199
203
  - spec/vcr_cassettes/google_cells/worksheet/save.yml
200
204
  - spec/vcr_cassettes/google_cells/worksheets.yml
201
- homepage: ''
205
+ homepage: https://github.com/jmthrower/google-cells
202
206
  licenses:
203
207
  - MIT
204
208
  metadata: {}
@@ -228,6 +232,7 @@ test_files:
228
232
  - spec/google_cells/fetcher_spec.rb
229
233
  - spec/google_cells/google_object_spec.rb
230
234
  - spec/google_cells/reader_spec.rb
235
+ - spec/google_cells/revision_spec.rb
231
236
  - spec/google_cells/spreadsheet_spec.rb
232
237
  - spec/google_cells/url_helper_spec.rb
233
238
  - spec/google_cells/worksheet_spec.rb
@@ -238,6 +243,7 @@ test_files:
238
243
  - spec/vcr_cassettes/google_cells/cell_selector/find_each/selection.yml
239
244
  - spec/vcr_cassettes/google_cells/fetcher.yml
240
245
  - spec/vcr_cassettes/google_cells/reader.yml
246
+ - spec/vcr_cassettes/google_cells/revisions/list.yml
241
247
  - spec/vcr_cassettes/google_cells/spreadsheet/cell_selector/worksheet.yml
242
248
  - spec/vcr_cassettes/google_cells/spreadsheet/copy.yml
243
249
  - spec/vcr_cassettes/google_cells/spreadsheet/copy/content.yml