google_drive 0.3.1 → 0.3.2

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.
@@ -5,9 +5,8 @@
5
5
 
6
6
  require "google_drive/acl_entry"
7
7
 
8
-
9
8
  module GoogleDrive
10
-
9
+
11
10
  # ACL (access control list) of a spreadsheet.
12
11
  #
13
12
  # Use GoogleDrive::Spreadsheet#acl to get GoogleDrive::Acl object.
@@ -15,10 +14,10 @@ module GoogleDrive
15
14
  #
16
15
  # This code is based on https://github.com/guyboertje/gdata-spreadsheet-ruby .
17
16
  class Acl
18
-
17
+
19
18
  include(Util)
20
19
  extend(Forwardable)
21
-
20
+
22
21
  def initialize(session, acls_feed_url) #:nodoc:
23
22
  @session = session
24
23
  @acls_feed_url = acls_feed_url
@@ -26,9 +25,9 @@ module GoogleDrive
26
25
  doc = @session.request(:get, @acls_feed_url, :header => header, :auth => :writely)
27
26
  @acls = doc.css("entry").map(){ |e| AclEntry.new(entry_to_params(e)) }
28
27
  end
29
-
28
+
30
29
  def_delegators(:@acls, :size, :[], :each)
31
-
30
+
32
31
  # Adds a new entry. +entry+ is either a GoogleDrive::AclEntry or a Hash with keys
33
32
  # :scope_type, :scope and :role. See GoogleDrive::AclEntry#scope_type and
34
33
  # GoogleDrive::AclEntry#role for the document of the fields.
@@ -36,35 +35,31 @@ module GoogleDrive
36
35
  # NOTE: This sends email to the new people.
37
36
  #
38
37
  # e.g.
38
+ # # A specific user can read or write.
39
39
  # spreadsheet.acl.push(
40
40
  # {:scope_type => "user", :scope => "example2@gmail.com", :role => "reader"})
41
41
  # spreadsheet.acl.push(
42
42
  # {:scope_type => "user", :scope => "example3@gmail.com", :role => "writer"})
43
+ # # Publish on the Web.
44
+ # spreadsheet.acl.push(
45
+ # {:scope_type => "default", :role => "reader"})
46
+ # # Anyone who knows the link can read.
47
+ # spreadsheet.acl.push(
48
+ # {:scope_type => "default", :with_key => true, :role => "reader"})
43
49
  def push(entry)
44
-
50
+
45
51
  entry = AclEntry.new(entry) if entry.is_a?(Hash)
46
-
52
+
47
53
  header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
48
- value_attr = entry.scope ? "value='#{h(entry.scope)}'" : ""
49
- xml = <<-EOS
50
- <entry
51
- xmlns='http://www.w3.org/2005/Atom'
52
- xmlns:gAcl='http://schemas.google.com/acl/2007'>
53
- <category scheme='http://schemas.google.com/g/2005#kind'
54
- term='http://schemas.google.com/acl/2007#accessRule'/>
55
- <gAcl:role value='#{h(entry.role)}'/>
56
- <gAcl:scope type='#{h(entry.scope_type)}' #{value_attr}/>
57
- </entry>
58
- EOS
59
54
  doc = @session.request(
60
- :post, @acls_feed_url, :data => xml, :header => header, :auth => :writely)
61
-
55
+ :post, @acls_feed_url, :data => entry.to_xml(), :header => header, :auth => :writely)
56
+
62
57
  entry.params = entry_to_params(doc.root)
63
58
  @acls.push(entry)
64
59
  return entry
65
-
60
+
66
61
  end
67
-
62
+
68
63
  # Deletes an ACL entry.
69
64
  #
70
65
  # e.g.
@@ -74,51 +69,47 @@ module GoogleDrive
74
69
  @session.request(:delete, entry.edit_url, :header => header, :auth => :writely)
75
70
  @acls.delete(entry)
76
71
  end
77
-
72
+
78
73
  def update_role(entry, role) #:nodoc:
79
-
74
+
80
75
  header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
81
- value_attr = entry.scope ? "value='#{h(entry.scope)}'" : ""
82
- xml = <<-EOS
83
- <entry
84
- xmlns='http://www.w3.org/2005/Atom'
85
- xmlns:gAcl='http://schemas.google.com/acl/2007'
86
- xmlns:gd='http://schemas.google.com/g/2005'
87
- gd:etag='#{h(entry.etag)}'>
88
- <category
89
- scheme='http://schemas.google.com/g/2005#kind'
90
- term='http://schemas.google.com/acl/2007#accessRule'/>
91
- <gAcl:role value='#{h(role)}'/>
92
- <gAcl:scope type='#{h(entry.scope_type)}' #{value_attr}/>
93
- </entry>
94
- EOS
95
76
  doc = @session.request(
96
- :put, entry.edit_url, :data => xml, :header => header, :auth => :writely)
97
-
77
+ :put, entry.edit_url, :data => entry.to_xml(), :header => header, :auth => :writely)
78
+
98
79
  entry.params = entry_to_params(doc.root)
