dewey 0.2.1 → 0.2.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.
@@ -1,3 +1,12 @@
1
+ ## 0.2.2 (October 27, 2010)
2
+
3
+ Changes:
4
+
5
+ - API Changes for get and put. All methods will use an options hash
6
+ rather than ordered options.
7
+ - Validation methods can accept either a string or a symbol
8
+ - More error-resistant handling of nil values passed to validation methods
9
+
1
10
  ## 0.2.1 (October 26, 2010)
2
11
 
3
12
  Additions:
data/README.md CHANGED
@@ -42,7 +42,7 @@ first operation.
42
42
  ### Putting a Document
43
43
 
44
44
  document = File.new('my_document.doc')
45
- resource = Dewey.put(document, 'My First Upload') # Returns the id when successful
45
+ resource = Dewey.put(document, :title => 'My First Upload') # Returns the id when successful
46
46
 
47
47
  ### Searching Documents
48
48
 
@@ -62,9 +62,9 @@ Upload your file
62
62
 
63
63
  Get it in various formats
64
64
 
65
- original = Dewey.get(id) # -> Tempfile
66
- pdf = Dewey.get(id, :pdf) # -> Tempfile
67
- html = Dewey.get(id, :html) # -> Tempfile
65
+ original = Dewey.get(id) #=> Tempfile
66
+ pdf = Dewey.get(id, :format => :pdf) #=> Tempfile
67
+ html = Dewey.get(id, :format => :html) #=> Tempfile
68
68
 
69
69
  A tempfile is returned, so you'll have to move it
70
70
 
@@ -73,4 +73,4 @@ A tempfile is returned, so you'll have to move it
73
73
  ### Deleting a Document
74
74
 
75
75
  id = Dewey.put(File.new('my_spreadsheet.xls'))
76
- result = Dewey.delete(id) # -> true
76
+ result = Dewey.delete(id) # -> true
@@ -32,37 +32,40 @@ module Dewey
32
32
  @@authenticator.authenticate!
33
33
  end
34
34
 
35
+ # Queries the document list for a particular title. Titles can be either
36
+ # full or partial matches. Matches are returned as an array of ids.
37
+ #
38
+ # @param [String] query The title to be matched
39
+ # @param [Hash] options Search options
40
+ # @option options [Symbol] :exact Setting this to `true` will force an
41
+ # exact match, with a maximum of one id returned
42
+ #
43
+ # @return [Array] An array of matched ids. No matches return an empty array
35
44
  def search(query, options = {})
36
- authenticate! unless authenticated?
37
-
38
45
  title = query.gsub(/\s+/, '+')
39
46
  headers = base_headers(false)
40
47
  url = "#{GOOGLE_FEED_URL}?title=#{title}"
41
48
  url << "&title-exact=true" if options[:exact]
42
49
  response = get_request(url, headers)
43
50
 
44
- case response
45
- when Net::HTTPOK
46
- extract_ids(response.body)
47
- else
48
- nil
49
- end
51
+ response.kind_of?(Net::HTTPOK) ? extract_ids(response.body) : []
50
52
  end
51
53
 
52
54
  # Upload a file to the account. A successful upload will return the resource
53
55
  # id, which is useful for downloading the file without doing a title search.
54
- # * file - A File reference
55
- # * title - An alternative title, to be used instead of the filename
56
56
  #
57
- def put(file, title = nil)
58
- authenticate! unless authenticated?
59
-
57
+ # @param [File] file An IOStream object that responds to path, size
58
+ # @param [Hash] options Options for uploading the file
59
+ # @option options [Symbol] :title An alternative title, to be used instead
60
+ # of the filename
61
+ #
62
+ # @return [String, Boolean] The id if upload was successful, false otherwise
63
+ def put(file, options = {})
60
64
  extension = File.extname(file.path).sub('.', '')
61
65
  basename = File.basename(file.path, ".#{extension}")
62
66
  mimetype = Dewey::Mime.mime_type(file)
63
67
  service = Dewey::Mime.guess_service(mimetype)
64
-
65
- title ||= basename
68
+ title = options[:title] || basename
66
69
 
