Class: GoogleDrive::File

Inherits:
Object
  • Object
show all
Includes:
Util
Defined in:
lib/google_drive/file.rb

Overview

A file in Google Drive, including Google Docs document/spreadsheet/presentation.

Use GoogleDrive::Session#files or GoogleDrive::Session#file_by_title to get this object.

Direct Known Subclasses

Collection, Spreadsheet

Constant Summary

Constants included from Util

Util::DOCS_BASE_URL, Util::EXT_TO_CONTENT_TYPE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Util

concat_url, encode_query, h, to_v3_url

Constructor Details

#initialize(session, entry_or_url) ⇒ File

:nodoc:



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/google_drive/file.rb', line 21

def initialize(session, entry_or_url) #:nodoc:
  @session = session
  if !entry_or_url
    # TODO Delete this after editing spreadsheet.rb.
    @document_feed_entry = nil
    @document_feed_url = entry_or_url
  elsif entry_or_url.is_a?(String)
    @document_feed_entry = nil
    @document_feed_url = entry_or_url
  else
    @document_feed_entry = entry_or_url
    # This is usually equal to the URL in <link rel="self">. But the URL in
    # <link rel="self"> in collection feed is e.g.
    # https://docs.google.com/feeds/default/private/full/folder%3Aroot/contents/folder%3Axxx
    # and deletion of the URL doesn't delete the file itself.
    # So we construct the URL here using resource ID instead.
    @document_feed_url = "%s/%s?v=3" % [DOCS_BASE_URL, CGI.escape(self.resource_id)]
  end
  @acl = nil
end

Instance Attribute Details

#document_feed_urlObject (readonly)

URL of feed used in document list feed API.



43
44
45
# File 'lib/google_drive/file.rb', line 43

def document_feed_url
  @document_feed_url
end

Instance Method Details

#acl(params = {}) ⇒ Object

Returns GoogleDrive::Acl object for the file.

With the object, you can see and modify people who can access the file. Modifications take effect immediately.

Set params[:reload] to true to force reloading the data.

e.g.

# Dumps people who have access:
for entry in file.acl
  p [entry.scope_type, entry.scope, entry.role]
  # => e.g. ["user", "[email protected]", "owner"]
end

# Shares the file with new people:
# NOTE: This sends email to the new people.
file.acl.push(
    {:scope_type => "user", :scope => "[email protected]", :role => "reader"})
file.acl.push(
    {:scope_type => "user", :scope => "[email protected]", :role => "writer"})

# Changes the role of a person:
file.acl[1].role = "writer"

# Deletes an ACL entry:
file.acl.delete(file.acl[1])


236
237
238
239
240
241
# File 'lib/google_drive/file.rb', line 236

def acl(params = {})
  if !@acl || params[:reload]
    @acl = Acl.new(@session, self.acl_feed_url)
  end
  return @acl
end

#acl_feed_urlObject

ACL feed URL of the file.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/google_drive/file.rb', line 81

