box-api 0.1.7 → 0.1.8

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.
Files changed (50) hide show
  1. data/Gemfile.lock +1 -1
  2. data/box-api.gemspec +1 -1
  3. data/doc/Box.html +108 -0
  4. data/doc/Box/Account.html +1099 -0
  5. data/doc/Box/Api.html +3428 -0
  6. data/doc/Box/Api/AccountExceeded.html +130 -0
  7. data/doc/Box/Api/EmailInvalid.html +141 -0
  8. data/doc/Box/Api/EmailTaken.html +130 -0
  9. data/doc/Box/Api/ErrorStatus.html +130 -0
  10. data/doc/Box/Api/Exception.html +120 -0
  11. data/doc/Box/Api/Generic.html +130 -0
  12. data/doc/Box/Api/InvalidFolder.html +141 -0
  13. data/doc/Box/Api/InvalidInput.html +130 -0
  14. data/doc/Box/Api/InvalidName.html +130 -0
  15. data/doc/Box/Api/NameTaken.html +130 -0
  16. data/doc/Box/Api/NoAccess.html +130 -0
  17. data/doc/Box/Api/NoParent.html +130 -0
  18. data/doc/Box/Api/NotAuthorized.html +130 -0
  19. data/doc/Box/Api/Restricted.html +141 -0
  20. data/doc/Box/Api/SizeExceeded.html +130 -0
  21. data/doc/Box/Api/Unknown.html +130 -0
  22. data/doc/Box/Api/UnknownResponse.html +141 -0
  23. data/doc/Box/Api/UploadFailed.html +141 -0
  24. data/doc/Box/File.html +580 -0
  25. data/doc/Box/Folder.html +1078 -0
  26. data/doc/Box/Item.html +1884 -0
  27. data/doc/_index.html +342 -0
  28. data/doc/class_list.html +47 -0
  29. data/doc/css/common.css +1 -0
  30. data/doc/css/full_list.css +53 -0
  31. data/doc/css/style.css +320 -0
  32. data/doc/file.README.html +98 -0
  33. data/doc/file_list.html +49 -0
  34. data/doc/frames.html +13 -0
  35. data/doc/index.html +98 -0
  36. data/doc/js/app.js +205 -0
  37. data/doc/js/full_list.js +150 -0
  38. data/doc/js/jquery.js +16 -0
  39. data/doc/method_list.html +574 -0
  40. data/doc/top-level-namespace.html +103 -0
  41. data/examples/login.rb +4 -4
  42. data/lib/box/account.rb +168 -51
  43. data/lib/box/api.rb +174 -16
  44. data/lib/box/api/exceptions.rb +4 -0
  45. data/lib/box/file.rb +17 -4
  46. data/lib/box/folder.rb +85 -30
  47. data/lib/box/item.rb +89 -20
  48. data/spec/account_spec.rb +0 -4
  49. data/spec/folder_spec.rb +3 -9
  50. metadata +42 -4
@@ -29,6 +29,10 @@ module Box
29
29
  class AccountExceeded < Exception; end
30
30
  class SizeExceeded < Exception; end
31
31
 
32
+ # Given a status, returning a cooresponding Exception class.
33
+ #
34
+ # @param [String] status The failing status to look for.
35
+ # @return [Exception] A coorespondng Exception.
32
36
  def self.get_exception(status)
33
37
  case status
34
38
  # Common responses
@@ -1,15 +1,24 @@
1
1
  require 'box/item'
2
2
 
3
3
  module Box
4
+ # Represents a file stored on Box. Any attributes or actions typical to
5
+ # a Box file can be accessed through this class.
6
+
4
7
  class File < Item
8
+ # (see Item.type)
5
9
  def self.type; 'file'; end
6
10
 
7
- # download the file to the specified path
11
+ # Download this file to the specified path.
12
+ #
13
+ # @param [String] path The path to write the file.
8
14
  def download(path)
9
15
  @api.download(path, id)
