myjohndeere 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 97de75462b83ea9c04fb0910eddf732c5affe625
4
- data.tar.gz: 7484ca74f1e54531717ab252b15b411d9baaf69c
3
+ metadata.gz: 19143fdf01d2f2e3fc3eb61a056784ab48ad13b0
4
+ data.tar.gz: 993ce13479bad9f237f88583a70a8fa3b7110136
5
5
  SHA512:
6
- metadata.gz: f3514ced5a8b3562afd29aa60f46ba4a446b31710ed74c29578761d67d1104ec2823f6df2a4b34efd69214b25761661843b40f7813543d5599ab7399c6c99339
7
- data.tar.gz: 5fce3d3e6c94a6652fde1443e12921c160f84716bcd5870f42a2760af5bb672a272fb9cd3e4c4caa1126eea1a6bb11c56741fcb9960ef6ce60f388ad502f86a7
6
+ metadata.gz: 92af50934686b143601301a29b07ac15cc432751942516dec22a1345eb2202ff1f005d2ed4b4816d65c1e43232dddcbd353d23d8e47c6ae8024a4bc03f248938
7
+ data.tar.gz: 89a9a893e011627cf950349c88201e0e4c061876f278f495775cc29d33299e027139c2ca168855712122670c1b3e0b392fa64a653eb0079bd06f64f3c1c8016a
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- myjohndeere (0.0.1)
4
+ myjohndeere (0.0.2)
5
5
  oauth (>= 0.5.3)
6
6
 
7
7
  GEM
@@ -59,6 +59,7 @@ module MyJohnDeere
59
59
  body: options[:body],
60
60
  etag: options[:etag])
61
61
  response = nil
62
+ MyJohnDeere.logger.debug("Sending request with body: #{body}\n headers: #{headers}")
62
63
  if REQUEST_METHODS_TO_PUT_PARAMS_IN_URL.include?(method)
63
64
  response = self.oauth_access_token.send(method, path, headers)
64
65
  else
@@ -66,13 +67,7 @@ module MyJohnDeere
66
67
  response = self.oauth_access_token.send(method, path, body, headers)
67
68
  end
68
69
  MyJohnDeere.logger.info("JohnDeere token response: #{response.body}")
69
- # if response.code == "401"
70
- # self.notify_on_destroy = true
71
- # # we are no longer authorized
72
- # self.destroy
73
- # logger.info("JohnDeere token destroyed: #{self.persisted?}, errors: #{self.errors.full_messages}")
74
- # end
75
- # return response
70
+ Util.handle_response_error_codes(response)
76
71
  return Response.new(response)
77
72
  end
78
73
  end
@@ -2,9 +2,60 @@ module MyJohnDeere
2
2
  # MyJohnDeereError is the base error from which all other more specific MyJohnError
3
3
  # errors derive.
4
4
  class MyJohnDeereError < StandardError
5
+ attr_reader :message
6
+
7
+ # These fields are now available as part of #response and that usage should
8
+ # be preferred.
9
+ attr_reader :http_body
10
+ attr_reader :http_headers
11
+ attr_reader :http_status
12
+
13
+ attr_accessor :response
14
+ # Initializes a MyJohnDeereError.
15
+ def initialize(message=nil, http_status: nil, http_body: nil,
16
+ http_headers: nil, my_john_deere_response: nil)
17
+ @message = message
18
+ if my_john_deere_response.is_a?(MyJohnDeere::Response) then
19
+ self.response = my_john_deere_response
20
+ http_status = my_john_deere_response.http_status
21
+ http_body = my_john_deere_response.http_body
22
+ http_headers = my_john_deere_response.http_headers
23
+ end
24
+ @http_status = http_status
25
+ @http_body = http_body
26
+ @http_headers = http_headers || {}
27
+ end
28
+
29
+ def to_s
30
+ status_string = @http_status.nil? ? "" : "(Status #{@http_status}) "
31
+ id_string = @request_id.nil? ? "" : "(Request #{@request_id}) "
32
+ "#{status_string}#{id_string}#{@message}"
33
+ end
5
34
  end
6
35
 
7
36
  # Configuration error is raised when configuration hasn't been properly done
8
37
  class ConfigurationError < MyJohnDeereError
9
38
  end