def acl_feed_url
  orig_acl_feed_url = self.document_feed_entry.css(
      "gd|feedLink[rel='http://schemas.google.com/acl/2007#accessControlList']")[0]["href"]
  case orig_acl_feed_url
    when %r{^https?://docs.google.com/feeds/default/private/full/.*/acl(\?.*)?$}
      return orig_acl_feed_url
    when %r{^https?://docs.google.com/feeds/acl/private/full/([^\?]*)(\?.*)?$}
      # URL of old API version. Converts to v3 URL.
      return "#{DOCS_BASE_URL}/#{$1}/acl"
    else
      raise(GoogleDrive::Error,
        "ACL feed URL is in unknown format: #{orig_acl_feed_url}")
  end
end

#available_content_typesObject

Content types you can specify in methods download_to_file, download_to_string, download_to_io .



98
99
100
# File 'lib/google_drive/file.rb', line 98

def available_content_types
  return self.document_feed_entry.css("content").map(){ |c| c["type"] }
end

#delete(permanent = false) ⇒ Object

If permanent is false, moves the file to the trash. If permanent is true, deletes the file permanently.



187
188
189
190
191
192
# File 'lib/google_drive/file.rb', line 187

def delete(permanent = false)
  url = to_v3_url(self.document_feed_url)
  url = concat_url(url, "?delete=true") if permanent
  @session.request(:delete, url,
    :auth => :writely, :header => {"If-Match" => "*"})
end

#document_feed_entry(params = {}) ⇒ Object

<entry> element of document list feed as Nokogiri::XML::Element.

Set params[:reload] to true to force reloading the feed.



48
49
50
51
52
53
54
# File 'lib/google_drive/file.rb', line 48

def document_feed_entry(params = {})
  if !@document_feed_entry || params[:reload]
    @document_feed_entry =
        @session.request(:get, self.document_feed_url, :auth => :writely).css("entry")[0]
  end
  return @document_feed_entry
end

#download_to_file(path, params = {}) ⇒ Object

Downloads the file to a local file.

e.g.

file.download_to_file("/path/to/hoge.txt")
file.download_to_file("/path/to/hoge", :content_type => "text/plain")


107
108
109
110
111
112
113
114
115
116
# File 'lib/google_drive/file.rb', line 107

def download_to_file(path, params = {})
  params = params.dup()
  if !params[:content_type]
    params[:content_type] = EXT_TO_CONTENT_TYPE[::File.extname(path).downcase]
    params[:content_type_is_hint] = true
  end
  open(path, "wb") do |f|
    download_to_io(f, params)
  end
end

#download_to_io(io, params = {}) ⇒ Object

Downloads the file and writes it to io.



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/google_drive/file.rb', line 130

def download_to_io(io, params = {})
  all_contents = self.document_feed_entry.css("content")
  if params[:content_type] && (!params[:content_type_is_hint] || all_contents.size > 1)
    contents = all_contents.select(){ |c| c["type"] == params[:content_type] }
  else
    contents = all_contents
  end
  if contents.size == 1
    url = contents[0]["src"]
  else
    if contents.empty?
      raise(GoogleDrive::Error,
          ("Downloading with content type %p not supported for this file. " +
           "Specify one of these to content_type: %p") %
          [params[:content_type], self.available_content_types])
    else
      raise(GoogleDrive::Error,
          ("Multiple content types are available for this file. " +
           "Specify one of these to content_type: %p") %
          [self.available_content_types])
    end
  end
  # TODO Use streaming if possible.
  body = @session.request(:get, url, :response_type => :raw, :auth => :writely)
  io.write(body)
end

#download_to_string(params = {}) ⇒ Object

Downloads the file and returns as a String.

e.g.

file.download_to_string()                               #=> "Hello world."
file.download_to_string(:content_type => "text/plain")  #=> "Hello world."


123
124
125
126
127
# File 'lib/google_drive/file.rb', line 123

def download_to_string(params = {})
  sio = StringIO.new()
  download_to_io(sio, params)
  return sio.string
end

#human_urlObject

URL to view/edit the file in a Web browser.

e.g. “docs.google.com/file/d/xxxx/edit



76
77
78
# File 'lib/google_drive/file.rb', line 76

def human_url
  return self.document_feed_entry.css("link[rel='alternate']")[0]["href"]
end

#inspectObject



243
244
245
246
247
# File 'lib/google_drive/file.rb', line 243

def inspect
  fields = {:document_feed_url => self.document_feed_url}
  fields[:title] = self.title if @document_feed_entry
  return "\#<%p %s>" % [self.class, fields.map(){ |k, v| "%s=%p" % [k, v] }.join(", ")]
end

#rename(title) ⇒ Object Also known as: title=

Renames title of the file.



195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/google_drive/file.rb', line 195

def rename(title)
  edit_url = self.document_feed_entry.css("link[rel='edit']").first["href"]
  xml = <<-"EOS"
    <atom:entry
        xmlns:atom="http://www.w3.org/2005/Atom"
        xmlns:docs="http://schemas.google.com/docs/2007">
      <atom:title>#{h(title)}</atom:title>
    </atom:entry>
  EOS
  header = {"Content-Type" => "application/atom+xml", "If-Match" => "*"}
  @session.request(:put, edit_url, :data => xml, :auth => :writely, :header => header)
end

#resource_idObject

Resource ID.



57
58
59
# File 'lib/google_drive/file.rb', line 57

def resource_id
  return self.document_feed_entry.css("gd|resourceId").text
end

#resource_typeObject

The type of resourse. e.g. “document”, “spreadsheet”, “folder”



62
63
64
# File 'lib/google_drive/file.rb', line 62

def resource_type
  return self.resource_id.split(/:/)[0]
end

#title(params = {}) ⇒ Object

Title of the file.

Set params[:reload] to true to force reloading the title.



69
70
71
# File 'lib/google_drive/file.rb', line 69

def title(params = {})
  return document_feed_entry(params).css("title").text
end

#update_from_file(path, params = {}) ⇒ Object

Updates the file with the content of the local file.

e.g.

file.update_from_file("/path/to/hoge.txt")


161
162
163
164
165
166
# File 'lib/google_drive/file.rb', line 161

def update_from_file(path, params = {})
  params = {:file_name => ::File.basename(path)}.merge(params)
  open(path, "rb") do |f|
    update_from_io(f, params)
  end
end

#update_from_io(io, params = {}) ⇒ Object

Reads content from io and updates the file with the content.



177
178
179
180
181
182
183
# File 'lib/google_drive/file.rb', line 177

def update_from_io(io, params = {})
  params = {:header => {"If-Match" => "*"}}.merge(params)
  initial_url = self.document_feed_entry.css(
      "link[rel='http://schemas.google.com/g/2005#resumable-edit-media']")[0]["href"]
  @document_feed_entry = @session.upload_raw(
      :put, initial_url, io, self.title, params)
end

#update_from_string(content, params = {}) ⇒ Object

Updates the file with content.

e.g.

file.update_from_string("Good bye, world.")


172
173
174
# File 'lib/google_drive/file.rb', line 172

def update_from_string(content, params = {})
  update_from_io(StringIO.new(content), params)
end