99
80
  return entry
100
-
81
+
101
82
  end
102
-
83
+
103
84
  def inspect
104
85
  return "\#<%p %p>" % [self.class, @acls]
105
86
  end
106
-
87
+
107
88
  private
108
-
89
+
109
90
  def entry_to_params(entry)
110
- # TODO Support with-link roles.
91
+
92
+ if !entry.css("gAcl|withKey").empty?
93
+ with_key = true
94
+ role = entry.css("gAcl|withKey gAcl|role")[0]["value"]
95
+ else
96
+ with_key = false
97
+ role = entry.css("gAcl|role")[0]["value"]
98
+ end
99
+
111
100
  return {
112
101
  :acl => self,
113
102
  :scope_type => entry.css("gAcl|scope")[0]["type"],
114
103
  :scope => entry.css("gAcl|scope")[0]["value"],
115
- :role => entry.css("gAcl|role")[0]["value"],
104
+ :with_key => with_key,
105
+ :role => role,
116
106
  :title => entry.css("title").text,
117
107
  :edit_url => entry.css("link[rel='edit']")[0]["href"],
118
108
  :etag => entry["etag"],
119
109
  }
110
+
120
111
  end
121
-
112
+
122
113
  end
123
-
114
+
124
115
  end
@@ -1,44 +1,44 @@
1
1
  # Author: Guy Boertje <https://github.com/guyboertje>
2
2
  # Author: David R. Albrecht <https://github.com/eldavido>
3
3
  # Author: Hiroshi Ichikawa <http://gimite.net/>
4
+ # Author: Phuogn Nguyen <https://github.com/phuongnd08>
4
5
  # The license of this source is "New BSD Licence"
5
6
 
6
- # acl.rb, derived from https://github.com/guyboertje/gdata-spreadsheet-ruby/blob/master/lib/document.rb
7
- # more frankensteining of the original library
8
-
9
7
  module GoogleDrive
10
-
8
+
11
9
  # An entry of an ACL (access control list) of a spreadsheet.
12
10
  #
13
11
  # Use GoogleDrive::Acl#[] to get GoogleDrive::AclEntry object.
14
12
  #
15
13
  # This code is based on https://github.com/guyboertje/gdata-spreadsheet-ruby .
16
14
  class AclEntry
17
-
15
+
18
16
  include(Util)
19
-
20
- PARAM_NAMES = [:acl, :scope_type, :scope, :role, :title, :edit_url, :etag] #:nodoc:
21
-
17
+
18
+ PARAM_NAMES = [:acl, :scope_type, :scope, :with_key, :role, :title, :edit_url, :etag] #:nodoc:
19
+
22
20
  # +params+ is a Hash object with keys +:scope_type+, +:scope+ and +:role+.
23
21
  # See scope_type and role for the document of the fields.
24
22
  def initialize(params)
25
23
  @params = {:role => "reader"}
26
24
  for name, value in params
27
- if !PARAM_NAMES.include?(name)
25
+ if !name.is_a?(Symbol)
26
+ raise(ArgumentError, "Key must be Symbol, but is %p" % name)
27
+ elsif !PARAM_NAMES.include?(name)
28
28
  raise(ArgumentError, "Invalid key: %p" % name)
29
29
  end
30
30
  @params[name] = value
31
31
  end
32
32
  end
33
-
33
+
34
34
  attr_accessor(:params) #:nodoc:
35
-
35
+
36
36
  PARAM_NAMES.each() do |name|
37
37
  define_method(name) do
38
38
  return @params[name]
39
39
  end
40
40
  end
41
-
41
+
42
42
  # Changes the role of the scope.
43
43
  #
44
44
  # e.g.
@@ -46,13 +46,44 @@ module GoogleDrive
46
46
  def role=(role)
47
47
  @params[:acl].update_role(self, role)
48
48
  end
49
-
49
+
50
50
  def inspect
51
- return "\#<%p scope_type=%p, scope=%p, role=%p>" %
52
- [self.class, @params[:scope_type], @params[:scope], @params[:role]]
51
+ return "\#<%p scope_type=%p, scope=%p, with_key=%p, role=%p>" %
52
+ [self.class, @params[:scope_type], @params[:scope], @params[:with_key], @params[:role]]
53
53
  end