10
16
  end
11
17
 
12
- # overwrite this file, using the file at the specified path
18
+ # Overwrite this file, using the file at the specified path
19
+ #
20
+ # @param [String] path The path to the file to upload.
21
+ # @return [File] self
13
22
  def upload_overwrite(path)
14
23
  info = @api.overwrite(path, id)['files']['file']
15
24
 
@@ -19,7 +28,11 @@ module Box
19
28
  self
20
29
  end
21
30
 
22
- # upload a new copy of this file, the name being 'file (#).ext' for the #th copy
31
+ # Upload a new copy of this file. The name will be "file (#).ext"
32
+ # for the each additional copy.
33
+ #
34
+ # @param path (see #upload_overwrite)
35
+ # @return [File] The newly created file.
23
36
  def upload_copy(path)
24
37
  info = @api.new_copy(path, id)['files']['file']
25
38
  parent.delete_info('files')
@@ -29,7 +42,7 @@ module Box
29
42
 
30
43
  protected
31
44
 
32
- # get the file info
45
+ # (see Item#get_info)
33
46
  def get_info
34
47
  @api.get_file_info(id)['info']
35
48
  end
@@ -2,12 +2,16 @@ require 'box/item'
2
2
  require 'box/file'
3
3
 
4
4
  module Box
5
- class Folder < Item
6
- attr_accessor :cached_tree
5
+ # Represents a folder stored on Box. Any attributes or actions typical to
6
+ # a Box folder can be accessed through this class.
7
7
 
8
+ class Folder < Item
9
+ # (see Item.type)
8
10
  def self.type; 'folder'; end
9
11
 
10
- # override the existing info method so that we create empty folders/files first
12
+ # (see Item#info)
13
+ # Files and folders will only be one-level deep, and {#tree} should be
14
+ # used if fetching deeper than that.
11
15
  def info(refresh = false)
12
16
  return self if @cached_info and not refresh
13
17
 
@@ -17,7 +21,16 @@ module Box
17
21
  super
18
22
  end
19
23
 
20
- # use the cached tree or update it if requested
24
+ # Get the tree for this folder. The tree includes all sub folders and
25
+ # files, including their info. Uses a cached copy if avaliable,
26
+ # or else it is fetched from the api.
27
+ #
28
+ # @note Fetching the tree can take a long time for large folders. There
29
+ # is a trade-off between one {#tree} call and multiple {#info}
30
+ # calls, so use the one most relevant for your application.
31
+ #
32
+ # @param [Boolean] refresh Does not use the cached copy if true.
33
+ # @return [Folder] self
21
34
  def tree(refresh = false)
22
35
  return self if @cached_tree and not refresh
23
36
 
@@ -30,7 +43,12 @@ module Box
30
43
  self
31
44
  end
32
45
 
33
- # create a new folder using this folder as the parent
46
+ # Create a new folder using this folder as the parent.
47
+ #
48
+ # @param [String] name The name of the new folder.
49
+ # @param [Integer] share The shared status of the new folder. Defaults
50
+ # to not being shared.
51
+ # @return [Folder] The new folder.
34
52
  def create(name, share = 0)
35
53
  info = @api.create_folder(id, name, share)['folder']
36
54
 
@@ -39,7 +57,10 @@ module Box
39
57
  Box::Folder.new(api, self, info)
40
58
  end
41
59
 
42
- # upload a new file using this folder as the parent
60
+ # Upload a new file using this folder as the parent
61
+ #
62
+ # @param [String] path The path of the file on disk to upload.
63
+ # @return [File] The new file.
43
64
  def upload(path)
44
65
  info = @api.upload(path, id)['files']['file']
45
66
 
@@ -48,7 +69,29 @@ module Box
48
69
  Box::File.new(api, self, info)
49
70
  end
50
71
 