39
+
40
+ # AuthenticationError is raised when invalid credentials are used to connect
41
+ # to MyJohnDeere's servers or if your credentials have expired.
42
+ class AuthenticationError < MyJohnDeereError
43
+ end
44
+
45
+ # Raised when accessing resources you don't have access to. Generally just need to
46
+ # avoid making this request
47
+ class PermissionError < MyJohnDeereError
48
+ end
49
+
50
+ # Raised when too many requests are being made
51
+ class RateLimitError < MyJohnDeereError
52
+ end
53
+
54
+ # Raised when something goes wrong with MyJohnDeere API
55
+ class InternalServerError < MyJohnDeereError
56
+ end
57
+
58
+ # Raised when the server is busy
59
+ class ServerBusyError < MyJohnDeereError
60
+ end
10
61
  end
@@ -30,17 +30,7 @@ module MyJohnDeere
30
30
  metadata: metadata.map { |m| m.to_hash }
31
31
  }
32
32
 
33
- response = access_token.execute_request(:post,
34
- build_resouce_base_path!(self.list_resource_path, {map_layer_id: map_layer_id}),
35
- body: body
36
- )
37
- #{"Content-Type"=>"text/plain", "X-Deere-Handling-Server"=>"ldxtc3", "X-Frame-Options"=>"SAMEORIGIN", "Location"=>"https://sandboxapi.deere.com/platform/mapLayers/e2711205-c5df-445e-aad5-81eaf9090e6c", "X-Deere-Elapsed-Ms"=>"162", "Vary"=>"Accept-Encoding", "Expires"=>"Thu, 14 Sep 2017 15:52:24 GMT", "Cache-Control"=>"max-age=0, no-cache", "Pragma"=>"no-cache", "Date"=>"Thu, 14 Sep 2017 15:52:24 GMT", "Transfer-Encoding"=>"chunked", "Connection"=>"close, Transfer-Encoding"}
38
- id = get_created_id_from_response_headers(self.base_jd_resource, response)
39
- if id.nil? then
40
- return nil
41
- else
42
- return self.new(HashUtils.deep_stringify_keys({"id" => id}.merge(body)))
43
- end
33
+ return send_create(access_token, body, {map_layer_id: map_layer_id})
44
34
  end
45
35
 
46
36
  def self.upload_file(access_token, file_resource_id, file_path)
@@ -30,12 +30,7 @@ module MyJohnDeere
30
30
  }
31
31
  }
32
32
 
33
- response = access_token.execute_request(:post,
34
- build_resouce_base_path!(self.list_resource_path, {map_layer_summary_id: map_layer_summary_id}),
35
- body: body
36
- )
37
- #{"Content-Type"=>"text/plain", "X-Deere-Handling-Server"=>"ldxtc3", "X-Frame-Options"=>"SAMEORIGIN", "Location"=>"https://sandboxapi.deere.com/platform/mapLayers/e2711205-c5df-445e-aad5-81eaf9090e6c", "X-Deere-Elapsed-Ms"=>"162", "Vary"=>"Accept-Encoding", "Expires"=>"Thu, 14 Sep 2017 15:52:24 GMT", "Cache-Control"=>"max-age=0, no-cache", "Pragma"=>"no-cache", "Date"=>"Thu, 14 Sep 2017 15:52:24 GMT", "Transfer-Encoding"=>"chunked", "Connection"=>"close, Transfer-Encoding"}
38
- return get_created_id_from_response_headers(self.base_jd_resource, response)
33
+ return send_create(access_token, body, {map_layer_summary_id: map_layer_summary_id})
39
34
  end
40
35
  end
41
36
  end
@@ -24,17 +24,8 @@ module MyJohnDeere
24
24
  metadata: metadata.map { |md| md.to_hash },
25
25
  dateCreated: (date_created || Time.now).strftime("%Y-%m-%dT%H:%M:%S.%LZ")
26
26
  }