54
-
54
+
55
+ def to_xml() #:nodoc:
56
+
57
+ etag_attr = self.etag ? "gd:etag='#{h(self.etag)}'" : ""
58
+ value_attr = self.scope ? "value='#{h(self.scope)}'" : ""
59
+ if self.with_key
60
+ role_tag = <<-EOS
61
+ <gAcl:withKey key='[ACL KEY]'>
62
+ <gAcl:role value='#{h(self.role)}'/>
63
+ </gAcl:withKey>
64
+ EOS
65
+ else
66
+ role_tag = <<-EOS
67
+ <gAcl:role value='#{h(self.role)}'/>
68
+ EOS
69
+ end
70
+
71
+ return <<-EOS
72
+ <entry
73
+ xmlns='http://www.w3.org/2005/Atom'
74
+ xmlns:gAcl='http://schemas.google.com/acl/2007'
75
+ xmlns:gd='http://schemas.google.com/g/2005'
76
+ #{etag_attr}>
77
+ <category scheme='http://schemas.google.com/g/2005#kind'
78
+ term='http://schemas.google.com/acl/2007#accessRule'/>
79
+ #{role_tag}
80
+ <gAcl:scope type='#{h(self.scope_type)}' #{value_attr}/>
81
+ </entry>
82
+ EOS
83
+
84
+ end
85
+
55
86
  end
56
-
87
+
57
88
  end
58
89
 
@@ -34,7 +34,7 @@ module GoogleDrive
34
34
  # https://docs.google.com/feeds/default/private/full/folder%3Aroot/contents/folder%3Axxx
35
35
  # and deletion of the URL doesn't delete the file itself.
36
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)]
37
+ @document_feed_url = "%s/%s?v=3" % [DOCS_BASE_URL, CGI.escape(self.resource_id)]
38
38
  end
39
39
  @acl = nil
40
40
  end
@@ -193,9 +193,7 @@ module GoogleDrive
193
193
 
194
194
  # Renames title of the file.
195
195
  def rename(title)
196
-
197
- doc = @session.request(:get, self.document_feed_url, :auth => :writely)
198
- edit_url = doc.css("link[rel='edit']").first["href"]
196
+ edit_url = self.document_feed_entry.css("link[rel='edit']").first["href"]
199
197
  xml = <<-"EOS"
200
198
  <atom:entry
201
199
  xmlns:atom="http://www.w3.org/2005/Atom"
@@ -203,11 +201,8 @@ module GoogleDrive
203
201
  <atom:title>#{h(title)}</atom:title>
204
202
  </atom:entry>
205
203
  EOS
206
-
207
- @session.request(
208
- :put, edit_url, :data => xml, :auth => :writely,
209
- :header => {"Content-Type" => "application/atom+xml", "If-Match" => "*"})
210
-
204
+ header = {"Content-Type" => "application/atom+xml", "If-Match" => "*"}
205
+ @session.request(:put, edit_url, :data => xml, :auth => :writely, :header => header)
211
206
  end
212
207
 
213
208
  alias title= rename
@@ -110,7 +110,7 @@ module GoogleDrive
110
110
  def key_to_col(key)
111
111
  key = key.to_s()
112
112
  col = (1..@worksheet.num_cols).find(){ |c| @worksheet[1, c] == key }
113
- raise(GoogleDrive::Error, "Colunm doesn't exist: %p" % key) if !col
113
+ raise(GoogleDrive::Error, "Column doesn't exist: %p" % key) if !col
114
114
  return col
115
115
  end
116
116
 
@@ -132,12 +132,12 @@ module GoogleDrive
132
132
  end
133
133
 
134
134
  # Returns list of spreadsheets for the user as array of GoogleDrive::Spreadsheet.
135
- # You can specify query parameters described at
136
- # http://code.google.com/apis/spreadsheets/docs/2.0/reference.html#Parameters
135
+ # You can specify query parameters e.g. "title", "title-exact".
137
136
  #
138
137
  # e.g.
139
138
  # session.spreadsheets
140
139
  # session.spreadsheets("title" => "hoge")
140
+ # session.spreadsheets("title" => "hoge", "title-exact" => "true")
141
141
  def spreadsheets(params = {})
142
142
  query = encode_query(params)
