google_drive 0.3.1 → 0.3.2

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