67
70
  raise DeweyException, "Invalid file type: #{extension}" unless Dewey::Validation.valid_upload_format?(extension, service)
68
71
 
@@ -75,46 +78,57 @@ module Dewey
75
78
  file.rewind
76
79
 
77
80
  response = post_request(GOOGLE_FEED_URL, file.read.to_s, headers)
78
-
79
- case response
80
- when Net::HTTPCreated
81
- extract_ids(response.body)
81
+
82
+ if response.kind_of?(Net::HTTPCreated)
83
+ extract_ids(response.body).first
82
84
  else
83
85
  false
84
86
  end
85
87
  end
86
88
 
87
- # Download, or export more accurately, a file to a specified format
88
- # * rid - A resource id, for example +document:12345+
89
- # * format - The output format, see *_EXPORT_FORMATS for possiblibilites
89
+ # Download a file. You may optionally specify a format for export.
90
90
  #
91
- def get(rid, format = nil)
92
- authenticate! unless authenticated?
93
-
94
- spreadsheet = !! rid.match(/^spreadsheet/)
95
- id = rid.sub(/[a-z]+:/, '')
96
-
97
- url = ''
98
- url << (spreadsheet ? GOOGLE_SPREADSHEET_URL : GOOGLE_DOCUMENT_URL)
99
- url << (spreadsheet ? "?key=#{id}" : "?docID=#{id}")
100
- url << "&exportFormat=#{format.to_s}" unless format.nil?
101
-
102
- headers = base_headers
91
+ # @param [String] id A resource id, for example `document:12345`
92
+ # @param [Hash] options Options for downloading the document
93
+ # @option options [Symbol] :format The output format
94
+ #
95
+ # @return [Tempfile] The downloaded file
96
+ #
97
+ # @see Dewey::Validation::DOCUMENT_EXPORT_FORMATS
98
+ # @see Dewey::Validation::SPREADSHEET_EXPORT_FORMATS
99
+ # @see Dewey::Validation::PRESENTATION_EXPORT_FORMATS
100
+ def get(id, options = {})
101
+ service, id = id.split(':')
102
+ format = options[:format].to_s
103
+
104
+ raise DeweyException, "Invalid format: #{format}" unless Dewey::Validation.valid_export_format?(format, service)
105
+
106
+ url = ''
107
+ case service
108
+ when 'document'
109
+ url << GOOGLE_DOCUMENT_URL
110
+ url << "?docID=#{id}"
111
+ when 'spreadsheet'
112
+ url << GOOGLE_SPREADSHEET_URL
113
+ url << "?key=#{id}"
114
+ end
115
+
116
+ url << "&exportFormat=#{format}" unless format.blank?
103
117
 
104
- file = Tempfile.new([rid, format].join('.'))
118
+ file = Tempfile.new([id, format].join('.'))
105
119
  file.binmode
106
120
 
107
- open(url, headers) { |data| file.write data.read }
121
+ open(url, base_headers) { |data| file.write data.read }
108
122
 
109
123
  file
110
124
  end
111
125
 
112
- # Deletes a document referenced either by resource id.
113
- # * id - A resource id or exact file name matching a document in the account
126
+ # Deletes a document referenced by id.
127
+ #
128
+ # @param [String] id An id matching a document
114
129
  #
130
+ # @return [Boolean] `true` if delete was successful, `false` otherwise
115
131
  def delete(id)
116
- authenticate! unless authenticated?
117
-
118
132
  headers = base_headers(false)
119
133
  headers['If-Match'] = '*' # We don't care if others have modified
120
134
 
@@ -124,34 +138,49 @@ module Dewey
124
138
 
125
139
  response = delete_request(url, headers)
126
140
 
127
- case response
128
- when Net::HTTPOK
129
- true
130
- else
131
- false
132
- end
141
+ response.kind_of?(Net::HTTPOK)
133
142
  end
134
143
 
135
- # The same as delete, except that it will raise +Dewey::DeweyException+ if
144
+ # The same as delete, except that it will raise `Dewey::DeweyException` if
136
145
  # the request fails.
137
- #
146
+ #
147
+ # @see #delete
138
148
  def delete!(id)
139
149
  delete(id) || raise(DeweyException, "Unable to delete document")