27
- response = access_token.execute_request(:post,
28
- build_resouce_base_path!(self.list_resource_path, {field_id: field_id, organization_id: organization_id}),
29
- body: body
30
- )
31
- #{"Content-Type"=>"text/plain", "X-Deere-Handling-Server"=>"ldxtc4", "X-Frame-Options"=>"SAMEORIGIN", "Location"=>"https://sandboxapi.deere.com/platform/mapLayerSummaries/c5e9317e-eda6-48d3-acc8-c3bca3424858", "X-Deere-Elapsed-Ms"=>"362", "Vary"=>"Accept-Encoding", "Expires"=>"Wed, 13 Sep 2017 22:00:45 GMT", "Cache-Control"=>"max-age=0, no-cache", "Pragma"=>"no-cache", "Date"=>"Wed, 13 Sep 2017 22:00:45 GMT", "Transfer-Encoding"=>"chunked", "Connection"=>"close, Transfer-Encoding"}
32
- id = get_created_id_from_response_headers(self.base_jd_resource, response)
33
- if id.nil?
34
- return nil
35
- else
36
- return self.new(HashUtils.deep_stringify_keys({"id" => id}.merge(body)))
37
- end
27
+
28
+ return send_create(access_token, body, {field_id: field_id, organization_id: organization_id})
38
29
  end
39
30
  end
40
31
  end
@@ -15,7 +15,7 @@ module MyJohnDeere
15
15
  options[:body][sbp] = options[sbp]
16
16
  end
17
17
 
