google_drive 0.3.11 → 1.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -7
  2. data/README.rdoc +27 -10
  3. data/lib/google_drive/acl.rb +40 -58
  4. data/lib/google_drive/acl_entry.rb +76 -56
  5. data/lib/google_drive/api_client_fetcher.rb +49 -0
  6. data/lib/google_drive/collection.rb +69 -71
  7. data/lib/google_drive/file.rb +171 -128
  8. data/lib/google_drive/session.rb +234 -268
  9. data/lib/google_drive/spreadsheet.rb +19 -163
  10. data/lib/google_drive/util.rb +126 -17
  11. data/lib/google_drive/worksheet.rb +108 -80
  12. data/lib/google_drive.rb +63 -57
  13. data/lib/google_drive_v1/acl.rb +115 -0
  14. data/lib/google_drive_v1/acl_entry.rb +100 -0
  15. data/lib/google_drive_v1/api_client_fetcher.rb +47 -0
  16. data/lib/google_drive_v1/authentication_error.rb +14 -0
  17. data/lib/{google_drive → google_drive_v1}/basic_fetcher.rb +1 -1
  18. data/lib/{google_drive → google_drive_v1}/client_login_fetcher.rb +2 -2
  19. data/lib/google_drive_v1/collection.rb +167 -0
  20. data/lib/google_drive_v1/error.rb +12 -0
  21. data/lib/google_drive_v1/file.rb +258 -0
  22. data/lib/google_drive_v1/list.rb +119 -0
  23. data/lib/google_drive_v1/list_row.rb +88 -0
  24. data/lib/{google_drive → google_drive_v1}/oauth1_fetcher.rb +1 -1
  25. data/lib/{google_drive → google_drive_v1}/oauth2_fetcher.rb +2 -2
  26. data/lib/google_drive_v1/record.rb +31 -0
  27. data/lib/google_drive_v1/session.rb +522 -0
  28. data/lib/google_drive_v1/spreadsheet.rb +248 -0
  29. data/lib/google_drive_v1/table.rb +60 -0
  30. data/lib/google_drive_v1/util.rb +73 -0
  31. data/lib/google_drive_v1/worksheet.rb +498 -0
  32. data/lib/google_drive_v1.rb +148 -0
  33. metadata +112 -77
  34. data/doc_src/google_drive/acl_entry.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA512:
3
- metadata.gz: aacfb80c76656613c5a1735977c6e39796a1df82a5a8a97944381c289362eaefdfee229b1c586f94378f46a8357caec0030f00b7a032404e27f2f93f69934137
4
- data.tar.gz: d8f9abf36d3406863e85520041adc04b5a1c9e64b344331982ed89ae6d2296d27d54fc13bb000bdf1ca0dce497f5f0a740ea40441ee18d2100c4cc6fdf4e724c
5
- SHA1:
6
- metadata.gz: cc0c279d89eeff98e5a5a85f82287db36343402d
7
- data.tar.gz: 9cb3dff31f112e16654f61bef9049b938487e33c
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 76b903fb2d84303774103ab6da528579367ce8a5
4
+ data.tar.gz: 04f591af34df950ba24d46a0ba0f6e099447f291
5
+ SHA512:
6
+ metadata.gz: e5253faaa7c32a502d296354cc1aa1728c79136d009f45fb05801c21b490b4f6ec81c6995d3486c5742b9ecf96f7408ced12d08b3b46d2c9a729ba1d3379a148
7
+ data.tar.gz: f52470706946884dd09e400b8fff2bd22af076947083910f58b92177566a80c96c8a9c833307c6f4ce9bc181ed7f6fa69723eff4a4e23faa31c0c91dd91a9c60
data/README.rdoc CHANGED
@@ -1,4 +1,4 @@
1
- This is a Ruby 1.9/2.0 library to read/write files/spreadsheets in Google Drive/Docs.
1
+ This is a Ruby 1.8/1.9/2.0 library to read/write files/spreadsheets in Google Drive/Docs.
2
2
 