140
150
  end
141
151
 
142
- # Convenience method for +put+, +get+, +delete+. Returns a Tempfile
143
- # with in the provided type. Note that if you omit the format option it will
144
- # simply upload the file and return it.
145
- # * file - The file that will be converted
146
- # * options - Takes :title and :format. See +upload+ for title, and +download+ for format.
152
+ [:search, :put, :get, :delete].each do |method|
153
+ aliased = "no_auto_authenticate_#{method.to_s}".to_sym
154
+ alias_method aliased, method
155
+
156
+ self.class_eval(%Q{
157
+ def #{method} *args
158
+ authenticate! unless authenticated?
159
+ #{aliased}(*args)
160
+ end
161
+ })
162
+ end
163
+
164
+ # Convenience method for `put`, `get`, `delete`.
165
+ #
166
+ # @param [File] file The file that will be converted
167
+ # @param [Hash] options Options for conversion
168
+ # @option options [Symbol] :title The title that the file will be stored
169
+ # under. Only useful if the conversion fails.
170
+ # @option options [Symbol] :format Format to convert to.
147
171
  #
172
+ # @return [Tempfile] The converted file
173
+ #
174
+ # @see #put
175
+ # @see #get
176
+ # @see #delete
148
177
  def convert(file, options = {})
149
- rid = put(file, options[:title])
150
- con = get(rid, options[:format])
178
+ id = put(file, options[:title])
179
+ converted = get(id, options[:format])
151
180
 
152
- delete(rid)
181
+ delete(id)
153
182
 
154
- con
183
+ converted
155
184
  end
156
185
 
157
186
  protected
@@ -187,27 +216,26 @@ module Dewey
187
216
  end
188
217
  end
189
218
 
190
- def base_headers(put_or_post = true) #:nodoc:
219
+ # A hash of default headers. Considers authentication and put/post headers.
220
+ #
221
+ # @param [Boolean] form If true the Content-Type will be set accordingly
222
+ # @return [Hash] Headers hash
223
+ def base_headers(form = true) #:nodoc:
191
224
  base = {}
192
225
  base['GData-Version'] = '3.0'
193
- base['Content-Type'] = 'application/x-www-form-urlencoded' if put_or_post
226
+ base['Content-Type'] = 'application/x-www-form-urlencoded' if form
194
227
  base['Authorization'] = "GoogleLogin auth=#{@@authenticator.token}" if authenticated?
195
228
 
196
229
  base
197
230
  end
198
231
 
232
+ # Parse the XML returned to pull out one or more document ids.
233
+ #
234
+ # @param [String] response An XML feed document
235
+ # @return [Array] Array of document ids
199
236
  def extract_ids(response) #:nodoc:
200
237
  xml = REXML::Document.new(response)
201
- ids = xml.elements.
202
- collect('//id') { |e| "#{$1}:#{$2}" if e.text =~ /.*(document|spreadsheet|presentation)(?:%3A|:)([0-9a-zA-Z_-]+)$/ }.
203
- reject(&:nil?)
204
-
205
- case ids.length
206
- when 0 then nil
207
- when 1 then ids.first
208
- else
209
- ids
210
- end
238
+ xml.elements.collect('//id') { |e| e.text.gsub('%3A', ':') }.reject(&:blank?)
211
239
  end
212
240
  end
213
241
  end
@@ -1,38 +1,63 @@
1
1
  module Dewey
2
2
 
3
- DOCUMENT_EXPORT_FORMATS = %w(txt odt pdf html rtf doc png zip)
4
- PRESENTATION_EXPORT_FORMATS = %w(swf pdf png ppt)
5
- SPREADSHEET_EXPORT_FORMATS = %W(xls csv pdf ods tsv html)
3
+ DOCUMENT_EXPORT_FORMATS = [:txt, :odt, :pdf, :html, :rtf, :doc, :png, :zip]
4
+ PRESENTATION_EXPORT_FORMATS = [:swf, :pdf, :png, :ppt]
5
+ SPREADSHEET_EXPORT_FORMATS = [:xls, :csv, :pdf, :ods, :tsv, :html]
6
6
 
7
+ # Utility methods to check that a format is accepted for a particular service
8
+ #
7
9
  class Validation
