google-cells 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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