fieldview 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +0 -4
- data/README.md +29 -2
- data/fieldview.gemspec +4 -4
- data/lib/fieldview/auth_token.rb +26 -8
- data/lib/fieldview/errors.rb +13 -1
- data/lib/fieldview/field.rb +2 -3
- data/lib/fieldview/fieldview_response.rb +7 -3
- data/lib/fieldview/list_object.rb +3 -3
- data/lib/fieldview/requestable.rb +9 -0
- data/lib/fieldview/upload.rb +62 -0
- data/lib/fieldview/util.rb +7 -0
- data/lib/fieldview/version.rb +3 -0
- data/lib/fieldview.rb +5 -0
- data/test/test_auth_token.rb +2 -2
- data/test/test_helper.rb +3 -0
- data/test/test_upload.rb +89 -0
- metadata +10 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05858ad578d5fc9f1a42d4f15c8d9ee0b7299f01
|
4
|
+
data.tar.gz: be48bc245a2c2a38c6b850b51f735ca4d8db193a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1893ef1af5bdcc6a9ca2790e9806d58828d24a859ad944109b611a1af556688a45761290f0694821a5690c44c3b3e86d59a69135178eec56bcad0598890997c
|
7
|
+
data.tar.gz: cad12cb23d33a5569cdd3583429bab951ede0d58c5fcc4ca6ea80e27266fff1554717d49edc4b28c76a4c5dfbaf2c7fc72507c5585e380d18e832f3f43866341
|
data/Gemfile.lock
CHANGED
@@ -2,7 +2,6 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
fieldview (0.0.0)
|
5
|
-
faraday (~> 0.9)
|
6
5
|
|
7
6
|
GEM
|
8
7
|
remote: https://rubygems.org/
|
@@ -12,11 +11,8 @@ GEM
|
|
12
11
|
byebug (9.0.6)
|
13
12
|
crack (0.4.3)
|
14
13
|
safe_yaml (~> 1.0.0)
|
15
|
-
faraday (0.12.0.1)
|
16
|
-
multipart-post (>= 1.2, < 3)
|
17
14
|
hashdiff (0.3.2)
|
18
15
|
minitest (5.8.4)
|
19
|
-
multipart-post (2.0.0)
|
20
16
|
public_suffix (2.0.5)
|
21
17
|
rake (11.3.0)
|
22
18
|
safe_yaml (1.0.4)
|
data/README.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
The FieldView Ruby library provides convenient access to the FieldView API from applications written in the Ruby language. It includes a pre-defined set of classes for API resources that are available currently from the API. You will need to get access from a Climate Corporation representative and the interface utilize OAUTH 2.0.
|
4
4
|
|
5
|
+
OAuth token refreshing is handled for your if for some reason the token expires in the middle of requests (this requires that you provide the `refresh_token` with the creation of the `AuthToken`).
|
6
|
+
|
7
|
+
## Listable Objects
|
8
|
+
|
9
|
+
FieldView returns pages of objects that are tracked via the headers, you cannot go back in pages easily (perhaps we could be tracking the next-token?). Use `more_pages?` on the listable object to see if there are more pages to be acquired by using `next_page!`. The `next_token` on listable objects can also be preserved when reaching the end of a list to see if there are any additional changes since the `next_token` was saved.
|
10
|
+
|
11
|
+
The raw data can be acquired by using `.data` on a listable object.
|
12
|
+
|
13
|
+
When finished you will want to store information of the `AuthToken` somewhere as it may have changed with requests.
|
14
|
+
|
5
15
|
## Usage
|
6
16
|
|
7
17
|
The library needs to be configured with your FieldView account's client secret,
|
@@ -25,9 +35,10 @@ auth_token = FieldView::AuthToken.new_auth_token_with_code_from_redirect_code(<C
|
|
25
35
|
# Or initialize with previous information
|
26
36
|
auth_token = FieldView::AuthToken.new(
|
27
37
|
access_token: <ATOKEN>,
|
28
|
-
expiration_at: <DATETIME>,
|
38
|
+
expiration_at: <DATETIME>, # not required, but should be known
|
29
39
|
refresh_token: <RTOKEN>,
|
30
|
-
refresh_token_expiration_at: <DATETIME>
|
40
|
+
refresh_token_expiration_at: <DATETIME> # Not required, but should be known
|
41
|
+
)
|
31
42
|
|
32
43
|
# Or with just auth_token (assuming it hasn't expired)
|
33
44
|
auth_token = FieldView::AuthToken.new(access_token: <ATOKEN>)
|
@@ -35,6 +46,15 @@ auth_token = FieldView::AuthToken.new(access_token: <ATOKEN>)
|
|
35
46
|
# refresh token and a new access/refresh token will be associated with the object
|
36
47
|
auth_token = FieldView::AuthToken.new(refresh_token: <RTOKEN>)
|
37
48
|
|
49
|
+
# Then you can do something like this:
|
50
|
+
|
51
|
+
fields = FieldView::Fields.list(auth_token)
|
52
|
+
|
53
|
+
fields.each do |field|
|
54
|
+
puts field.boundary
|
55
|
+
end
|
56
|
+
|
57
|
+
fields.has_more?
|
38
58
|
|
39
59
|
```
|
40
60
|
|
@@ -52,6 +72,13 @@ Run a single test:
|
|
52
72
|
|
53
73
|
bundle exec ruby -Ilib/ test/field_view_test.rb -n /client.id/
|
54
74
|
|
75
|
+
## TODOs
|
76
|
+
|
77
|
+
- [ ] Thread safety of the auth token object since it's passed to all created objects
|
78
|
+
- [ ] Probably add configurable behavior for auto-refresh
|
79
|
+
- [ ] Change the configuration to non-static variables (at least the items that are required)
|
80
|
+
- [ ] Use faraday so that we are middleware agnostic
|
81
|
+
|
55
82
|
## Disclaimer
|
56
83
|
|
57
84
|
This Gem is in no way associated with The Climate Corporation, and they are in no way associated with it's support, maintenance, or updates.
|
data/fieldview.gemspec
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
2
2
|
|
3
|
+
require 'fieldview/version'
|
4
|
+
|
3
5
|
spec = Gem::Specification.new do |s|
|
4
6
|
s.name = 'fieldview'
|
5
|
-
s.version =
|
7
|
+
s.version = FieldView::VERSION
|
6
8
|
s.required_ruby_version = '>= 1.9.3'
|
7
9
|
s.summary = 'Ruby bindings for the FieldView API'
|
8
|
-
s.description = ' FieldView is used make data-driven decisions to maximize your return on every acre.'
|
10
|
+
s.description = ' FieldView is used to make data-driven decisions to maximize your return on every acre. This Ruby Gem is provided as a convenient way to access their API.'
|
9
11
|
s.author = 'Paul Susmarski'
|
10
12
|
s.email = 'paul@susmarski.com'
|
11
13
|
s.homepage = 'http://rubygems.org/gems/fielview'
|
12
14
|
s.license = 'MIT'
|
13
15
|
|
14
|
-
s.add_dependency('faraday', '~> 0.9')
|
15
|
-
|
16
16
|
s.files = Dir['lib/**/*.rb']
|
17
17
|
s.files = `git ls-files`.split("\n")
|
18
18
|
s.test_files = `git ls-files -- test/*`.split("\n")
|
data/lib/fieldview/auth_token.rb
CHANGED
@@ -12,14 +12,13 @@ module FieldView
|
|
12
12
|
# When the access token expires we'll need to refresh,
|
13
13
|
# can be specified as part of the object, 14399 is what is being
|
14
14
|
# returned at the time of writing this (2017-04-11)
|
15
|
-
self.access_token_expiration_at = params[:access_token_expiration_at] || (now + (params[:expires_in]||14399)
|
15
|
+
self.access_token_expiration_at = params[:access_token_expiration_at] || (now + (params[:expires_in]||14399))
|
16
16
|
|
17
17
|
# Refresh token isn't required, but can be initialized with this
|
18
18
|
self.refresh_token = params[:refresh_token]
|
19
19
|
|
20
|
-
# Refresh token technically expires in 30 days
|
21
|
-
|
22
|
-
self.refresh_token_expiration_at = params[:access_token_expiration_at] || (now + (30-1)*24*60*60)
|
20
|
+
# Refresh token technically expires in 30 days
|
21
|
+
self.refresh_token_expiration_at = params[:access_token_expiration_at] || (now + (30)*24*60*60)
|
23
22
|
end
|
24
23
|
|
25
24
|
def access_token_expired?
|
@@ -61,15 +60,27 @@ module FieldView
|
|
61
60
|
http = Net::HTTP.new(uri.host, uri.port)
|
62
61
|
http.use_ssl = FieldView.api_base.start_with?("https")
|
63
62
|
request = Net::HTTP.class_eval(method.to_s.capitalize).new(uri.request_uri)
|
63
|
+
if method == :get then
|
64
|
+
new_query_ar = URI.decode_www_form(uri.query || '')
|
65
|
+
params.each do |key,value|
|
66
|
+
new_query_ar << [key.to_s, value.to_s]
|
67
|
+
end
|
68
|
+
uri.query = URI.encode_www_form(new_query_ar)
|
69
|
+
request = Net::HTTP.class_eval(method.to_s.capitalize).new(uri.request_uri)
|
70
|
+
else
|
71
|
+
if params.is_a?(Hash)
|
72
|
+
request.body = params.to_json()
|
73
|
+
else
|
74
|
+
request.body = params
|
75
|
+
end
|
76
|
+
end
|
64
77
|
request["Accept"] = "*/*"
|
65
78
|
request["Authorization"] = "Bearer #{self.access_token}"
|
66
79
|
request["X-Api-Key"] = FieldView.x_api_key
|
67
80
|
request["Content-Type"] = "application/json"
|
68
|
-
|
69
81
|
headers.each do |header,value|
|
70
82
|
request[header] = value.to_s
|
71
83
|
end
|
72
|
-
|
73
84
|
response = http.request(request)
|
74
85
|
FieldView.handle_response_error_codes(response)
|
75
86
|
return FieldViewResponse.new(response)
|
@@ -92,10 +103,10 @@ module FieldView
|
|
92
103
|
end
|
93
104
|
|
94
105
|
# Code will be collected from the redirect to your server
|
95
|
-
def self.new_auth_token_with_code_from_redirect_code(code)
|
106
|
+
def self.new_auth_token_with_code_from_redirect_code(code, redirect_uri: nil)
|
96
107
|
http, request = build_token_request([
|
97
108
|
["grant_type", "authorization_code"],
|
98
|
-
["redirect_uri", FieldView.redirect_uri],
|
109
|
+
["redirect_uri", FieldView.redirect_uri || redirect_uri],
|
99
110
|
["code", code]
|
100
111
|
])
|
101
112
|
response = http.request(request)
|
@@ -107,5 +118,12 @@ module FieldView
|
|
107
118
|
return AuthToken.new(json)
|
108
119
|
end
|
109
120
|
end
|
121
|
+
|
122
|
+
def to_s()
|
123
|
+
[
|
124
|
+
"AccessToken: #{self.access_token}, Expiration: #{self.access_token_expiration_at}",
|
125
|
+
"RefreshToken: #{self.refresh_token}, Expiration: #{self.refresh_token_expiration_at}"
|
126
|
+
].join('\n')
|
127
|
+
end
|
110
128
|
end
|
111
129
|
end
|
data/lib/fieldview/errors.rb
CHANGED
@@ -14,8 +14,14 @@ module FieldView
|
|
14
14
|
attr_accessor :response
|
15
15
|
# Initializes a FieldViewError.
|
16
16
|
def initialize(message=nil, http_status: nil, http_body: nil,
|
17
|
-
http_headers: nil)
|
17
|
+
http_headers: nil, fieldview_response: nil)
|
18
18
|
@message = message
|
19
|
+
if fieldview_response then
|
20
|
+
self.response = fieldview_response
|
21
|
+
http_status = fieldview_response.http_status
|
22
|
+
http_body = fieldview_response.http_body
|
23
|
+
http_headers = fieldview_response.http_headers
|
24
|
+
end
|
19
25
|
@http_status = http_status
|
20
26
|
@http_body = http_body
|
21
27
|
@http_headers = http_headers || {}
|
@@ -61,4 +67,10 @@ module FieldView
|
|
61
67
|
# Raised when the server is busy
|
62
68
|
class ServerBusyError < FieldViewError
|
63
69
|
end
|
70
|
+
|
71
|
+
# Raised when a response code that is non-breaking is outside
|
72
|
+
# API specifications, ex: We expect a 201 when creating an upload, but it
|
73
|
+
# returns a 200
|
74
|
+
class UnexpectedResponseError < FieldViewError
|
75
|
+
end
|
64
76
|
end
|
data/lib/fieldview/field.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
module FieldView
|
2
|
-
class Field
|
2
|
+
class Field < Requestable
|
3
3
|
attr_accessor :id
|
4
4
|
attr_accessor :name
|
5
5
|
attr_accessor :boundary_id
|
6
|
-
attr_accessor :auth_token
|
7
6
|
def initialize(json_object, auth_token = nil)
|
8
7
|
self.id = json_object[:id]
|
9
8
|
self.name = json_object[:name]
|
10
9
|
self.boundary_id = json_object[:boundaryId]
|
11
|
-
|
10
|
+
super(auth_token)
|
12
11
|
end
|
13
12
|
|
14
13
|
def boundary
|
@@ -12,9 +12,13 @@ module FieldView
|
|
12
12
|
end
|
13
13
|
|
14
14
|
self.http_body = response.body
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
if response.body then
|
16
|
+
begin
|
17
|
+
self.data = JSON.parse(response.body, symbolize_names: true)
|
18
|
+
rescue JSON::ParserError
|
19
|
+
self.data = nil
|
20
|
+
end
|
21
|
+
else
|
18
22
|
self.data = nil
|
19
23
|
end
|
20
24
|
self.http_status = response.code.to_i
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module FieldView
|
2
|
-
class ListObject
|
2
|
+
class ListObject < Requestable
|
3
3
|
attr_accessor :limit
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :data, :last_http_status, :next_token, :listable
|
5
5
|
include Enumerable
|
6
6
|
|
7
7
|
def initialize(listable, auth_token, data, http_status, next_token: nil, limit: 100)
|
8
8
|
@listable = listable
|
9
|
-
@auth_token = auth_token
|
10
9
|
@data = data
|
11
10
|
@last_http_status = http_status
|
12
11
|
@next_token = next_token
|
13
12
|
@limit = 100
|
13
|
+
super(auth_token)
|
14
14
|
end
|
15
15
|
|
16
16
|
def each(&blk)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module FieldView
|
2
|
+
class Upload < Requestable
|
3
|
+
# 5 Megabytes is the current chunk size
|
4
|
+
REQUIRED_CHUNK_SIZE = 5*1024*1024
|
5
|
+
CHUNK_CONTENT_TYPE = "application/octet-stream"
|
6
|
+
|
7
|
+
PATH = "uploads"
|
8
|
+
attr_accessor :id, :content_length, :content_type
|
9
|
+
|
10
|
+
# Creates an upload with the specified items, all required.
|
11
|
+
# will return an a new upload object that has it's ID which can be
|
12
|
+
# used to upload. The following are known content types:
|
13
|
+
# image/vnd.climate.thermal.geotiff, image/vnd.climate.ndvi.geotiff,
|
14
|
+
# image/vnd.climate.chlorophyll.geotiff, image/vnd.climate.cci.geotiff,
|
15
|
+
# image/vnd.climate.waterstress.geotiff, image/vnd.climate.infrared.geotiff
|
16
|
+
def self.create(auth_token, md5, content_length, content_type)
|
17
|
+
response = auth_token.execute_request!(:post, PATH,
|
18
|
+
params: {
|
19
|
+
"md5" => md5,
|
20
|
+
"length" => content_length,
|
21
|
+
"content-type" => content_type
|
22
|
+
})
|
23
|
+
|
24
|
+
Util.verify_response_with_code("Upload creation", response, 201)
|
25
|
+
|
26
|
+
return new(response.http_body.gsub('"', ''), content_length, auth_token)
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(id, content_length, auth_token = nil)
|
30
|
+
self.id = id
|
31
|
+
self.content_length = content_length.to_i
|
32
|
+
if self.content_length <= 0 then
|
33
|
+
raise ArgumentError.new("You must set content_length to a non-zero value")
|
34
|
+
end
|
35
|
+
super(auth_token)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Upload a chunk of a file, specify the range of the bytes, 0 based, for the bytes
|
39
|
+
# you're passing, for example, the first 256 bytes would be start_bytes = 0 and
|
40
|
+
# end_bytes = 255, with bytes = 256 byte size object
|
41
|
+
def upload_chunk(start_bytes, end_bytes, bytes)
|
42
|
+
if (end_bytes.to_i - start_bytes.to_i + 1) != bytes.bytesize ||
|
43
|
+
bytes.bytesize > REQUIRED_CHUNK_SIZE then
|
44
|
+
raise ArgumentError.new("End bytes (#{end_bytes}) - Start bytes (#{start_bytes})" \
|
45
|
+
" must be equal to bytes (#{bytes}) and no greater than #{REQUIRED_CHUNK_SIZE}")
|
46
|
+
end
|
47
|
+
response = auth_token.execute_request!(:put, "#{PATH}/#{self.id}",
|
48
|
+
headers: {
|
49
|
+
"Content-Range" => "bytes #{start_bytes}-#{end_bytes}/#{self.content_length}",
|
50
|
+
"Content-Length" => bytes.bytesize,
|
51
|
+
"Content-Type" => CHUNK_CONTENT_TYPE,
|
52
|
+
"Transfer-Encoding" => "chunked"
|
53
|
+
},
|
54
|
+
params: bytes)
|
55
|
+
|
56
|
+
# We expect a 204
|
57
|
+
Util.verify_response_with_code("Chunk upload", response, 204)
|
58
|
+
|
59
|
+
return response
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/fieldview/util.rb
CHANGED
@@ -3,5 +3,12 @@ module FieldView
|
|
3
3
|
def self.http_status_is_more_in_list?(http_status)
|
4
4
|
return http_status.to_i == 206
|
5
5
|
end
|
6
|
+
|
7
|
+
def self.verify_response_with_code(message, fieldview_response, *acceptable_response_codes)
|
8
|
+
if not acceptable_response_codes.include?(fieldview_response.http_status) then
|
9
|
+
raise UnexpectedResponseError.new("#{message} expects #{acceptable_response_codes}",
|
10
|
+
fieldview_response: fieldview_response)
|
11
|
+
end
|
12
|
+
end
|
6
13
|
end
|
7
14
|
end
|
data/lib/fieldview.rb
CHANGED
@@ -3,13 +3,18 @@ require 'json'
|
|
3
3
|
require 'rbconfig'
|
4
4
|
require 'base64'
|
5
5
|
|
6
|
+
# Version
|
7
|
+
require 'fieldview/version'
|
8
|
+
|
6
9
|
# API Support Classes
|
7
10
|
require 'fieldview/errors'
|
11
|
+
require 'fieldview/requestable'
|
8
12
|
require 'fieldview/auth_token'
|
9
13
|
require 'fieldview/fields'
|
10
14
|
require 'fieldview/util'
|
11
15
|
require 'fieldview/fieldview_response'
|
12
16
|
require 'fieldview/field'
|
17
|
+
require 'fieldview/upload'
|
13
18
|
require 'fieldview/list_object'
|
14
19
|
require 'fieldview/boundary'
|
15
20
|
|
data/test/test_auth_token.rb
CHANGED
@@ -9,8 +9,8 @@ class TestAuthToken < Minitest::Test
|
|
9
9
|
def check_token_matches_fixture(token)
|
10
10
|
assert_equal FIXTURE[:access_token], token.access_token
|
11
11
|
assert_equal FIXTURE[:refresh_token], token.refresh_token
|
12
|
-
assert_equal FieldView.now + FIXTURE[:expires_in] -
|
13
|
-
assert_equal FieldView.now
|
12
|
+
assert_equal FieldView.now + FIXTURE[:expires_in] - 5, token.access_token_expiration_at
|
13
|
+
assert_equal FieldView.now + 30*24*60*60 - 5, token.refresh_token_expiration_at, "Should be 30 days in the future"
|
14
14
|
end
|
15
15
|
|
16
16
|
def setup
|
data/test/test_helper.rb
CHANGED
data/test/test_upload.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class TestUpload < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
setup_for_api_requests
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
teardown_for_api_request
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_expects_certain_status_code
|
14
|
+
stub_request(:post, /uploads/).
|
15
|
+
to_return(status: 200)
|
16
|
+
|
17
|
+
assert_raises(FieldView::UnexpectedResponseError) do
|
18
|
+
FieldView::Upload.create(new_auth_token, "dontcare", 5, "dontcare")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_create()
|
23
|
+
md5 = "eb782356d6011dab2b112bdcb098ec7d"
|
24
|
+
uuid = "1a2623b3-d2a7-4e52-ba21-a3eb521a3208"
|
25
|
+
content_length = 275
|
26
|
+
content_type = "image/vnd.climate.thermal.geotiff"
|
27
|
+
stub_request(:post, /uploads/).
|
28
|
+
with(body: {
|
29
|
+
"md5" => md5,
|
30
|
+
"length" => content_length,
|
31
|
+
"content-type" => content_type
|
32
|
+
}).
|
33
|
+
to_return(status: 201, body: %Q!"#{uuid}"!)
|
34
|
+
|
35
|
+
auth_token = new_auth_token
|
36
|
+
|
37
|
+
upload = FieldView::Upload.create(auth_token, md5, content_length, content_type)
|
38
|
+
|
39
|
+
assert_equal uuid, upload.id
|
40
|
+
assert_equal content_length, upload.content_length
|
41
|
+
assert_equal auth_token, upload.auth_token
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_checks_content_length
|
45
|
+
assert_raises(ArgumentError) do
|
46
|
+
# nil is going to result in 0 when converting to integer
|
47
|
+
FieldView::Upload.new(1,nil,new_auth_token)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_uploading_wrong_chunk_size
|
52
|
+
upload = FieldView::Upload.new("dontcare",
|
53
|
+
50000000, new_auth_token)
|
54
|
+
|
55
|
+
bytes = "12345678"
|
56
|
+
start_bytes = 0
|
57
|
+
end_bytes = 5
|
58
|
+
assert_raises(ArgumentError, "Wrong byte start/end") do
|
59
|
+
upload.upload_chunk(start_bytes, end_bytes, bytes)
|
60
|
+
end
|
61
|
+
|
62
|
+
bytes = "A" * (FieldView::Upload::REQUIRED_CHUNK_SIZE + 1)
|
63
|
+
end_bytes = bytes.bytesize - 1
|
64
|
+
assert_raises(ArgumentError, "Larger than the accepted chunk size") do
|
65
|
+
upload.upload_chunk(start_bytes, end_bytes, bytes)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_can_upload_chunk
|
70
|
+
uuid = "1a2623b3-d2a7-4e52-ba21-a3eb521a3208"
|
71
|
+
total_content_length = FieldView::Upload::REQUIRED_CHUNK_SIZE * 2
|
72
|
+
upload = FieldView::Upload.new(uuid,
|
73
|
+
total_content_length, new_auth_token)
|
74
|
+
|
75
|
+
chunk = "A"
|
76
|
+
start_bytes = 0
|
77
|
+
end_bytes = chunk.bytesize - 1
|
78
|
+
|
79
|
+
stub_request(:put, /uploads\/#{uuid}/).
|
80
|
+
with(headers: {
|
81
|
+
content_range: "bytes #{start_bytes}-#{end_bytes}/#{total_content_length}",
|
82
|
+
content_length: chunk.bytesize.to_s,
|
83
|
+
content_type: "application/octet-stream",
|
84
|
+
transfer_encoding: "chunked"
|
85
|
+
}).
|
86
|
+
to_return(status: 204, body: nil)
|
87
|
+
assert upload.upload_chunk(start_bytes, end_bytes, chunk)
|
88
|
+
end
|
89
|
+
end
|
metadata
CHANGED
@@ -1,31 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fieldview
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Susmarski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
12
|
-
dependencies:
|
13
|
-
-
|
14
|
-
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ~>
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0.9'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ~>
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0.9'
|
27
|
-
description: ' FieldView is used make data-driven decisions to maximize your return
|
28
|
-
on every acre.'
|
11
|
+
date: 2017-04-19 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: ' FieldView is used to make data-driven decisions to maximize your return
|
14
|
+
on every acre. This Ruby Gem is provided as a convenient way to access their API.'
|
29
15
|
email: paul@susmarski.com
|
30
16
|
executables: []
|
31
17
|
extensions: []
|
@@ -46,7 +32,10 @@ files:
|
|
46
32
|
- lib/fieldview/fields.rb
|
47
33
|
- lib/fieldview/fieldview_response.rb
|
48
34
|
- lib/fieldview/list_object.rb
|
35
|
+
- lib/fieldview/requestable.rb
|
36
|
+
- lib/fieldview/upload.rb
|
49
37
|
- lib/fieldview/util.rb
|
38
|
+
- lib/fieldview/version.rb
|
50
39
|
- spec/fixtures.json
|
51
40
|
- test/api_fixtures.rb
|
52
41
|
- test/test_auth_token.rb
|
@@ -56,6 +45,7 @@ files:
|
|
56
45
|
- test/test_fieldview.rb
|
57
46
|
- test/test_helper.rb
|
58
47
|
- test/test_list_object.rb
|
48
|
+
- test/test_upload.rb
|
59
49
|
homepage: http://rubygems.org/gems/fielview
|
60
50
|
licenses:
|
61
51
|
- MIT
|
@@ -89,3 +79,4 @@ test_files:
|
|
89
79
|
- test/test_fieldview.rb
|
90
80
|
- test/test_helper.rb
|
91
81
|
- test/test_list_object.rb
|
82
|
+
- test/test_upload.rb
|