google_drive 0.3.0 → 0.3.1

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