box_view 0.0.1
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.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +72 -0
- data/Rakefile +6 -0
- data/box_view.gemspec +23 -0
- data/lib/box_view/api/actions/crudable.rb +20 -0
- data/lib/box_view/api/actions/findable.rb +12 -0
- data/lib/box_view/api/actions/listable.rb +12 -0
- data/lib/box_view/api/base.rb +22 -0
- data/lib/box_view/api/document.rb +47 -0
- data/lib/box_view/api/document_session.rb +25 -0
- data/lib/box_view/http.rb +80 -0
- data/lib/box_view/models/base.rb +86 -0
- data/lib/box_view/models/document.rb +36 -0
- data/lib/box_view/models/document_session.rb +26 -0
- data/lib/box_view/session.rb +21 -0
- data/lib/box_view/version.rb +3 -0
- data/lib/box_view.rb +43 -0
- data/spec/api/actions/crudable_spec.rb +38 -0
- data/spec/api/actions/findable_spec.rb +23 -0
- data/spec/api/actions/listable_spec.rb +26 -0
- data/spec/api/base_spec.rb +18 -0
- data/spec/api/document_spec.rb +28 -0
- data/spec/models/base_spec.rb +206 -0
- data/spec/models/document_spec.rb +45 -0
- data/spec/session_spec.rb +21 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/dummy_api.rb +9 -0
- data/spec/support/dummy_resource.rb +16 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NDM0ZmZhYjA5OTFmM2NiN2IxYTQ3ZDcyYjJjZTNmZTA2ZDJkZWEzYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NzkzZWU2NWE2ZTc1ZWNlYWU2ZTQyZTk4YmM2ZWIwMmFlMGNhZDQ0Mw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
N2I2OGY2NzAyNzk5MjQxMDNmZmZjZjYzMDBjNTU2YmM4YmM0MGVhZWRlOGZh
|
10
|
+
NmI0NjY5OWM4NWVlMjIxMTNjNzQxZDc4NDE1NGM0Yzg2ZjA3NzYzMTlkMzI1
|
11
|
+
OGQwZDAyZDNmYTgxZjJmZGM4MDI2NDYwYjI3OTNlYTcwYjc1N2M=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZDJjMjE3YjgwZGZkYzU5Y2VjOThhNTA2ZmY4MDNlM2IxMTAwYzlhNmVkYTkw
|
14
|
+
OTg1NzI2NmY5Y2YyMDVjZGUwYWMxNjdlMjBhY2YxMTMzZWFiMGQ1MDNkMDgw
|
15
|
+
OTJjNmYwOGU0ZjNkNTQ5NDdmY2Y2MmIyYmI3YmNiMWFmYTllZjI=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 reillyforshaw
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# BoxView
|
2
|
+
|
3
|
+
A ruby client for [Box's View API](http://developers.box.com/view/).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'box_view'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install box_view
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Configure with your Box View API key.
|
22
|
+
|
23
|
+
BoxView::Session.config do |config|
|
24
|
+
config.box_view_token = YOUR_API_KEY
|
25
|
+
end
|
26
|
+
|
27
|
+
Or configure a session and pass it to the API when you instatiate it.
|
28
|
+
|
29
|
+
session = BoxView::Session.new(token: YOUR_API_KEY)
|
30
|
+
BoxView::Api::Document.new(session)
|
31
|
+
|
32
|
+
Upload a document at a url.
|
33
|
+
|
34
|
+
doc = BoxView::Api::Document.new.upload("http://www.example.com/myfile.pdf", "My File")
|
35
|
+
|
36
|
+
Check the document's `status`. When it is "done", you're ready to generate a viewing session.
|
37
|
+
|
38
|
+
doc = doc.reload
|
39
|
+
if doc.status == "done"
|
40
|
+
document_session = doc.document_session
|
41
|
+
view_url = document_session.view_url
|
42
|
+
end
|
43
|
+
|
44
|
+
Remove the document from Box View.
|
45
|
+
|
46
|
+
doc.destroy
|
47
|
+
|
48
|
+
List all of your Box View documents.
|
49
|
+
|
50
|
+
docs = BoxView::Api::Document.new.list
|
51
|
+
|
52
|
+
Generate a thumbnail of a document
|
53
|
+
|
54
|
+
f = File.open("myfile.pdf", 'w')
|
55
|
+
f.write(doc.thumbnail(100, 100))
|
56
|
+
f.flush
|
57
|
+
f.close
|
58
|
+
|
59
|
+
Download the conents in pdf or zip format
|
60
|
+
|
61
|
+
f = File.open("myfile.pdf", 'w')
|
62
|
+
f.write(doc.content("pdf"))
|
63
|
+
f.flush
|
64
|
+
f.close
|
65
|
+
|
66
|
+
## Contributing
|
67
|
+
|
68
|
+
1. Fork it
|
69
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
70
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
71
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
72
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/box_view.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'box_view/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "box_view"
|
8
|
+
spec.version = BoxView::VERSION
|
9
|
+
spec.authors = ["Reilly Forshaw"]
|
10
|
+
spec.email = ["reilly.forshaw@goclio.com"]
|
11
|
+
spec.description = "API client for Box View"
|
12
|
+
spec.summary = "A ruby library to interact with Box View"
|
13
|
+
spec.homepage = "https://github.com/reillyforshaw/box_view"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module BoxView
|
2
|
+
module Api
|
3
|
+
module Actions
|
4
|
+
module Crudable
|
5
|
+
|
6
|
+
def create(params)
|
7
|
+
data_item(session.post(endpoint_url, session.convert_params(params).to_json), session)
|
8
|
+
end
|
9
|
+
|
10
|
+
def update(id, params)
|
11
|
+
data_item(session.put("#{endpoint_url}/#{id}", session.convert_params(params).to_json), session)
|
12
|
+
end
|
13
|
+
|
14
|
+
def destroy(id)
|
15
|
+
session.delete("#{endpoint_url}/#{id}", false)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module BoxView
|
2
|
+
module Api
|
3
|
+
class Base
|
4
|
+
|
5
|
+
attr_accessor :session
|
6
|
+
|
7
|
+
def initialize(session=nil)
|
8
|
+
self.session = session || BoxView::Session.new
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def data_item(params, session)
|
14
|
+
data_klass.new(params, session)
|
15
|
+
end
|
16
|
+
|
17
|
+
def data_klass
|
18
|
+
raise NotImplementedError.new
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module BoxView
|
2
|
+
module Api
|
3
|
+
class Document < Base
|
4
|
+
|
5
|
+
include BoxView::Api::Actions::Findable
|
6
|
+
include BoxView::Api::Actions::Listable
|
7
|
+
include BoxView::Api::Actions::Crudable
|
8
|
+
|
9
|
+
def self.supported_filetypes
|
10
|
+
[:pdf, :doc, :docx, :ppt, :pptx]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.supported_filetype?(filetype)
|
14
|
+
supported_filetypes.include?(filetype.to_sym)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(*args)
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
def upload(url, name)
|
22
|
+
data_item(session.post(endpoint_url, { url: url, name: name }.to_json), session)
|
23
|
+
end
|
24
|
+
|
25
|
+
def thumbnail(id, width, height)
|
26
|
+
session.get("#{endpoint_url}/#{id}/thumbnail", { width: width, height: height }, false)
|
27
|
+
end
|
28
|
+
|
29
|
+
def content(id, extension=nil)
|
30
|
+
supported_extensions = %w(zip pdf)
|
31
|
+
raise ArgumentError.new("Unsupported content extension #{extension}. Must use one of #{supported_extensions} or nil.") unless supported_extensions.include?(extension) || extension.nil?
|
32
|
+
|
33
|
+
extension = ".#{extension}" if extension
|
34
|
+
session.get("#{endpoint_url}/#{id}/content#{extension}", {}, false)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def data_klass
|
40
|
+
BoxView::Models::Document
|
41
|
+
end
|
42
|
+
|
43
|
+
def endpoint_url; "documents"; end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module BoxView
|
2
|
+
module Api
|
3
|
+
class DocumentSession < Base
|
4
|
+
|
5
|
+
include BoxView::Api::Actions::Crudable
|
6
|
+
|
7
|
+
def update(*args)
|
8
|
+
raise NotImplementedError
|
9
|
+
end
|
10
|
+
|
11
|
+
def destroy(*args)
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def data_klass
|
18
|
+
BoxView::Models::DocumentSession
|
19
|
+
end
|
20
|
+
|
21
|
+
def endpoint_url; "sessions"; end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module BoxView
|
2
|
+
module Http
|
3
|
+
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
def base_uri(path, params = {})
|
7
|
+
uri = URI.parse("https://view-api.box.com")
|
8
|
+
uri.path = path
|
9
|
+
uri.query = URI.encode_www_form(convert_params(params)) if params.any?
|
10
|
+
uri
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(path, params={}, parse=true)
|
14
|
+
uri = base_uri("#{api_prefix}/#{path}", params)
|
15
|
+
req = Net::HTTP::Get.new(uri.to_s)
|
16
|
+
make_api_request(req, uri, parse)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def post(path, body="", parse=true)
|
21
|
+
uri = base_uri("#{api_prefix}/#{path}")
|
22
|
+
req = Net::HTTP::Post.new(uri.request_uri)
|
23
|
+
req.body = body
|
24
|
+
req.add_field("Content-Type", "application/json")
|
25
|
+
make_api_request(req, uri, parse)
|
26
|
+
end
|
27
|
+
|
28
|
+
def put(path, body="", parse=true)
|
29
|
+
uri = base_uri("#{api_prefix}/#{path}")
|
30
|
+
req = Net::HTTP::Put.new(uri.request_uri)
|
31
|
+
req.body = body
|
32
|
+
req.add_field("Content-Type", "application/json")
|
33
|
+
make_api_request(req, uri, parse)
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete(path, parse=true)
|
37
|
+
uri = base_uri("#{api_prefix}/#{path}")
|
38
|
+
req = Net::HTTP::Delete.new(uri.request_uri)
|
39
|
+
make_api_request(req, uri, parse)
|
40
|
+
end
|
41
|
+
|
42
|
+
def make_api_request(req, uri, parse=true)
|
43
|
+
puts "BoxView::Http#make_api_request token not availble #{uri}" if self.token.nil? || self.token.empty?
|
44
|
+
return if self.token.nil? || self.token.empty?
|
45
|
+
req.add_field("Authorization", "Token #{self.token}")
|
46
|
+
make_request(req, uri, parse)
|
47
|
+
end
|
48
|
+
|
49
|
+
def make_request(req, uri, parse=true)
|
50
|
+
req.add_field("Accept", "text/json")
|
51
|
+
n = Net::HTTP.new(uri.host, uri.port)
|
52
|
+
n.use_ssl = true
|
53
|
+
res = n.start do |http|
|
54
|
+
http.request(req)
|
55
|
+
end
|
56
|
+
puts "BoxView::Http#make_request #{uri} response: #{res.body}#{" Parsing" if parse}"
|
57
|
+
parse_response(res, parse)
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_response(res, parse=true)
|
61
|
+
parse ? JSON.parse(res.body) : res.body
|
62
|
+
end
|
63
|
+
|
64
|
+
def convert_params(params)
|
65
|
+
params.each_pair do |key, val|
|
66
|
+
if [Date, Time, DateTime].include?(val.class)
|
67
|
+
params[key] = val.iso8601
|
68
|
+
end
|
69
|
+
end
|
70
|
+
params
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def api_prefix()
|
76
|
+
"/1"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module BoxView
|
2
|
+
module Models
|
3
|
+
|
4
|
+
class ReadOnlyAttribute < Exception; end
|
5
|
+
class ResourceNotSaved < Exception; end
|
6
|
+
|
7
|
+
class Base
|
8
|
+
|
9
|
+
require 'time'
|
10
|
+
|
11
|
+
attr_accessor :session
|
12
|
+
|
13
|
+
def initialize(fields = {}, session = nil)
|
14
|
+
self.session = session
|
15
|
+
fields.each_pair do |k, v|
|
16
|
+
self.send("#{k}=", v) if self.respond_to?("#{k}=") && !v.nil?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def write_attribute(name, value)
|
21
|
+
instance_variable_set("@#{name}", value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def reload
|
25
|
+
raise ResourceNotSaved.new if self.id.nil?
|
26
|
+
api.find(self.id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def save
|
30
|
+
if self.id.nil?
|
31
|
+
created_item = api.create(self.to_params)
|
32
|
+
self.id = created_item && created_item.id
|
33
|
+
self
|
34
|
+
else
|
35
|
+
api.update(self.id, self.to_params)
|
36
|
+
self
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy
|
41
|
+
raise ResourceNotSaved.new if self.id.nil?
|
42
|
+
api.destroy(self.id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def api
|
46
|
+
raise NotImplementedError.new
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_params
|
50
|
+
raise NotImplementedError.new
|
51
|
+
end
|
52
|
+
|
53
|
+
class << self
|
54
|
+
def has_attributes(attributes)
|
55
|
+
attributes.each_pair do |name, options|
|
56
|
+
attr_reader name
|
57
|
+
define_method "#{name}=" do |value|
|
58
|
+
if options[:readonly] && !instance_variable_get("@#{name}").nil?
|
59
|
+
raise ReadOnlyAttribute.new(name)
|
60
|
+
end
|
61
|
+
write_attribute(name, self.class.convert_attribute(value, options[:type]))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def convert_attribute(value, type)
|
67
|
+
case type
|
68
|
+
when :date
|
69
|
+
(value.is_a?(Time) || value.is_a?(DateTime)) ? value.to_date : Date.parse(value)
|
70
|
+
when :time
|
71
|
+
(value.is_a?(Date) || value.is_a?(DateTime)) ? value.to_time : Time.parse(value)
|
72
|
+
when :datetime
|
73
|
+
(value.is_a?(Date) || value.is_a?(Time)) ? value.to_datetime : DateTime.parse(value)
|
74
|
+
when :integer
|
75
|
+
value.to_i
|
76
|
+
when :string
|
77
|
+
value.to_s
|
78
|
+
else
|
79
|
+
value
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module BoxView
|
2
|
+
module Models
|
3
|
+
class Document < Base
|
4
|
+
|
5
|
+
has_attributes(
|
6
|
+
type: { type: :string },
|
7
|
+
id: { type: :string },
|
8
|
+
status: { type: :string },
|
9
|
+
name: { type: :name },
|
10
|
+
created_at: { type: :datetime, readonly: true },
|
11
|
+
modified_at: { type: :datetime, readonly: true }
|
12
|
+
)
|
13
|
+
|
14
|
+
def document_session
|
15
|
+
@document_session ||= BoxView::Api::DocumentSession.new(session).create(document_id: self.id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def thumbnail(width, height)
|
19
|
+
self.api.thumbnail(self.id, width, height)
|
20
|
+
end
|
21
|
+
|
22
|
+
def content(extension=nil)
|
23
|
+
self.api.content(self.id, extension)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_params
|
27
|
+
{ name: self.name }
|
28
|
+
end
|
29
|
+
|
30
|
+
def api
|
31
|
+
@api ||= BoxView::Api::Document.new(session)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module BoxView
|
2
|
+
module Models
|
3
|
+
class DocumentSession < Base
|
4
|
+
|
5
|
+
has_attributes(
|
6
|
+
type: { type: :string },
|
7
|
+
id: { type: :string },
|
8
|
+
expires_at: { type: :datetime, readonly: true }
|
9
|
+
)
|
10
|
+
|
11
|
+
def view_url(theme = "dark")
|
12
|
+
return nil if self.id.nil?
|
13
|
+
"https://view-api.box.com/view/#{self.id}?theme=#{theme}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_params
|
17
|
+
{}
|
18
|
+
end
|
19
|
+
|
20
|
+
def api
|
21
|
+
@api ||= BoxView::Api::DocumentSession.new(session)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module BoxView
|
2
|
+
class Session
|
3
|
+
|
4
|
+
include Http
|
5
|
+
|
6
|
+
attr_accessor :token
|
7
|
+
|
8
|
+
def initialize(credentials={})
|
9
|
+
self.token = credentials[:token] || self.class.box_view_token
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :box_view_token
|
14
|
+
|
15
|
+
def config
|
16
|
+
yield self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/box_view.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "box_view/version"
|
2
|
+
|
3
|
+
require "net/http"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module BoxView
|
7
|
+
{
|
8
|
+
Session: 'session',
|
9
|
+
Http: 'http'
|
10
|
+
}.each_pair do |klass, file|
|
11
|
+
autoload klass, "box_view/#{file}"
|
12
|
+
end
|
13
|
+
|
14
|
+
module Models
|
15
|
+
{
|
16
|
+
Base: 'base',
|
17
|
+
Document: 'document',
|
18
|
+
DocumentSession: 'document_session'
|
19
|
+
}.each_pair do |klass, file|
|
20
|
+
autoload klass, "box_view/models/#{file}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module Api
|
25
|
+
{
|
26
|
+
Base: 'base',
|
27
|
+
Document: 'document',
|
28
|
+
DocumentSession: 'document_session'
|
29
|
+
}.each_pair do |klass, file|
|
30
|
+
autoload klass, "box_view/api/#{file}"
|
31
|
+
end
|
32
|
+
|
33
|
+
module Actions
|
34
|
+
{
|
35
|
+
Crudable: 'crudable',
|
36
|
+
Findable: 'findable',
|
37
|
+
Listable: 'listable'
|
38
|
+
}.each_pair do |klass, file|
|
39
|
+
autoload klass, "box_view/api/actions/#{file}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxView::Api::Actions::Crudable do
|
4
|
+
let(:session) { double("BoxView::Api::Actions::Crudable") }
|
5
|
+
let(:params) { { text: "1" } }
|
6
|
+
let(:subject) {
|
7
|
+
d = DummyApi.new(session)
|
8
|
+
d.extend(BoxView::Api::Actions::Crudable)
|
9
|
+
d
|
10
|
+
}
|
11
|
+
let(:response) { { id: 1, text: "1"} }
|
12
|
+
before { session.stub(:convert_params).and_return(params) }
|
13
|
+
|
14
|
+
describe "#create" do
|
15
|
+
it "should send a create request" do
|
16
|
+
session.stub(:post).with("dummies", params.to_json).and_return(response)
|
17
|
+
record = subject.create(params)
|
18
|
+
expect(record).to be_kind_of(DummyResource)
|
19
|
+
expect(record.id).to eql(1)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#update" do
|
24
|
+
it "should send an update request" do
|
25
|
+
session.stub(:put).with("dummies/1", params.to_json).and_return(response)
|
26
|
+
record = subject.update(1, params)
|
27
|
+
expect(record).to be_kind_of(DummyResource)
|
28
|
+
expect(record.id).to eql(1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#destroy" do
|
33
|
+
it "should send a delete request" do
|
34
|
+
session.should_receive(:delete)
|
35
|
+
subject.destroy(1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxView::Api::Actions::Findable do
|
4
|
+
let(:session) { double("BoxView::Api::Actions::Findable") }
|
5
|
+
let(:subject) {
|
6
|
+
d = DummyApi.new(session)
|
7
|
+
d.extend(BoxView::Api::Actions::Findable)
|
8
|
+
d
|
9
|
+
}
|
10
|
+
|
11
|
+
describe "#find" do
|
12
|
+
let(:response) do
|
13
|
+
{ id: 1 }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return the correct data item" do
|
17
|
+
session.stub(:get).and_return(response)
|
18
|
+
record = subject.find(1)
|
19
|
+
expect(record).to be_kind_of(DummyResource)
|
20
|
+
expect(record.id).to eql(1)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxView::Api::Actions::Listable do
|
4
|
+
let(:session) { double("BoxView::Api::Actions::Listable") }
|
5
|
+
let(:subject) {
|
6
|
+
d = DummyApi.new(session)
|
7
|
+
d.extend(BoxView::Api::Actions::Listable)
|
8
|
+
d
|
9
|
+
}
|
10
|
+
|
11
|
+
describe "#list" do
|
12
|
+
let(:response) do
|
13
|
+
{ "document_collection" => { "entries" => [{ id: 1 }, { id: 2 }] } }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return the correct data items" do
|
17
|
+
session.stub(:get).and_return(response)
|
18
|
+
records = subject.list
|
19
|
+
expect(records.count).to eql(2)
|
20
|
+
expect(records.first).to be_kind_of(DummyResource)
|
21
|
+
expect(records.first.id).to eql(1)
|
22
|
+
expect(records.last.id).to eql(2)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxView::Api::Base do
|
4
|
+
let(:api) { BoxView::Api::Base.new(session) }
|
5
|
+
let(:session) { nil }
|
6
|
+
|
7
|
+
it "should ues the configured session" do
|
8
|
+
expect(api.session).to_not be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
context "when a session is suppied" do
|
12
|
+
let(:session) { "the session" }
|
13
|
+
|
14
|
+
it "should use the supplied session" do
|
15
|
+
expect(api.session).to eql(session)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxView::Api::Document do
|
4
|
+
let(:session) { double("BoxView::Api::Session") }
|
5
|
+
let(:url) { "http://www.example.com/1.pdf" }
|
6
|
+
let(:name) { "Doc 1" }
|
7
|
+
let(:params) { { url: url, name: name } }
|
8
|
+
let(:subject) { BoxView::Api::Document.new(session) }
|
9
|
+
|
10
|
+
describe "#upload" do
|
11
|
+
let(:response) { { id: "1" } }
|
12
|
+
|
13
|
+
it "should send a post request" do
|
14
|
+
session.stub(:post).with("documents", params.to_json).and_return(response)
|
15
|
+
record = subject.upload(url, name)
|
16
|
+
expect(record).to be_kind_of(BoxView::Models::Document)
|
17
|
+
expect(record.id).to eql("1")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#content" do
|
22
|
+
context "filename has invalid extension" do
|
23
|
+
it "should raise an ArgumentError" do
|
24
|
+
expect{subject.content("1", "foo.bar")}.to raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe BoxView::Models::Base do
|
4
|
+
let(:model) { BoxView::Models::Base.new(fields, session) }
|
5
|
+
let(:fields) { {} }
|
6
|
+
let(:session) { nil }
|
7
|
+
|
8
|
+
before {
|
9
|
+
model.stub(:api).and_return(BoxView::Api::Base.new)
|
10
|
+
model.stub(:to_params).and_return({})
|
11
|
+
model.stub(:id).and_return(1)
|
12
|
+
}
|
13
|
+
|
14
|
+
describe "#reload" do
|
15
|
+
context "when the resource is not saved" do
|
16
|
+
before { model.stub(:id) }
|
17
|
+
it "should raise ResourceNotSaved" do
|
18
|
+
expect{model.reload}.to raise_error(BoxView::Models::ResourceNotSaved)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should use the api's find method" do
|
23
|
+
model.api.should_receive(:find)
|
24
|
+
model.reload
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#save" do
|
29
|
+
context "when the resource is not saved" do
|
30
|
+
before {
|
31
|
+
model.stub(:id)
|
32
|
+
model.api.stub(:create).and_return(double("BoxView::Models::Base", id: 1))
|
33
|
+
}
|
34
|
+
it "should use the api's create method" do
|
35
|
+
model.api.should_receive(:create)
|
36
|
+
model.should_receive(:id=)
|
37
|
+
model.save
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should use the api's update method" do
|
42
|
+
model.api.should_receive(:update)
|
43
|
+
model.save
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#destroy" do
|
48
|
+
context "when the resource is not saved" do
|
49
|
+
before { model.stub(:id) }
|
50
|
+
it "should raise ResourceNotSaved" do
|
51
|
+
expect{model.destroy}.to raise_error(BoxView::Models::ResourceNotSaved)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should use the api's destroy method" do
|
56
|
+
model.api.should_receive(:destroy)
|
57
|
+
model.destroy
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe ".has_attributes" do
|
62
|
+
before do
|
63
|
+
BoxView::Models::Base.has_attributes(
|
64
|
+
foo: { type: :string, readonly: true },
|
65
|
+
bar: { type: :string }
|
66
|
+
)
|
67
|
+
end
|
68
|
+
let(:model) { BoxView::Models::Base.new({foo: "foo"}) }
|
69
|
+
|
70
|
+
it "should define getter for the given attributes" do
|
71
|
+
model.should respond_to :foo
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should define setter for the given attributes" do
|
75
|
+
model.should respond_to :foo=
|
76
|
+
end
|
77
|
+
|
78
|
+
context "when an attribute is readonly" do
|
79
|
+
it "should create setter that throws an exception" do
|
80
|
+
expect{model.foo = "bar"}.to raise_error(BoxView::Models::ReadOnlyAttribute)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should convert the attribute when setting it" do
|
85
|
+
BoxView::Models::Base.should_receive :convert_attribute
|
86
|
+
model.bar = "bar"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe ".convert_attribute" do
|
91
|
+
let(:result) { BoxView::Models::Base.convert_attribute(value, type) }
|
92
|
+
|
93
|
+
context "when type is date" do
|
94
|
+
let(:type) { :date }
|
95
|
+
let(:value) { "2014-02-11" }
|
96
|
+
|
97
|
+
context "when value is a Time" do
|
98
|
+
let(:value) { Time.new }
|
99
|
+
|
100
|
+
it "should call to_date on the value" do
|
101
|
+
value.should_receive(:to_date)
|
102
|
+
result
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when value is a DateTime" do
|
107
|
+
let(:value) { DateTime.new }
|
108
|
+
|
109
|
+
it "should call to_date on the value" do
|
110
|
+
value.should_receive(:to_date)
|
111
|
+
result
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should parse the value" do
|
116
|
+
Date.should_receive(:parse).with(value)
|
117
|
+
result
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when type is time" do
|
122
|
+
let(:type) { :time }
|
123
|
+
let(:value) { "15:00:00" }
|
124
|
+
|
125
|
+
context "when value is a Date" do
|
126
|
+
let(:value) { Date.new }
|
127
|
+
|
128
|
+
it "should call to_time on the value" do
|
129
|
+
value.should_receive(:to_time)
|
130
|
+
result
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when value is a DateTime" do
|
135
|
+
let(:value) { DateTime.new }
|
136
|
+
|
137
|
+
it "should call to_time on the value" do
|
138
|
+
value.should_receive(:to_time)
|
139
|
+
result
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should parse the value" do
|
144
|
+
Time.should_receive(:parse).with(value)
|
145
|
+
result
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context "when type is datetime" do
|
150
|
+
let(:type) { :datetime }
|
151
|
+
let(:value) { "15:00:00" }
|
152
|
+
|
153
|
+
context "when value is a Date" do
|
154
|
+
let(:value) { Date.new }
|
155
|
+
|
156
|
+
it "should call to_datetime on the value" do
|
157
|
+
value.should_receive(:to_datetime)
|
158
|
+
result
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "when value is a DateTime" do
|
163
|
+
let(:value) { DateTime.new }
|
164
|
+
|
165
|
+
it "should call to_datetime on the value" do
|
166
|
+
value.should_receive(:to_datetime)
|
167
|
+
result
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should parse the value" do
|
172
|
+
DateTime.should_receive(:parse).with(value)
|
173
|
+
result
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context "when type is integer" do
|
178
|
+
let(:type) { :integer }
|
179
|
+
let(:value) { "42" }
|
180
|
+
|
181
|
+
it "should convert the value to an integer" do
|
182
|
+
expect(result).to eql(42)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context "when type is string" do
|
187
|
+
let(:type) { :string }
|
188
|
+
let(:value) { 42 }
|
189
|
+
|
190
|
+
it "should convert the value to a string" do
|
191
|
+
expect(result).to eql("42")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context "when type is anything else" do
|
196
|
+
let(:type) { :foo }
|
197
|
+
let(:value) { [1, 2, 3] }
|
198
|
+
|
199
|
+
it "should pass the value through" do
|
200
|
+
expect(result).to eql(value)
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxView::Models::Document do
|
4
|
+
let(:document) { BoxView::Models::Document.new }
|
5
|
+
let(:api) { BoxView::Api::Document.new }
|
6
|
+
before { document.stub(:api).and_return(api) }
|
7
|
+
|
8
|
+
describe "#document_session" do
|
9
|
+
before do
|
10
|
+
BoxView::Api::DocumentSession.any_instance.stub(:create).and_return(BoxView::Models::DocumentSession.new)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when a document session has already been created" do
|
14
|
+
before do
|
15
|
+
document.instance_variable_set("@document_session", BoxView::Models::DocumentSession.new)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should not use DocumentSession api's create method" do
|
19
|
+
BoxView::Api::DocumentSession.any_instance.should_not_receive(:create)
|
20
|
+
document.document_session
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should use DocumentSession api's create method" do
|
25
|
+
BoxView::Api::DocumentSession.any_instance.should_receive(:create)
|
26
|
+
document.document_session
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#thumbnail" do
|
31
|
+
before { document.api.stub(:thumbnail) }
|
32
|
+
it "should use the api's thumbnail method" do
|
33
|
+
document.api.should receive(:thumbnail)
|
34
|
+
document.thumbnail(100, 100)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#content" do
|
39
|
+
before { document.api.stub(:content) }
|
40
|
+
it "should use the api's content method" do
|
41
|
+
document.api.should receive(:content)
|
42
|
+
document.content
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxView::Session do
|
4
|
+
let(:session) { BoxView::Session.new(credentials) }
|
5
|
+
let(:credentials) { {} }
|
6
|
+
let(:config_token) { "ABC123" }
|
7
|
+
before { BoxView::Session.config { |config| config.box_view_token = config_token } }
|
8
|
+
|
9
|
+
it "should pick up the configured token" do
|
10
|
+
expect(session.token).to eql(config_token)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when credentials are supplied" do
|
14
|
+
let(:credentials) { { token: override_token } }
|
15
|
+
let(:override_token) { "overridden token" }
|
16
|
+
|
17
|
+
it "should use supplied token" do
|
18
|
+
expect(session.token).to eql(override_token)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: box_view
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Reilly Forshaw
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: API client for Box View
|
42
|
+
email:
|
43
|
+
- reilly.forshaw@goclio.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- box_view.gemspec
|
54
|
+
- lib/box_view.rb
|
55
|
+
- lib/box_view/api/actions/crudable.rb
|
56
|
+
- lib/box_view/api/actions/findable.rb
|
57
|
+
- lib/box_view/api/actions/listable.rb
|
58
|
+
- lib/box_view/api/base.rb
|
59
|
+
- lib/box_view/api/document.rb
|
60
|
+
- lib/box_view/api/document_session.rb
|
61
|
+
- lib/box_view/http.rb
|
62
|
+
- lib/box_view/models/base.rb
|
63
|
+
- lib/box_view/models/document.rb
|
64
|
+
- lib/box_view/models/document_session.rb
|
65
|
+
- lib/box_view/session.rb
|
66
|
+
- lib/box_view/version.rb
|
67
|
+
- spec/api/actions/crudable_spec.rb
|
68
|
+
- spec/api/actions/findable_spec.rb
|
69
|
+
- spec/api/actions/listable_spec.rb
|
70
|
+
- spec/api/base_spec.rb
|
71
|
+
- spec/api/document_spec.rb
|
72
|
+
- spec/models/base_spec.rb
|
73
|
+
- spec/models/document_spec.rb
|
74
|
+
- spec/session_spec.rb
|
75
|
+
- spec/spec_helper.rb
|
76
|
+
- spec/support/dummy_api.rb
|
77
|
+
- spec/support/dummy_resource.rb
|
78
|
+
homepage: https://github.com/reillyforshaw/box_view
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
metadata: {}
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 2.0.3
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: A ruby library to interact with Box View
|
102
|
+
test_files:
|
103
|
+
- spec/api/actions/crudable_spec.rb
|
104
|
+
- spec/api/actions/findable_spec.rb
|
105
|
+
- spec/api/actions/listable_spec.rb
|
106
|
+
- spec/api/base_spec.rb
|
107
|
+
- spec/api/document_spec.rb
|
108
|
+
- spec/models/base_spec.rb
|
109
|
+
- spec/models/document_spec.rb
|
110
|
+
- spec/session_spec.rb
|
111
|
+
- spec/spec_helper.rb
|
112
|
+
- spec/support/dummy_api.rb
|
113
|
+
- spec/support/dummy_resource.rb
|