51
- # search for items using criteria
72
+ # Search for sub-items using criteria.
73
+ #
74
+ # @param [Hash] criteria The hash of criteria to use. Each key of
75
+ # the criteria will be called on each sub-item and tested
76
+ # for equality. This lets you use any method of {Item}, {Folder},
77
+ # and {File} as the criteria.
78
+ # @return [Array] An array of all sub-items that matched the criteria.
79
+ #
80
+ # @note The recursive option will call {#tree}, which can be slow for
81
+ # large folders.
82
+ # @note Any item method (as a symbol) can be used as criteria, which
83
+ # could cause major problems if used improperly.
84
+ #
85
+ # @example Find all sub-items with the name 'README'
86
+ # folder.search(:name => 'README')
87
+ #
88
+ # @example Recusively find a sub-item with the given path.
89
+ # folder.search(:path => '/test/file.mp4', :recursive => true)
90
+ #
91
+ # @example Recursively find all files with a given sha1.
92
+ # folder.search(:type => 'file', :sha1 => 'abcdefg', :recursive => true)
93
+ #
94
+ # TODO: Lookup YARD syntax for options hash.
52
95
  def find(criteria)
53
96
  recursive = criteria.delete(:recursive)
54
97
  recursive = false if recursive == nil # default to false for performance reasons
@@ -58,24 +101,49 @@ module Box
58
101
  find!(criteria, recursive)
59
102
  end
60
103
 
104
+ # (see Item#force_cached_info)
105
+ def force_cached_info
106
+ create_sub_items(nil, Box::Folder)
107
+ create_sub_items(nil, Box::File)
108
+
109
+ super
110
+ end
111
+
112
+ # Consider the tree cached. This prevents an additional api
113
+ # when we know the item is fully fetched.
114
+ def force_cached_tree
115
+ @cached_tree = true
116
+
117
+ create_sub_items(nil, Box::Folder)
118
+ create_sub_items(nil, Box::File)
119
+
120
+ folders.each do |folder|
121
+ folder.force_cached_tree
122
+ end
123
+ end
124
+
61
125
  protected
62
126
 
63
- # get the folder info
127
+ attr_accessor :cached_tree
128
+
129
+ # (see Item#get_info)
64
130
  def get_info
65
131
  @api.get_account_tree(id, 'onelevel')['tree']['folder']
66
132
  end
67
133
 
68
- # get the folder info and all nested items
134
+ # Fetch the folder tree from the api.
135
+ # @return [Hash] The folder tree.
69
136
  def get_tree
70
- @api.get_account_tree(id)['tree']['folder']
137
+ @api.get_account_tree(id, 'simple')['tree']['folder']
71
138
  end
72
139
 
140
+ # (see Item#clear_info)
73
141
  def clear_info
74
142
  @cached_tree = false
75
143
  super
76
144
  end
77
145
 
78
- # overload Item#update_info to create the subobjects like Files and Folders
146
+ # (see Item#update_info)
79
147
  def update_info(info)
80
148
  if folders = info.delete('folders')
81
149
  create_sub_items(folders, Box::Folder)
@@ -88,7 +156,11 @@ module Box
88
156
  super
89
157
  end
90
158
 
91
- # create the sub items, so they are objects rather than hashes
159
+ # Create objects for the sub items.
160
+ #
161
+ # @param [Array] items Array of item info.
162
+ # @param [Item] item_class The class of the items in the Array.
163
+ # @return [Array] Array of {Item}s.
92
164
  def create_sub_items(items, item_class)
93
165
  @data[item_class.types] ||= Array.new
94
166
 
@@ -104,24 +176,7 @@ module Box
104
176
  end
105
177
  end
106
178
 
107
- # update the cached status of all sub items, as we got the entire tree
108
- def force_cached_tree
109
- create_sub_items(nil, Box::Folder)
110
- create_sub_items(nil, Box::File)
111
-
112
- files.each do |file|
113
- file.cached_info = true
114
- end
115
-
116
- folders.each do |folder|
117
- folder.cached_info = true
118
- folder.cached_tree = true
119
-
120
- folder.force_cached_tree
121
- end
122
- end
123
-
124
- # search for any files/folders that match the criteria sent
179
+ # (see #find)
125
180
  def find!(criteria, recursive)
126
181
  matches = (files + folders).collect do |item| # search over our files and folders
127
182
  match = criteria.all? do |key, value| # make sure all criteria pass
@@ -1,8 +1,24 @@
1
1
  module Box
2
+ # Represents a folder or file stored on Box. Any attributes or actions
3
+ # typical to a Box item can be accessed through this class. The {Item}
4
+ # class contains only methods shared by {Folder} and {File}, and should
5
+ # not be instanciated directly.
6
+
2
7
  class Item
3
- attr_accessor :data, :api, :parent
4
- attr_accessor :cached_info
8
+ # @return [Hash] The hash of info for this item.
9
+ attr_accessor :data
10
+
11
+ # @return [Api] The {Api} used by this item.
12
+ attr_accessor :api
13
+
14
+ # @return [Folder] The parent of this item.
15
+ attr_accessor :parent
5
16
 
17
+ # Create a new item representing either a file or folder.
18
+ #
19
+ # @param [Api] api The {Api} instance used to generate requests.
20
+ # @param [Folder] parent The {Folder} parent of this item.
21
+ # @param [Hash] info The hash of initial info for this item.
6
22
  def initialize(api, parent, info)
7
23
  @api = api
8
24
  @parent = parent
@@ -11,17 +27,31 @@ module Box
11
27
  update_info(info) # merges with the info hash, and renames some fields
12
28
  end
13
29
 
14
- # return the string representation of this item (file or folder)
30
+ # @return [String] The string representation of this item.
15
31
  def self.type; raise "Overwrite this method"; end
32
+
33
+ # @return [String] The plural string representation of this item.
16
34
  def self.types; type + 's'; end
17
35
 
18
- # should be a better way of doing this
36
+ # TODO: There should be a better way of doing this.
37
+
38
+ # (see .type)
19
39
  def type; self.class.type; end
40
+
41
+ # (see .types)
20
42
  def types; self.class.types; end
21
43
 
22
- def id; @data['id']; end # overwrite Object#id, which is not what we want
44
+ # @return [String] The id of this item.
45
+ def id
46
+ # overloads Object#id
47
+ @data['id']
48
+ end
23
49
 
24
- # use cached info or update it if requested
50
+ # Get the info for this item. Uses a cached copy if avaliable,
51
+ # or else it is fetched from the api.
52
+ #
53
+ # @param [Boolean] refresh Does not use the cached copy if true.
54
+ # @return [Item] self
25
55
  def info(refresh = false)
26
56
  return self if @cached_info and not refresh
27
57
 
@@ -31,7 +61,10 @@ module Box
31
61
  self
32
62
  end
33
63
 
34
- # move the item to the destination folder
64
+ # Move this item to the destination folder.
65
+ #
66
+ # @param [Folder] destination The new parent folder to use.
67
+ # @return [Item] self
35
68
  def move(destination)
36
69
  @api.move(type, id, destination.id)
37
70
 
@@ -43,7 +76,12 @@ module Box
43
76
  self
44
77
  end
45
78
 
46
- # copy the file (folder not supported in the api) to the destination folder
79
+ # Copy this item to the destination folder.
80
+ #
81
+ # @note Copying folders is not currently supported.
82
+ #
83
+ # @param [Folder] destination The parent folder to copy the item to.
84
+ # @return [Item] The new copy of this item.
47
85
  def copy(destination)
48
86
  @api.copy(type, id, destination.id)
49
87
 
@@ -52,7 +90,10 @@ module Box
52
90
  self.class.new(api, destination, @data)
53
91
  end
54
92
 
55
- # rename the item
93
+ # Rename this item.
94
+ #
95
+ # @param [String] new_name The new name for the item.
96
+ # @return [Item] self
56
97
  def rename(new_name)
57
98
  @api.rename(type, id, new_name)
58
99
 
@@ -61,7 +102,10 @@ module Box
61
102
  self
62
103
  end
63
104
 
64
- # delete the item
105
+ # Delete this item and all sub-items.
106
+ #
107
+ # @return [Item] self
108
+ # TODO: Return nil instead
65
109
  def delete
66
110
  @api.delete(type, id)
67
111
 
@@ -71,41 +115,62 @@ module Box
71
115
  self
72
116
  end
73
117
 
74
- # set the description of the item
118
+ # Set the description of this item.
119
+ #
120
+ # @param [String] message The description message to use.
121
+ # @return [Item] self
75
122
  def description(message)
76
123
  @api.set_description(type, id, message)
77
124
 
78
125
  self
79
126
  end
80
127
 
81
- # get the path, starting with /
128
+ # @return [String] The path of this item. This starts with a '/'.
82
129
  def path
83
130
  "#{ parent.path + '/' if parent }#{ name }"
84
131
  end
85
132
 
86
- # use method_missing as to provide an easy way to access the item's properties
133
+ # Provides an easy way to access this item's info.
134
+ #
135
+ # @example
136
+ # item.name # returns @data['name'] or fetches it if not cached
87
137
  def method_missing(sym, *args, &block)
138
+ # TODO: Why not symbols?
139
+ # convert to a string
88
140
  str = sym.to_s
89
141
 
90
142
  # return the value if it already exists
91
143
  return @data[str] if @data.key?(str)
92
144
 
93
- # value didn't exist, so update the info
145
+ # value didn't exist, so try to update the info
94
146
  self.info
95
147
 
96
- # try again
148
+ # try returning the value again
97
149
  return @data[str] if @data.key?(str)
98
150
 
99
151
  # we didn't find a value, so it must be invalid
152
+ # call the normal method_missing function
100
153
  super
101
154
  end
102
155
 
156
+ # Consider the item cached. This prevents an additional api
157
+ # when we know the item is fully fetched.
158
+ def force_cached_info
159
+ @cached_info = true
160
+ end
161
+
103
162
  protected
104
163
 
105
- # sub-classes are meant to implement this
106
- def get_info(*args); Hash.new; end
164
+ # Fetches this item's info from the api.
165
+ #
166
+ # @return [Hash] The info for the item.
167
+ def get_info; Hash.new; end
107
168
 
108
- # takes in a hash of info, cleans it, and merges it into the existing info
169
+ # Merges in the given info, making sure the fields are uniform.
170
+ # This is done because the api will occasionally return fields like
171
+ # 'file_id', but we want just 'id'.
172
+ #
173
+ # @param [Hash] info A hash to be merged this item's info
109
174
  def update_info(info)
110
175
  ninfo = Hash.new
111
176
 
@@ -118,13 +183,17 @@ module Box
118
183
  @data.merge!(ninfo) # merge in the updated info
119
184
  end
120
185
 
121
- # delete the cache for a specific info
186
+ # Invalidates and deletes the cache for a specific field. This forces
187
+ # the item to lazy-load this field if it is requested.
188
+ #
189
+ # @param [String] field The field to delete.
122
190
  def delete_info(field)
123
191
  @cached_info = false
124
192
  @data.delete(field)
125
193
  end
126
194
 
127
- # delete the entire cache
195
+ # Invalidates and deletes the entire cache. This forces all info to be
196
+ # lazy-loaded if requested.
128
197
  def clear_info
129
198
  @cached_info = false
130
199
  @data.clear
@@ -9,10 +9,6 @@ describe Box::Account do
9
9
  @account = get_account(false)
10
10
  end
11
11
 
12
- it "gets a ticket" do
13
- @account.ticket.should_not == nil
14
- end
15
-
16
12
  it "fails to authorize without auth token" do
17
13
  @account.authorize.should == false
18
14
  end