18
- response = access_token.execute_request(:get, build_resouce_base_path!(self.list_resource_path, options),
18
+ response = access_token.execute_request(:get, build_resource_base_path!(self.list_resource_path, options),
19
19
  options
20
20
  )
21
21
  return ListObject.new(
@@ -31,25 +31,44 @@ module MyJohnDeere
31
31
  def retrieve(access_token, id, options={})
32
32
  validate_access_token(access_token)
33
33
  response = access_token.execute_request(:get,
34
- "#{build_resouce_base_path!(self.retrieve_resource_path, options)}/#{id}",
34
+ "#{build_resource_base_path!(self.retrieve_resource_path, options)}/#{id}",
35
35
  options)
36
36
 
37
37
  return new(response.data, access_token)
38
38
  end
39
39
 
40
- def build_resouce_base_path!(resource_path, options)
40
+ def build_resource_base_path!(resource_path, options = {})
41
+ expected_definitions = resource_path.scan(/%{(.+?)}/)
42
+ return resource_path if expected_definitions.empty?
41
43
  base_resources = {}
42
44
  options.each do |key, val|
43
45
  base_resources[key] = options.delete(key) if key.match(/_id\Z/)
44
46
  end
45
- return resource_path if base_resources.nil? || base_resources.empty?
46
47
  MyJohnDeere.logger.info("Building resource path: #{resource_path}, with ids: #{base_resources}")
47
- return resource_path % base_resources
48
+ begin
49
+ return resource_path % base_resources
50
+ rescue KeyError
51
+ raise ArgumentError.new("You must specify #{expected_definitions.join(", ")} as part of this request path")
52
+ end
48
53
  end
49
54
 
50
55
  def validate_access_token(access_token)
51
56
  raise ArgumentError.new("The first argument must be an #{AccessToken}") if !access_token.is_a?(AccessToken)
52
57
  end
58
+
59
+ def send_create(access_token, body, path_builder_options = {})
60
+ response = access_token.execute_request(:post,
61
+ build_resource_base_path!(self.list_resource_path, path_builder_options),
62
+ body: body
63
+ )
64
+ #{"Content-Type"=>"text/plain", "X-Deere-Handling-Server"=>"ldxtc3", "X-Frame-Options"=>"SAMEORIGIN", "Location"=>"https://sandboxapi.deere.com/platform/mapLayers/e2711205-c5df-445e-aad5-81eaf9090e6c", "X-Deere-Elapsed-Ms"=>"162", "Vary"=>"Accept-Encoding", "Expires"=>"Thu, 14 Sep 2017 15:52:24 GMT", "Cache-Control"=>"max-age=0, no-cache", "Pragma"=>"no-cache", "Date"=>"Thu, 14 Sep 2017 15:52:24 GMT", "Transfer-Encoding"=>"chunked", "Connection"=>"close, Transfer-Encoding"}
65
+ id = get_created_id_from_response_headers(self.base_jd_resource, response)
66
+ if id.nil? then
67
+ return nil
68
+ else
69
+ return self.new(HashUtils.deep_stringify_keys({"id" => id}.merge(body)))
70
+ end
71
+ end
53
72
  end
54
73
 
55
74
  module InstanceMethods
@@ -50,5 +50,36 @@ module MyJohnDeere
50
50
 
51
51
  return path, headers, body
52
52
  end
53
+
54
+ def self.handle_response_error_codes(response)
55
+ headers = response.to_hash
56
+ code = response.code.to_i
57
+ body = response.body
58
+ error = nil
59
+ case code
60
+ when 503
61
+ error = ServerBusyError
62
+ when 400, 404
63
+ error = InvalidRequestError
64
+ when 401
65
+ error = AuthenticationError
66
+ when 403
67
+ error = PermissionError
68
+ when 429
69
+ error = RateLimitError
70
+ when 500
71
+ error = InternalServerError
72
+ end
73
+
74
+ if error.nil? then
75
+ return
76
+ else
77
+ error = error.new(
78
+ http_status: code, http_body: body,
79
+ http_headers: headers)
80
+ error.response = response
81
+ raise error
82
+ end
83
+ end
53
84
  end
54
85
  end
@@ -1,3 +1,3 @@
1
1
  module MyJohnDeere
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -7,7 +7,7 @@ spec = Gem::Specification.new do |s|
7
7
  s.version = MyJohnDeere::VERSION
8
8
  s.required_ruby_version = '>= 1.9.3'
9
9
  s.summary = 'Ruby bindings for the MyJohnDeere API'
10
- s.description = ' MyJohnDeere 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.'
10
+ s.description = ' MyJohnDeere allows you to access your John Deere Financial account, JDLink, Operations Center and many other applications from one convenient place. This Ruby Gem is provided as a convenient way to access their API.'
11
11
  s.author = 'Paul Susmarski'
12
12
  s.email = 'paul@susmarski.com'
13
13
  s.homepage = 'https://github.com/psusmars/myjohndeere'
@@ -47,6 +47,16 @@ class TestAccessToken < Minitest::Test
47
47
  assert_equal expected_secret, at.secret
48
48
  end
49
49
 
50
+ def test_send_request_with_bad_responses
51
+ at = default_access_token()
52
+ stub_request(:get, "https://sandboxapi.deere.com/platform/").
53
+ to_return(status: 403, body: "Stuff")
54
+
55
+ assert_raises MyJohnDeere::PermissionError do
56
+ at.execute_request(:get, "/")
57
+ end
58
+ end
59
+
50
60
  def test_send_get_request
51
61
  at = default_access_token()
52
62
  expected_json = API_FIXTURES.fetch("api_catalog")
@@ -48,6 +48,7 @@ class TestMapLayer < Minitest::Test
48
48
  title: "blah",
49
49
  map_layer_id: "foo", map_legend_items: [MyJohnDeere::MapLegendItem.new("bar", 1, 2, "#0BA74A", 15.0)]
50
50
  )
51
- assert_equal MAP_LAYER_ID, response
51
+ assert_equal MAP_LAYER_ID, response.id
52
+ assert_equal ORGANIZATION_ID, response.organization_id
52
53
  end
53
54
  end
@@ -24,6 +24,19 @@ class TestRestMethods < Minitest::Test
24
24
  assert_equal "something", organizations.etag
25
25
  end
26
26
 
27
+ def test_build_resource_base_path
28
+ resource_path = "blah"
29
+ assert_equal "blah", MyJohnDeere::Organization.build_resource_base_path!("blah", {})
30
+ resource_path = "blah%{x_id}"
31
+ options = {x: 5, x_id: 1}
32
+ assert_equal "blah1", MyJohnDeere::Organization.build_resource_base_path!(resource_path, options)
33
+ assert_equal({x: 5}, options)
34
+
35
+ assert_raises ArgumentError do
36
+ MyJohnDeere::Organization.build_resource_base_path!(resource_path, {})
37
+ end
38
+ end
39
+
27
40
  def test_list_with_body
28
41
  stub_request(:get, /organizations;start=0;count=1/).
29
42
  with(query: {embed: "boundaries"}).
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: myjohndeere
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
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-09-14 00:00:00.000000000 Z
11
+ date: 2017-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth
@@ -24,9 +24,9 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.5.3
27
- description: ' MyJohnDeere is used to make data-driven decisions to maximize your
28
- return on every acre. This Ruby Gem is provided as a convenient way to access their
29
- API.'
27
+ description: ' MyJohnDeere allows you to access your John Deere Financial account,
28
+ JDLink, Operations Center and many other applications from one convenient place.
29
+ This Ruby Gem is provided as a convenient way to access their API.'
30
30
  email: paul@susmarski.com
31
31
  executables: []
32
32
  extensions: []