8
- # Determine wether or not a format is available for download.
9
- #
10
- # * format - The file format to check, i.e. 'txt', 'doc', 'pdf'
11
- # * service - The service that would be used. Must be document, presentation,
12
- # or spreadsheet.
13
- def self.valid_upload_format?(format, service = :document)
14
- case service
15
- when :document then Dewey::DOCUMENT_MIMETYPES.has_key?(format.to_sym)
16
- when :presentation then Dewey::PRESENTATION_MIMETYPES.has_key?(format.to_sym)
17
- when :spreadsheet then Dewey::SPREADSHEET_MIMETYPES.has_key?(format.to_sym)
18
- else
19
- raise DeweyException, "Unknown service: #{service}"
10
+
11
+ class << self
12
+ # Determine wether or not a format is available for download.
13
+ #
14
+ # @param [Symbol] format The file format to check, i.e. `:txt`, `:doc`, `:pdf`
15
+ # @param [Symbol] service The service that would be used. Must be
16
+ # `:document`, `:presentation`, or `:spreadsheet`.
17
+ #
18
+ # @return [Boolean] `true` if the format is supported, `false` otherwise
19
+ #
20
+ # @raise [DeweyException] Raised when an unknown service is given
21
+ def valid_upload_format?(format, service = nil)
22
+ format = format.to_sym
23
+ service = default_service(service)
24
+
25
+ case service
26
+ when :document then Dewey::DOCUMENT_MIMETYPES.has_key?(format)
27
+ when :presentation then Dewey::PRESENTATION_MIMETYPES.has_key?(format)
28
+ when :spreadsheet then Dewey::SPREADSHEET_MIMETYPES.has_key?(format)
29
+ else
30
+ raise DeweyException, "Unknown service: #{service}"
31
+ end
20
32
  end
21
- end
22
33
 
23
- # Determine whether or not a format is available for export.
24
- #
25
- # * format - The file format to check, i.e. 'txt', 'doc', 'pdf'
26
- # * service - The service that would be used. Must be document, presentation,
27
- # or spreadsheet.
28
- def self.valid_export_format?(format, service = :document)
29
- case service
30
- when :document then Dewey::DOCUMENT_EXPORT_FORMATS.include?(format)
31
- when :presentation then Dewey::PRESENTATION_EXPORT_FORMATS.include?(format)
32
- when :spreadsheet then Dewey::SPREADSHEET_EXPORT_FORMATS.include?(format)
33
- else
34
- raise DeweyException, "Unknown service: #{service}"
34
+ # Determine whether or not a format is available for export.
35
+ #
36
+ # @param [Symbol] format The file format to check, i.e. `:txt`, `:doc`, `:pdf`
37
+ # @param [Symbol] service The service that would be used. Must be
38
+ # `:document`, `:presentation`, or `:spreadsheet`.
39
+ #
40
+ # @return [Boolean] `true` if the format is supported, `false` otherwise
41
+ #
42
+ # @raise [DeweyException] Raised when an unknown service is given
43
+ def valid_export_format?(format, service = nil)
44
+ format = format.to_sym
45
+ service = default_service(service)
46
+
47
+ case service
48
+ when :document then Dewey::DOCUMENT_EXPORT_FORMATS.include?(format)
49
+ when :presentation then Dewey::PRESENTATION_EXPORT_FORMATS.include?(format)
50
+ when :spreadsheet then Dewey::SPREADSHEET_EXPORT_FORMATS.include?(format)
51
+ else
52
+ raise DeweyException, "Unknown service: #{service}"
53
+ end
54
+ end
55
+
56
+ protected
57
+
58
+ def default_service(service)
59
+ service.nil? ? :document : service.to_sym
35
60
  end
36
61
  end
37
62
  end
38
- end
63
+ end
@@ -1,3 +1,3 @@
1
1
  module Dewey
2
- VERSION = '0.2.1'
3
- end
2
+ VERSION = '0.2.2'
3
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 1
9
- version: 0.2.1
8
+ - 2
9
+ version: 0.2.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Parker Selbert
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-26 00:00:00 -05:00
17
+ date: 2010-10-28 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency