box-api 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/box-api.gemspec +1 -1
- data/doc/Box.html +108 -0
- data/doc/Box/Account.html +1099 -0
- data/doc/Box/Api.html +3428 -0
- data/doc/Box/Api/AccountExceeded.html +130 -0
- data/doc/Box/Api/EmailInvalid.html +141 -0
- data/doc/Box/Api/EmailTaken.html +130 -0
- data/doc/Box/Api/ErrorStatus.html +130 -0
- data/doc/Box/Api/Exception.html +120 -0
- data/doc/Box/Api/Generic.html +130 -0
- data/doc/Box/Api/InvalidFolder.html +141 -0
- data/doc/Box/Api/InvalidInput.html +130 -0
- data/doc/Box/Api/InvalidName.html +130 -0
- data/doc/Box/Api/NameTaken.html +130 -0
- data/doc/Box/Api/NoAccess.html +130 -0
- data/doc/Box/Api/NoParent.html +130 -0
- data/doc/Box/Api/NotAuthorized.html +130 -0
- data/doc/Box/Api/Restricted.html +141 -0
- data/doc/Box/Api/SizeExceeded.html +130 -0
- data/doc/Box/Api/Unknown.html +130 -0
- data/doc/Box/Api/UnknownResponse.html +141 -0
- data/doc/Box/Api/UploadFailed.html +141 -0
- data/doc/Box/File.html +580 -0
- data/doc/Box/Folder.html +1078 -0
- data/doc/Box/Item.html +1884 -0
- data/doc/_index.html +342 -0
- data/doc/class_list.html +47 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +53 -0
- data/doc/css/style.css +320 -0
- data/doc/file.README.html +98 -0
- data/doc/file_list.html +49 -0
- data/doc/frames.html +13 -0
- data/doc/index.html +98 -0
- data/doc/js/app.js +205 -0
- data/doc/js/full_list.js +150 -0
- data/doc/js/jquery.js +16 -0
- data/doc/method_list.html +574 -0
- data/doc/top-level-namespace.html +103 -0
- data/examples/login.rb +4 -4
- data/lib/box/account.rb +168 -51
- data/lib/box/api.rb +174 -16
- data/lib/box/api/exceptions.rb +4 -0
- data/lib/box/file.rb +17 -4
- data/lib/box/folder.rb +85 -30
- data/lib/box/item.rb +89 -20
- data/spec/account_spec.rb +0 -4
- data/spec/folder_spec.rb +3 -9
- metadata +42 -4
data/lib/box/api/exceptions.rb
CHANGED
@@ -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
|
data/lib/box/file.rb
CHANGED
@@ -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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
45
|
+
# (see Item#get_info)
|
33
46
|
def get_info
|
34
47
|
@api.get_file_info(id)['info']
|
35
48
|
end
|
data/lib/box/folder.rb
CHANGED
@@ -2,12 +2,16 @@ require 'box/item'
|
|
2
2
|
require 'box/file'
|
3
3
|
|
4
4
|
module Box
|
5
|
-
|
6
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
data/lib/box/item.rb
CHANGED
@@ -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
|
-
|
4
|
-
attr_accessor :
|
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
|
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
|
-
|
44
|
+
# @return [String] The id of this item.
|
45
|
+
def id
|
46
|
+
# overloads Object#id
|
47
|
+
@data['id']
|
48
|
+
end
|
23
49
|
|
24
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
106
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
data/spec/account_spec.rb
CHANGED