143
143
  doc = request(
@@ -189,7 +189,7 @@ module GoogleDrive
189
189
  # Returns nil if not found. If multiple spreadsheets with the +title+ are found, returns
190
190
  # one of them.
191
191
  def spreadsheet_by_title(title)
192
- return spreadsheets({"title" => title})[0]
192
+ return spreadsheets({"title" => title, "title-exact" => "true"})[0]
193
193
  end
194
194
 
195
195
  # Returns GoogleDrive::Worksheet with given +url+.
@@ -282,6 +282,10 @@ module GoogleDrive
282
282
  # # Uploads without conversion:
283
283
  # session.upload_from_string(
284
284
  # "Hello world.", "Hello", :content_type => "text/plain", :convert => false)
285
+ #
286
+ # # Uploads and converts to a Google Spreadsheet:
287
+ # session.upload_from_string("hoge\tfoo\n", "Hoge", :content_type => "text/tab-separated-values")
288
+ # session.upload_from_string("hoge,foo\n", "Hoge", :content_type => "text/tsv")
285
289
  def upload_from_string(content, title = "Untitled", params = {})
286
290
  return upload_from_io(StringIO.new(content), title, params)
287
291
  end
@@ -290,7 +294,7 @@ module GoogleDrive
290
294
  # Returns a GoogleSpreadsheet::File object.
291
295
  #
292
296
  # e.g.
293
- # # Uploads and converts to a Google Docs document:
297
+ # # Uploads a text file and converts to a Google Docs document:
294
298
  # session.upload_from_file("/path/to/hoge.txt")
295
299
  #
296
300
  # # Uploads without conversion:
@@ -298,6 +302,12 @@ module GoogleDrive
298
302
  #
299
303
  # # Uploads with explicit content type:
300
304
  # session.upload_from_file("/path/to/hoge", "Hoge", :content_type => "text/plain")
305
+ #
306
+ # # Uploads a text file and converts to a Google Spreadsheet:
307
+ # session.upload_from_file("/path/to/hoge.tsv", "Hoge")
308
+ # session.upload_from_file("/path/to/hoge.csv", "Hoge")
309
+ # session.upload_from_file("/path/to/hoge", "Hoge", :content_type => "text/tab-separated-values")
310
+ # session.upload_from_file("/path/to/hoge", "Hoge", :content_type => "text/tsv")
301
311
  def upload_from_file(path, title = nil, params = {})
302
312
  file_name = ::File.basename(path)
303
313
  params = {:file_name => file_name}.merge(params)
@@ -351,20 +361,28 @@ module GoogleDrive
351
361
  :response_type => :response)
352
362
  upload_url = initial_response["location"]
353
363
 
354
- sent_bytes = 0
355
- while data = io.read(UPLOAD_CHUNK_SIZE)
356
- content_range = "bytes %d-%d/%d" % [
357
- sent_bytes,
358
- sent_bytes + data.bytesize - 1,
359
- total_bytes,
360
- ]
364
+ if total_bytes > 0
365
+ sent_bytes = 0
366
+ while data = io.read(UPLOAD_CHUNK_SIZE)
367
+ content_range = "bytes %d-%d/%d" % [
368
+ sent_bytes,
369
+ sent_bytes + data.bytesize - 1,
370
+ total_bytes,
371
+ ]
372
+ upload_header = {
373
+ "Content-Type" => content_type,
374
+ "Content-Range" => content_range,
375
+ }
376
+ doc = request(
377
+ :put, upload_url, :header => upload_header, :data => data, :auth => :writely)
378
+ sent_bytes += data.bytesize
379
+ end
380
+ else
361
381
  upload_header = {
362
382
  "Content-Type" => content_type,
363
- "Content-Range" => content_range,
364
383
  }
365
384
  doc = request(
366
- :put, upload_url, :header => upload_header, :data => data, :auth => :writely)
367
- sent_bytes += data.bytesize
385
+ :put, upload_url, :header => upload_header, :data => "", :auth => :writely)
368
386
  end
369
387
 
370
388
  return entry_element_to_file(doc.root)
@@ -59,7 +59,8 @@ module GoogleDrive
59
59
  end
60
60
 
61
61
  def h(str)
62
- return CGI.escapeHTML(str.to_s())
62
+ # Should also escape "\n" to keep it in cell contents.
63
+ return CGI.escapeHTML(str.to_s()).gsub(/\n/, '&#x0a;')
63
64
  end
64
65
 
65
66
  end
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.1
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-01 00:00:00.000000000 Z
12
+ date: 2012-10-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -87,6 +87,22 @@ dependencies:
87
87
  - - ! '>='
88
88
  - !ruby/object:Gem::Version
89
89
  version: 0.8.0
90
+ - !ruby/object:Gem::Dependency
91
+ name: debugger
92
+ requirement: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ type: :development
99
+ prerelease: false
100
+ version_requirements: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
90
106
  description: A library to read/write files/spreadsheets in Google Drive/Docs.
91
107
  email:
92
108
  - gimite+github@gmail.com