3
3
  NOTE: This is NOT a library to create Google Drive App.
4
4
 
@@ -10,15 +10,31 @@ NOTE: This is NOT a library to create Google Drive App.
10
10
 
11
11
  = How to use
12
12
 
13
+ First, follow "Create a client ID and client secret" in {this page}[https://developers.google.com/drive/web/auth/web-server] to get a client ID and client secret for OAuth.
14
+
13
15
  Example to read/write files in Google Drive:
14
16
 
15
17
  require "rubygems"
18
+ require "google/api_client"
16
19
  require "google_drive"
17
-
18
- # Logs in.
19
- # You can also use OAuth. See document of
20
- # GoogleDrive.login_with_oauth for details.
21
- session = GoogleDrive.login("username@gmail.com", "mypassword")
20
+
21
+ # Authorizes with OAuth and gets an access token.
22
+ client = Google::APIClient.new
23
+ auth = client.authorization
24
+ auth.client_id = "YOUR CLIENT ID"
25
+ auth.client_secret = "YOUR CLIENT SECRET"
26
+ auth.scope =
27
+ "https://www.googleapis.com/auth/drive " +
28
+ "https://spreadsheets.google.com/feeds/"
29
+ auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
30
+ print("1. Open this page:\n%s\n\n" % auth.authorization_uri)
31
+ print("2. Enter the authorization code shown in the page: ")
32
+ auth.code = $stdin.gets.chomp
33
+ auth.fetch_access_token!
34
+ access_token = auth.access_token
35
+
36
+ # Creates a session.
37
+ session = GoogleDrive.login_with_oauth(access_token)
22
38
 
23
39
  # Gets list of remote files.
24
40
  for file in session.files
@@ -38,12 +54,13 @@ Example to read/write files in Google Drive:
38
54
  Example to read/write spreadsheets:
39
55
 
40
56
  require "rubygems"
57
+ require "google/api_client"
41
58
  require "google_drive"
59
+
60
+ # Same as the code above to get access_token...
42
61
 
43
- # Logs in.
44
- # You can also use OAuth. See document of
45
- # GoogleDrive.login_with_oauth for details.
46
- session = GoogleDrive.login("username@gmail.com", "mypassword")
62
+ # Creates a session.
63
+ session = GoogleDrive.login(access_token)
47
64
 
48
65
  # First worksheet of
49
66
  # https://docs.google.com/spreadsheet/ccc?key=pz7XtlQC-PYx-jrVMJErTcg
@@ -18,15 +18,16 @@ module GoogleDrive
18
18
  include(Util)
19
19
  extend(Forwardable)
20
20
 
21
- def initialize(session, acls_feed_url) #:nodoc:
21
+ def initialize(session, file) #:nodoc:
22
22
  @session = session
23
- @acls_feed_url = acls_feed_url
24
- header = {"GData-Version" => "3.0"}
25
- doc = @session.request(:get, @acls_feed_url, :header => header, :auth => :writely)
26
- @acls = doc.css("entry").map(){ |e| AclEntry.new(entry_to_params(e)) }
23
+ @file = file
24
+ api_result = @session.execute!(
25
+ :api_method => @session.drive.permissions.list,
26
+ :parameters => { "fileId" => @file.id })
27
+ @entries = api_result.data.items.map(){ |i| AclEntry.new(i, self) }
27
28
  end
28
29
 
29
- def_delegators(:@acls, :size, :[], :each)
30
+ def_delegators(:@entries, :size, :[], :each)
30
31
 
31
32
  # Adds a new entry. +entry+ is either a GoogleDrive::AclEntry or a Hash with keys
32
33
  # :scope_type, :scope and :role. See GoogleDrive::AclEntry#scope_type and
@@ -37,27 +38,28 @@ module GoogleDrive
37
38
  # e.g.
38
39
  # # A specific user can read or write.
39
40
  # spreadsheet.acl.push(
40
- # {:scope_type => "user", :scope => "example2@gmail.com", :role => "reader"})
41
+ # {:type => "user", :value => "example2@gmail.com", :role => "reader"})
41
42
  # spreadsheet.acl.push(
42
- # {:scope_type => "user", :scope => "example3@gmail.com", :role => "writer"})
43
+ # {:type => "user", :value => "example3@gmail.com", :role => "writer"})
43
44
  # # Publish on the Web.
44
45
  # spreadsheet.acl.push(
45
- # {:scope_type => "default", :role => "reader"})
46
+ # {:type => "anyone", :role => "reader"})
46
47
  # # Anyone who knows the link can read.
47
48
  # spreadsheet.acl.push(
48
- # {:scope_type => "default", :with_key => true, :role => "reader"})
49
- def push(entry)
50
-
51
- entry = AclEntry.new(entry) if entry.is_a?(Hash)
52
-
53
- header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml;charset=utf-8"}
54
- doc = @session.request(
55
- :post, @acls_feed_url, :data => entry.to_xml(), :header => header, :auth => :writely)
56
-
57
- entry.params = entry_to_params(doc.root)
58
- @acls.push(entry)
59
- return entry
60
-
49
+ # {:type => "anyone", :withLink => true, :role => "reader"})
50
+ #
51
+ # See here for parameter detais:
52
+ # https://developers.google.com/drive/v2/reference/permissions/insert
53
+ def push(params_or_entry)
54
+ entry = params_or_entry.is_a?(AclEntry) ? params_or_entry : AclEntry.new(params_or_entry)
55
+ new_permission = @session.drive.permissions.insert.request_schema.new(entry.params)
56
+ api_result = @session.execute!(
57
+ :api_method => @session.drive.permissions.insert,
58
+ :body_object => new_permission,
59
+ :parameters => { "fileId" => @file.id })
60
+ new_entry = AclEntry.new(api_result.data, self)
61
+ @entries.push(new_entry)
62
+ return new_entry
61
63
  end
62
64
 
63
65
  # Deletes an ACL entry.
@@ -65,49 +67,29 @@ module GoogleDrive
65
67
  # e.g.
66
68
  # spreadsheet.acl.delete(spreadsheet.acl[1])
67
69
  def delete(entry)
68
- header = {"GData-Version" => "3.0"}
69
- @session.request(:delete, entry.edit_url_internal, :header => header, :auth => :writely)
70
- @acls.delete(entry)
70
+ @session.execute!(
71
+ :api_method => @session.drive.permissions.delete,
72
+ :parameters => {
73
+ "fileId" => @file.id,
74
+ "permissionId" => entry.id,
75
+ })
76
+ @entries.delete(entry)
71
77
  end
72
78
 
73
79
  def update_role(entry) #:nodoc:
74
-
75
- header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml;charset=utf-8"}
76
- doc = @session.request(
77
- :put, entry.edit_url_internal, :data => entry.to_xml(), :header => header, :auth => :writely)
78
-
79
- entry.params = entry_to_params(doc.root)
80
+ api_result = @session.execute!(
81
+ :api_method => @session.drive.permissions.update,
82
+ :body_object => entry.api_permission,
83
+ :parameters => {
84
+ "fileId" => @file.id,
85
+ "permissionId" => entry.id,
86
+ })
87
+ entry.api_permission = api_result.data
80
88
  return entry
81
-
82
89
  end
83
90
 
84
91
  def inspect
85
- return "\#<%p %p>" % [self.class, @acls]
86
- end
87
-
88
- private
89
-
90
- def entry_to_params(entry)
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
-
100
- return {
101
- :acl => self,
102
- :scope_type => entry.css("gAcl|scope")[0]["type"],
103
- :scope => entry.css("gAcl|scope")[0]["value"],
104
- :with_key => with_key,
105
- :role => role,
106
- :title => entry.css("title").text,
107
- :edit_url => entry.css("link[rel='edit']")[0]["href"],
108
- :etag => entry["etag"],
109
- }
110
-
92
+ return "\#<%p %p>" % [self.class, @entries]
111
93
  end
112
94
 
113
95
  end
@@ -15,83 +15,103 @@ module GoogleDrive
15
15
 
16
16
  include(Util)
17
17
 
18
- PARAM_NAMES = [:acl, :scope_type, :scope, :with_key, :role, :title, :edit_url, :etag] #:nodoc:
19
-
20
- # +params+ is a Hash object with keys +:scope_type+, +:scope+ and +:role+.
21
- # See scope_type and role for the document of the fields.
22
- def initialize(params)
23
- @params = {:role => "reader"}
24
- for name, value in params
25
- if !name.is_a?(Symbol)
26
- raise(ArgumentError, "Key must be Symbol, but is %p" % name)
27
- elsif !PARAM_NAMES.include?(name)
28
- raise(ArgumentError, "Invalid key: %p" % name)
29
- end
30
- @params[name] = value
18
+ # +params_or_api_permission+ is a Hash object with keys +:type+, +:value+, +:role+ and +:withLink+.
19
+ # See GoogleDrive::Acl#push for description of the parameters.
20
+ def initialize(params_or_api_permission, acl = nil)
21
+ @acl = acl
22
+ if acl
23
+ @api_permission = params_or_api_permission
24
+ @params = nil
25
+ delegate_api_methods(self, @api_permission)
26
+ else
27
+ @api_permission = nil
28
+ @params = convert_params(params_or_api_permission)
31
29
  end
32
30
  end
33
31
 
34
- attr_accessor(:params) #:nodoc:
32
+ attr_reader(:acl)
33
+ attr_reader(:params) #:nodoc:
34
+ attr_accessor(:api_permission) #:nodoc:
35
35
 
36
- PARAM_NAMES.each() do |name|
37
- define_method(name) do
38
- return @params[name]
39
- end
36
+ # The role given to the scope. One of:
37
+ # - "owner": The owner.
38
+ # - "writer": With read/write access.
39
+ # - "reader": With read-only access.
40
+ def role
41
+ return @params ? @params["role"] : @api_permission.role
42
+ end
43
+
44
+ # Type of the scope. One of:
45
+ #
46
+ # - "user": value is a user's email address.
47
+ # - "group": value is a Google Group email address.
48
+ # - "domain": value is a Google Apps domain.
49
+ # - "anyone": Publicly shared with all users. value is +nil+.
50
+ def type
51
+ return @params ? @params["type"] : @api_permission.type
52
+ end
53
+
54
+ alias scope_type type
55
+
56
+ def additional_roles
57
+ return @params ? @params["additionalRoles"] : @api_permission.additional_roles
40
58
  end
41
59
 
42
- def edit_url
43
- warn(
44
- "WARNING: GoogleDrive::AclEntry\#edit_url is deprecated and will be removed in the next version.")
45
- return self.edit_url_internal
60
+ def id
61
+ return @params ? @params["id"] : @api_permission.id
46
62
  end
47
63
 
48
- def edit_url_internal #:nodoc:
49
- return @params[:edit_url]
64
+ # The value of the scope. See type.
65
+ def value
66
+ return @params ? @params["value"] : @api_permission.value
50
67
  end
51
68
 
69
+ alias scope value
70
+
71
+ # If +true+, the file is shared only with people who know the link.
72
+ def with_link
73
+ return @params ? @params["withLink"] : @api_permission.with_link
74
+ end
75
+
76
+ alias with_key with_link
77
+
52
78
  # Changes the role of the scope.
53
79
  #
54
80
  # e.g.
55
81
  # spreadsheet.acl[1].role = "writer"
56
82
  def role=(role)
57
- @params[:role] = role
58
- @params[:acl].update_role(self)
83
+ if @params
84
+ @params["role"] = role
85
+ else
86
+ @api_permission.role = role
87
+ @acl.update_role(self)
88
+ end
59
89
  end
60
90
 
61
91
  def inspect
62
- return "\#<%p scope_type=%p, scope=%p, with_key=%p, role=%p>" %
63
- [self.class, @params[:scope_type], @params[:scope], @params[:with_key], @params[:role]]
92
+ return "\#<%p type=%p, name=%p, role=%p>" %
93
+ [self.class, self.type, self.name, self.role]
64
94
  end
65
95
 
66
- def to_xml() #:nodoc:
67
-
68
- etag_attr = self.etag ? "gd:etag='#{h(self.etag)}'" : ""
69
- value_attr = self.scope ? "value='#{h(self.scope)}'" : ""
70
- if self.with_key
71
- role_tag = <<-EOS
72
- <gAcl:withKey key='[ACL KEY]'>
73
- <gAcl:role value='#{h(self.role)}'/>
74
- </gAcl:withKey>
75
- EOS
76
- else
77
- role_tag = <<-EOS
78
- <gAcl:role value='#{h(self.role)}'/>
79
- EOS
96
+ private
97
+
98
+ # Normalizes the key to String, and converts parameters in the old version.
99
+ def convert_params(orig_params)
100
+ new_params = {}
101
+ for k, v in orig_params
102
+ k = k.to_s()
103
+ case k
104
+ when "scope_type"
105
+ new_params["type"] = (v == "default" ? "anyone" : v)
106
+ when "scope"
107
+ new_params["value"] = v
108
+ when "with_key"
109
+ new_params["withLink"] = v
110
+ else
111
+ new_params[k] = v
112
+ end
80
113
  end
81
-
82
- return <<-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
- #{etag_attr}>
88
- <category scheme='http://schemas.google.com/g/2005#kind'
89
- term='http://schemas.google.com/acl/2007#accessRule'/>
90
- #{role_tag}
91
- <gAcl:scope type='#{h(self.scope_type)}' #{value_attr}/>
92
- </entry>
93
- EOS
94
-
114
+ return new_params
95
115
  end
96
116
 
97
117
  end
@@ -0,0 +1,49 @@
1
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
2
+ # The license of this source is "New BSD Licence"
3
+
4
+ require "net/https"
5
+ require "uri"
6
+ Net::HTTP.version_1_2
7
+
8
+
9
+ module GoogleDrive
10
+
11
+ class ApiClientFetcher
12
+
13
+ class Response
14
+
15
+ def initialize(client_response)
16
+ @client_response = client_response
17
+ end
18
+
19
+ def code
20
+ return @client_response.status.to_s()
21
+ end
22
+
23
+ def body
24
+ return @client_response.body
25
+ end
26
+
27
+ attr_reader(:client_response)
28
+
29
+ end
30
+
31
+ def initialize(client)
32
+ @client = client
33
+ @drive = @client.discovered_api("drive", "v2")
34
+ end
35
+
36
+ attr_reader(:client, :drive)
37
+
38
+ def request_raw(method, url, data, extra_header, auth)
39
+ client_response = @client.execute(
40
+ :http_method => method,
41
+ :uri => url,
42
+ :body => data,
43
+ :headers => extra_header)
44
+ return Response.new(client_response)
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -13,107 +13,97 @@ module GoogleDrive
13
13
  class Collection < GoogleDrive::File
14
14
 
15
15
  include(Util)
16
-
17
- ROOT_URL = "#{DOCS_BASE_URL}/folder%3Aroot" #:nodoc:
18
16
 
19
17
  alias collection_feed_url document_feed_url
20
18
 
21
- def contents_url
22
- if self.root?
23
- # The root collection doesn't have document feed.
24
- return concat_url(ROOT_URL, "/contents")
25
- else
26
- return self.document_feed_entry_internal.css(
27
- "content[type='application/atom+xml;type=feed']")[0]["src"]
28
- end
29
- end
30
-
31
- # Title of the collection.
32
- #
33
- # Set <tt>params[:reload]</tt> to true to force reloading the title.
34
- def title(params = {})
35
- if self.root?
36
- # The root collection doesn't have document feed.
37
- return nil
38
- else
39
- return super
40
- end
41
- end
42
-
43
- def resource_id
44
- return self.root? ? nil : super
45
- end
46
-
47
19
  # Adds the given GoogleDrive::File to the collection.
48
20
  def add(file)
49
- header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml;charset=utf-8"}
50
- xml = <<-"EOS"
51
- <entry xmlns="http://www.w3.org/2005/Atom">
52
- <id>#{h(file.document_feed_url)}</id>
53
- </entry>
54
- EOS
55
- @session.request(
56
- :post, self.contents_url, :data => xml, :header => header, :auth => :writely)
21
+ new_child = @session.drive.children.insert.request_schema.new({
22
+ "id" => file.id,
23
+ })
24
+ @session.execute!(
25
+ :api_method => @session.drive.children.insert,
26
+ :body_object => new_child,
27
+ :parameters => {
28
+ "folderId" => self.id,
29
+ "childId" => file.id,
30
+ })
57
31
  return nil
58
32
  end
59
33
 
60
34
  # Creates a sub-collection with given title. Returns GoogleDrive::Collection object.
61
35
  def create_subcollection(title)
62
- header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml;charset=utf-8"}
63
- xml = <<-EOS
64
- <entry xmlns="http://www.w3.org/2005/Atom">
65
- <category scheme="http://schemas.google.com/g/2005#kind"
66
- term="http://schemas.google.com/docs/2007#folder"/>
67
- <title>#{h(title)}</title>
68
- </entry>
69
- EOS
70
- doc = @session.request(
71
- :post, contents_url, :data => xml, :header => header, :auth => :writely)
72
- return @session.entry_element_to_file(doc)
36
+ file = @session.drive.files.insert.request_schema.new({
37
+ "title" => title,
38
+ "mimeType" => "application/vnd.google-apps.folder",
39
+ "parents" => [{"id" => self.id}],
40
+ })
41
+ api_result = @session.execute!(
42
+ :api_method => @session.drive.files.insert,
43
+ :body_object => file)
44
+ return @session.wrap_api_file(api_result.data)
73
45
  end
74
46
 
75
47
  # Removes the given GoogleDrive::File from the collection.
76
48
  def remove(file)
77
- url = to_v3_url("#{contents_url}/#{file.resource_id}")
78
- @session.request(:delete, url, :auth => :writely, :header => {"If-Match" => "*"})
49
+ @session.execute!(
50
+ :api_method => @session.drive.children.delete,
51
+ :parameters => {
52
+ "folderId" => self.id,
53
+ "childId" => file.id,
54
+ })
55
+ return nil
79
56
  end
80
57
 
81
58
  # Returns true if this is a root collection
82
59
  def root?
83
- self.document_feed_url == ROOT_URL
60
+ return self.api_file.parents.empty?
84
61
  end
85
62
 
86
63
  # Returns all the files (including spreadsheets, documents, subcollections) in the collection.
87
64
  #
88
- # You can specify query parameters described at
89
- # https://developers.google.com/google-apps/documents-list/#getting_a_list_of_documents_and_files
65
+ # You can specify parameters documented at
66
+ # https://developers.google.com/drive/v2/reference/files/list
90
67
  #
91
68
  # e.g.
92
69
  #
93
70
  # # Gets all the files in collection, including subcollections.
94
71
  # collection.files
95
- #
96
72
  # # Gets only files with title "hoge".
97
- # collection.files("title" => "hoge", "title-exact" => "true")
98
- def files(params = {})
99
- return files_with_type(nil, params)
73
+ # collection.files("q" => "title = 'hoge'")
74
+ # # Same as above with a placeholder.
75
+ # collection.files("q" => ["title = ?", "hoge"])
76
+ #
77
+ # By default, it returns the first 100 files. See document of GoogleDrive::Session#files method
78
+ # for how to get all files.
79
+ def files(params = {}, &block)
80
+ return files_with_type(nil, params, &block)
100
81
  end
101
82
 
102
83
  alias contents files
103
84
 
104
85
  # Returns all the spreadsheets in the collection.
105
- def spreadsheets(params = {})
106
- return files_with_type("spreadsheet", params)
86
+ #
87
+ # By default, it returns the first 100 spreadsheets. See document of GoogleDrive::Session#files method
88
+ # for how to get all spreadsheets.
89
+ def spreadsheets(params = {}, &block)
90
+ return files_with_type("application/vnd.google-apps.spreadsheet", params, &block)
107
91
  end
108
92
 
109
93
  # Returns all the Google Docs documents in the collection.
110
- def documents(params = {})
111
- return files_with_type("document", params)
94
+ #
95
+ # By default, it returns the first 100 documents. See document of GoogleDrive::Session#files method
96
+ # for how to get all documents.
97
+ def documents(params = {}, &block)
98
+ return files_with_type("application/vnd.google-apps.document", params, &block)
112
99
  end
113
100
 
114
101
  # Returns all its subcollections.
115
- def subcollections(params = {})
116
- return files_with_type("folder", params)
102
+ #
103
+ # By default, it returns the first 100 subcollections. See document of GoogleDrive::Session#files method
104
+ # for how to get all subcollections.
105
+ def subcollections(params = {}, &block)
106
+ return files_with_type("application/vnd.google-apps.folder", params, &block)
117
107
  end
118
108
 
119
109
  # Returns a file (can be a spreadsheet, document, subcollection or other files) in the
@@ -132,7 +122,12 @@ module GoogleDrive
132
122
  #
133
123
  # If given an Array, does a recursive subcollection traversal.
134
124
  def subcollection_by_title(title)
135
- return file_by_title_with_type(title, "folder")
125
+ return file_by_title_with_type(title, "application/vnd.google-apps.folder")
126
+ end
127
+
128
+ # Returns URL of the deprecated contents feed.
129
+ def contents_url
130
+ self.document_feed_url + "/contents"
136
131
  end
137
132
 
138
133
  protected
@@ -147,19 +142,22 @@ module GoogleDrive
147
142
  return parent && parent.file_by_title_with_type(rel_path[-1], type)
148
143
  end
149
144
  else
150
- return files_with_type(type, "title" => title, "title-exact" => "true")[0]
145
+ return files_with_type(type, "q" => ["title = ?", title], "maxResults" => 1)[0]
151
146
  end
152
147
  end
153
148
 
154
149
  private
155
150
 
156
- def files_with_type(type, params = {})
157
- contents_url = self.contents_url
158
- contents_url = concat_url(contents_url, "/-/#{type}") if type
159
- contents_url = concat_url(contents_url, "?" + encode_query(params))
160
- header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml;charset=utf-8"}
161
- doc = @session.request(:get, contents_url, :header => header, :auth => :writely)
162
- return doc.css("feed > entry").map(){ |e| @session.entry_element_to_file(e) }
151
+ def files_with_type(type, params = {}, &block)
152
+ params = convert_params(params)
153
+ query = construct_and_query([
154
+ ["? in parents", self.id],
155
+ type ? ["mimeType = ?", type] : nil,
156
+ params["q"],
157
+ ])
158
+ params = params.merge({"q" => query})
159
+ # This is faster than calling children.list and then files.get for each file.
160
+ return @session.files(params, &block)
163
161
  end
164
162
 
165
163
  end