my_john_deere_api 0.3.0 → 0.4.0

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/my_john_deere_api/client.rb +1 -1
  3. data/lib/my_john_deere_api/consumer.rb +88 -84
  4. data/lib/my_john_deere_api/errors/access_token_error.rb +12 -0
  5. data/lib/my_john_deere_api/errors.rb +2 -11
  6. data/lib/my_john_deere_api/helpers/case_conversion.rb +27 -0
  7. data/lib/my_john_deere_api/helpers.rb +1 -0
  8. data/lib/my_john_deere_api/model/field.rb +13 -0
  9. data/lib/my_john_deere_api/model/flag.rb +51 -0
  10. data/lib/my_john_deere_api/model/organization.rb +14 -1
  11. data/lib/my_john_deere_api/model.rb +1 -0
  12. data/lib/my_john_deere_api/request/collection/base.rb +83 -0
  13. data/lib/my_john_deere_api/request/{fields.rb → collection/fields.rb} +1 -1
  14. data/lib/my_john_deere_api/request/collection/flags.rb +19 -0
  15. data/lib/my_john_deere_api/request/{organizations.rb → collection/organizations.rb} +1 -1
  16. data/lib/my_john_deere_api/request/collection.rb +5 -82
  17. data/lib/my_john_deere_api/request.rb +0 -2
  18. data/lib/my_john_deere_api/version.rb +1 -1
  19. data/test/lib/my_john_deere_api/errors/test_access_token_error.rb +13 -0
  20. data/test/lib/my_john_deere_api/helpers/test_case_conversion.rb +56 -0
  21. data/test/lib/my_john_deere_api/model/test_flag.rb +52 -0
  22. data/test/lib/my_john_deere_api/request/collection/test_base.rb +28 -0
  23. data/test/lib/my_john_deere_api/request/{test_fields.rb → collection/test_fields.rb} +3 -3
  24. data/test/lib/my_john_deere_api/request/collection/test_flags.rb +90 -0
  25. data/test/lib/my_john_deere_api/request/{test_organizations.rb → collection/test_organizations.rb} +2 -2
  26. data/test/lib/my_john_deere_api/request/test_collection.rb +11 -18
  27. data/test/lib/my_john_deere_api/test_errors.rb +9 -0
  28. data/test/lib/my_john_deere_api/test_helpers.rb +4 -0
  29. data/test/lib/my_john_deere_api/test_model.rb +4 -0
  30. data/test/lib/my_john_deere_api/test_request.rb +0 -8
  31. data/test/support/vcr/get_flags.yml +47 -0
  32. metadata +17 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31aa8280a3df1a7eb45d47c7f5d8a3f6606316b5d7bec7ce42256a843beb0274
4
- data.tar.gz: d1cff664da5725a67903fdfc1d71b344b26c038099b456295302cb4b0949f1b0
3
+ metadata.gz: 5005d82b1ef3ac1363022c0a4344000cd823bef860301bc9a067f3d5ac200cbc
4
+ data.tar.gz: df32f8ea65db2bb668f23fa1a9c7e48db055abf6fc85dbeb84b51d97db777050
5
5
  SHA512:
6
- metadata.gz: 555d80933c95a91da91ed4892ecc8e3243d6d7df448ed220f8921973dbfa93737e98e9d5be74a96c7509d4361c05bba257828be37e49580b1b56c911da569ecc
7
- data.tar.gz: 33efb9f16ef9323279aa6449b9bbc21c532db6130ee2bbb7da4dba47a93510c8d36af6efb4c17262805fe26a0e2f2e4ee083ed7a65fa98aadd00b00c9410e42a
6
+ metadata.gz: 85b45d83f40727e26a7259c4237abe4d876a4eb6edb9c73eca3764ceb3253d5220729ac4fa52ab7b03e3e9fad4fbf2efbc3d97c91a80f7f57e17704b69cc89fe
7
+ data.tar.gz: 6511158e47fc47504f0143569ad435f00e45cd9cfa24a52be526bfd20f22d9f606bed14d22246fa1f0308865bebb92ad8b449dd41476fe269511011bb7ea5318
@@ -46,7 +46,7 @@ class MyJohnDeereApi::Client
46
46
 
47
47
  def organizations
48
48
  return @organizations if defined?(@organizations)
49
- @organizations = MyJohnDeereApi::Request::Organizations.new(accessor).all
49
+ @organizations = MyJohnDeereApi::Request::Collection::Organizations.new(accessor).all
50
50
  end
51
51
 
52
52
  private
@@ -1,85 +1,89 @@
1
- class MyJohnDeereApi::Consumer
2
- attr_reader :api_key, :api_secret, :environment, :base_url
3
-
4
- # valid API urls
5
- URLS = {
6
- sandbox: 'https://sandboxapi.deere.com',
7
- production: 'https://api.soa-proxy.deere.com',
8
- }
9
-
10
- DEFAULTS = {
11
- environment: :production
12
- }
13
-
14
- def initialize(api_key, api_secret, options={})
15
- options = DEFAULTS.merge(options)
16
-
17
- @api_key = api_key
18
- @api_secret = api_secret
19
-
20
- @environment = options[:environment]
21
- @base_url = options[:base_url] || URLS[@environment]
22
- end
23
-
24
- ##
25
- # oAuth Consumer which uses just the base url, for
26
- # app-wide, non user-specific GET requests.
27
-
28
- def app_get
29
- @app_get ||= consumer(base_url)
30
- end
31
-
32
- ##
33
- # oAuth Consumer which uses the proper url for user-specific GET requests.
34
-
35
- def user_get
36
- @user_get ||= consumer("#{base_url}/platform")
37
- end
38
-
39
- private
40
-
41
- def consumer(site)
42
- OAuth::Consumer.new(
43
- api_key,
44
- api_secret,
45
- site: site,
46
- header: header,
47
- http_method: :get,
48
- request_token_url: links[:request_token],
49
- access_token_url: links[:access_token],
50
- authorize_url: links[:authorize_request_token]
51
- )
52
- end
53
-
54
- def links
55
- return @links if defined?(@links)
56
-
57
- catalog = OAuth::Consumer.new(api_key, api_secret)
58
- .request(
59
- :get,
60
- "#{base_url}/platform/",
61
- nil,
62
- {},
63
- header
64
- ).body
65
-
66
- @links = {}
67
-
68
- JSON.parse(catalog)['links'].each do |link|
69
- uri = URI.parse(link['uri'])
70
- uri.query = nil
71
-
72
- @links[keyify(link['rel'])] = uri.to_s
73
- end
74
-
75
- @links
76
- end
77
-
78
- def header
79
- @header ||= {accept: 'application/vnd.deere.axiom.v3+json'}
80
- end
81
-
82
- def keyify key_name
83
- key_name.gsub(/^oauth/, '').gsub(/([a-z])([A-Z])/, '\1_\2').downcase.to_sym
1
+ module MyJohnDeereApi
2
+ class Consumer
3
+ include Helpers::CaseConversion
4
+
5
+ attr_reader :api_key, :api_secret, :environment, :base_url
6
+
7
+ # valid API urls
8
+ URLS = {
9
+ sandbox: 'https://sandboxapi.deere.com',
10
+ production: 'https://api.soa-proxy.deere.com',
11
+ }
12
+
13
+ DEFAULTS = {
14
+ environment: :production
15
+ }
16
+
17
+ def initialize(api_key, api_secret, options={})
18
+ options = DEFAULTS.merge(options)
19
+
20
+ @api_key = api_key
21
+ @api_secret = api_secret
22
+
23
+ @environment = options[:environment]
24
+ @base_url = options[:base_url] || URLS[@environment]
25
+ end
26
+
27
+ ##
28
+ # oAuth Consumer which uses just the base url, for
29
+ # app-wide, non user-specific GET requests.
30
+
31
+ def app_get
32
+ @app_get ||= consumer(base_url)
33
+ end
34
+
35
+ ##
36
+ # oAuth Consumer which uses the proper url for user-specific GET requests.
37
+
38
+ def user_get
39
+ @user_get ||= consumer("#{base_url}/platform")
40
+ end
41
+
42
+ private
43
+
44
+ def consumer(site)
45
+ OAuth::Consumer.new(
46
+ api_key,
47
+ api_secret,
48
+ site: site,
49
+ header: header,
50
+ http_method: :get,
51
+ request_token_url: links[:request_token],
52
+ access_token_url: links[:access_token],
53
+ authorize_url: links[:authorize_request_token]
54
+ )
55
+ end
56
+
57
+ def links
58
+ return @links if defined?(@links)
59
+
60
+ catalog = OAuth::Consumer.new(api_key, api_secret)
61
+ .request(
62
+ :get,
63
+ "#{base_url}/platform/",
64
+ nil,
65
+ {},
66
+ header
67
+ ).body
68
+
69
+ @links = {}
70
+
71
+ JSON.parse(catalog)['links'].each do |link|
72
+ uri = URI.parse(link['uri'])
73
+ uri.query = nil
74
+
75
+ @links[keyify(link['rel'])] = uri.to_s
76
+ end
77
+
78
+ @links
79
+ end
80
+
81
+ def header
82
+ @header ||= {accept: 'application/vnd.deere.axiom.v3+json'}
83
+ end
84
+
85
+ def keyify key_name
86
+ underscore(key_name.gsub(/^oauth/, '')).to_sym
87
+ end
84
88
  end
85
- end
89
+ end
@@ -0,0 +1,12 @@
1
+ module MyJohnDeereApi
2
+ ##
3
+ # This error is used in a context that will fail in the absence of
4
+ # a valid oAuth access token. We have classes that may only need
5
+ # access tokens for some use cases.
6
+
7
+ class AccessTokenError < StandardError
8
+ def initialize(message = "A valid oAuth Access Token must be supplied to use this feature.")
9
+ super
10
+ end
11
+ end
12
+ end
@@ -1,12 +1,3 @@
1
- module MyJohnDeereApi
2
- ##
3
- # This error is used in a context that will fail in the absence of
4
- # a valid oAuth access token. We have classes that may only need
5
- # access tokens for some use cases.
6
-
7
- class AccessTokenError < StandardError
8
- def initialize(message = "A valid oAuth Access Token must be supplied to use this feature.")
9
- super
10
- end
11
- end
1
+ module MyJohnDeereApi::Errors
2
+ require 'my_john_deere_api/errors/access_token_error'
12
3
  end
@@ -0,0 +1,27 @@
1
+ require 'uri'
2
+
3
+ module MyJohnDeereApi::Helpers::CaseConversion
4
+ ##
5
+ # convert a text or camelcase string to underscore
6
+
7
+ def underscore(string)
8
+ string.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/\s+/, '_').gsub(/_+/, '_').downcase
9
+ end
10
+
11
+ private :underscore
12
+
13
+ ##
14
+ # convert text or underscored string to camelcase
15
+
16
+ def camelize(string)
17
+ list = string.strip.split(/[_\s]+/)
18
+
19
+ # preserve case of the first element
20
+ new_list = [list.shift]
21
+ new_list += list.map(&:capitalize)
22
+
23
+ new_list.join('')
24
+ end
25
+
26
+ private :camelize
27
+ end
@@ -1,3 +1,4 @@
1
1
  module MyJohnDeereApi::Helpers
2
2
  autoload :UriPath, 'my_john_deere_api/helpers/uri_path'
3
+ autoload :CaseConversion, 'my_john_deere_api/helpers/case_conversion'
3
4
  end
@@ -4,6 +4,15 @@ module MyJohnDeereApi
4
4
 
5
5
  attr_reader :name, :id, :links, :accessor
6
6
 
7
+ ##
8
+ # arguments:
9
+ #
10
+ # [record] a JSON object of type 'Field', returned from the API.
11
+ #
12
+ # [accessor (optional)] a valid oAuth Access Token. This is only
13
+ # needed if further API requests are going
14
+ # to be made, as is the case with *flags*.
15
+
7
16
  def initialize(record, accessor = nil)
8
17
  @accessor = accessor
9
18
 
@@ -18,6 +27,10 @@ module MyJohnDeereApi
18
27
  end
19
28
  end
20
29
 
30
+ ##
31
+ # Since the archived attribute is boolean, we reflect this in the
32
+ # method name instead of using a standard attr_reader.
33
+
21
34
  def archived?
22
35
  @archived
23
36
  end
@@ -0,0 +1,51 @@
1
+ require 'json'
2
+
3
+ module MyJohnDeereApi
4
+ class Model::Flag
5
+ include Helpers::CaseConversion
6
+ include Helpers::UriPath
7
+
8
+ attr_reader :id, :notes, :geometry, :links, :accessor
9
+
10
+ ##
11
+ # arguments:
12
+ #
13
+ # [record] a JSON object of type 'Flag', returned from the API.
14
+ #
15
+ # [accessor (optional)] a valid oAuth Access Token. This is only
16
+ # needed if further API requests are going
17
+ # to be made.
18
+
19
+ def initialize(record, accessor = nil)
20
+ @accessor = accessor
21
+
22
+ @id = record['id']
23
+ @notes = record['notes']
24
+ @geometry =JSON.parse(record['geometry'])
25
+ @proximity_alert_enabled = record['proximityAlertEnabled']
26
+ @archived = record['archived']
27
+
28
+ @links = {}
29
+
30
+ record['links'].each do |association|
31
+ @links[underscore(association['rel'])] = uri_path(association['uri'])
32
+ end
33
+ end
34
+
35
+ ##
36
+ # Since the archived attribute is boolean, we reflect this in the
37
+ # method name instead of using a standard attr_reader.
38
+
39
+ def archived?
40
+ @archived
41
+ end
42
+
43
+ ##
44
+ # Since the proximity_alert_enabled attribute is boolean, we reflect this
45
+ # in the method name instead of using a standard attr_reader.
46
+
47
+ def proximity_alert_enabled?
48
+ @proximity_alert_enabled
49
+ end
50
+ end
51
+ end
@@ -6,6 +6,15 @@ module MyJohnDeereApi
6
6
 
7
7
  attr_reader :name, :type, :id, :links, :accessor
8
8
 
9
+ ##
10
+ # arguments:
11
+ #
12
+ # [record] a JSON object of type 'Organization', returned from the API.
13
+ #
14
+ # [accessor (optional)] a valid oAuth Access Token. This is only
15
+ # needed if further API requests are going
16
+ # to be made, as is the case with *fields*.
17
+
9
18
  def initialize(record, accessor = nil)
10
19
  @accessor = accessor
11
20
 
@@ -21,6 +30,10 @@ module MyJohnDeereApi
21
30
  end
22
31
  end
23
32
 
33
+ ##
34
+ # Since the member attribute is boolean, we reflect this in the
35
+ # method name instead of using a standard attr_reader.
36
+
24
37
  def member?
25
38
  @member
26
39
  end
@@ -32,7 +45,7 @@ module MyJohnDeereApi
32
45
  raise AccessTokenError unless accessor
33
46
 
34
47
  return @fields if defined?(@fields)
35
- @fields = MyJohnDeereApi::Request::Fields.new(accessor, organization: id).all
48
+ @fields = MyJohnDeereApi::Request::Collection::Fields.new(accessor, organization: id).all
36
49
  end
37
50
  end
38
51
  end
@@ -1,4 +1,5 @@
1
1
  module MyJohnDeereApi::Model
2
2
  autoload :Organization, 'my_john_deere_api/model/organization'
3
3
  autoload :Field, 'my_john_deere_api/model/field'
4
+ autoload :Flag, 'my_john_deere_api/model/flag'
4
5
  end
@@ -0,0 +1,83 @@
1
+ module MyJohnDeereApi
2
+ class Request::Collection::Base
3
+ include Enumerable
4
+ include Helpers::UriPath
5
+
6
+ attr_reader :accessor, :associations
7
+
8
+ ##
9
+ # accessor is an OAuth::AccessToken object which has the necessary
10
+ # credentials to make the desired requests.
11
+
12
+ def initialize(accessor, associations = {})
13
+ @accessor = accessor
14
+ @associations = associations
15
+ @items = []
16
+ end
17
+
18
+ ##
19
+ # Iterate lazily through all records in the collection, fetching
20
+ # additional pages as needed.
21
+
22
+ def each(&block)
23
+ count.times do |index|
24
+ fetch if @items.size <= index
25
+ block.call(@items[index])
26
+ end
27
+ end
28
+
29
+ ##
30
+ # Return all objects in the collection at once
31
+
32
+ def all
33
+ return @all if defined?(@all)
34
+ @all = map { |i| i }
35
+ end
36
+
37
+ ##
38
+ # Total count of records, even before pagination
39
+
40
+ def count
41
+ @count ||= first_page['total']
42
+ end
43
+
44
+ private
45
+
46
+ def first_page
47
+ return @first_page if defined?(@first_page)
48
+
49
+ @first_page = JSON.parse(@accessor.get(resource, headers).body)
50
+ extract_page_contents(@first_page)
51
+
52
+ @first_page
53
+ end
54
+
55
+ def fetch
56
+ return unless @next_page
57
+
58
+ page = JSON.parse(@accessor.get(@next_page, headers).body)
59
+ extract_page_contents(page)
60
+ end
61
+
62
+ def headers
63
+ @headers ||= {accept: 'application/vnd.deere.axiom.v3+json'}
64
+ end
65
+
66
+ def extract_page_contents(page)
67
+ add_items_from_page(page)
68
+ set_next_page(page)
69
+ end
70
+
71
+ def add_items_from_page(page)
72
+ @items += page['values'].map{|record| model.new(record, accessor) }
73
+ end
74
+
75
+ def set_next_page(page)
76
+ if next_page = page['links'].detect{|link| link['rel'] == 'nextPage'}
77
+ @next_page = uri_path(next_page['uri'])
78
+ else
79
+ @next_page = nil
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,7 +1,7 @@
1
1
  require 'json'
2
2
 
3
3
  module MyJohnDeereApi::Request
4
- class Fields < Collection
4
+ class Collection::Fields < Collection::Base
5
5
  ##
6
6
  # The resource path for the first page in the collection
7
7
 
@@ -0,0 +1,19 @@
1
+ require 'json'
2
+
3
+ module MyJohnDeereApi::Request
4
+ class Collection::Flags < Collection::Base
5
+ ##
6
+ # The resource path for the first page in the collection
7
+
8
+ def resource
9
+ "/organizations/#{associations[:organization]}/fields/#{associations[:field]}/flags"
10
+ end
11
+
12
+ ##
13
+ # This is the class used to model the data
14
+
15
+ def model
16
+ MyJohnDeereApi::Model::Flag
17
+ end
18
+ end
19
+ end
@@ -1,7 +1,7 @@
1
1
  require 'json'
2
2
 
3
3
  module MyJohnDeereApi::Request
4
- class Organizations < Collection
4
+ class Collection::Organizations < Collection::Base
5
5
  ##
6
6
  # The resource path for the first page in the collection
7
7
 
@@ -1,83 +1,6 @@
1
- module MyJohnDeereApi
2
- class Request::Collection
3
- include Enumerable
4
- include Helpers::UriPath
5
-
6
- attr_reader :accessor, :associations
7
-
8
- ##
9
- # accessor is an OAuth::AccessToken object which has the necessary
10
- # credentials to make the desired requests.
11
-
12
- def initialize(accessor, associations = {})
13
- @accessor = accessor
14
- @associations = associations
15
- @items = []
16
- end
17
-
18
- ##
19
- # Iterate lazily through all records in the collection, fetching
20
- # additional pages as needed.
21
-
22
- def each(&block)
23
- count.times do |index|
24
- fetch if @items.size <= index
25
- block.call(@items[index])
26
- end
27
- end
28
-
29
- ##
30
- # Return all objects in the collection at once
31
-
32
- def all
33
- return @all if defined?(@all)
34
- @all = map { |i| i }
35
- end
36
-
37
- ##
38
- # Total count of records, even before pagination
39
-
40
- def count
41
- @count ||= first_page['total']
42
- end
43
-
44
- private
45
-
46
- def first_page
47
- return @first_page if defined?(@first_page)
48
-
49
- @first_page = JSON.parse(@accessor.get(resource, headers).body)
50
- extract_page_contents(@first_page)
51
-
52
- @first_page
53
- end
54
-
55
- def fetch
56
- return unless @next_page
57
-
58
- page = JSON.parse(@accessor.get(@next_page, headers).body)
59
- extract_page_contents(page)
60
- end
61
-
62
- def headers
63
- @headers ||= {accept: 'application/vnd.deere.axiom.v3+json'}
64
- end
65
-
66
- def extract_page_contents(page)
67
- add_items_from_page(page)
68
- set_next_page(page)
69
- end
70
-
71
- def add_items_from_page(page)
72
- @items += page['values'].map{|record| model.new(record, accessor) }
73
- end
74
-
75
- def set_next_page(page)
76
- if next_page = page['links'].detect{|link| link['rel'] == 'nextPage'}
77
- @next_page = uri_path(next_page['uri'])
78
- else
79
- @next_page = nil
80
- end
81
- end
82
- end
1
+ module MyJohnDeereApi::Request::Collection
2
+ autoload :Base, 'my_john_deere_api/request/collection/base'
3
+ autoload :Organizations, 'my_john_deere_api/request/collection/organizations'
4
+ autoload :Fields, 'my_john_deere_api/request/collection/fields'
5
+ autoload :Flags, 'my_john_deere_api/request/collection/flags'
83
6
  end
@@ -1,5 +1,3 @@
1
1
  module MyJohnDeereApi::Request
2
2
  autoload :Collection, 'my_john_deere_api/request/collection'
3
- autoload :Organizations, 'my_john_deere_api/request/organizations'
4
- autoload :Fields, 'my_john_deere_api/request/fields'
5
3
  end
@@ -1,3 +1,3 @@
1
1
  module MyJohnDeereApi
2
- VERSION='0.3.0'
2
+ VERSION='0.4.0'
3
3
  end
@@ -0,0 +1,13 @@
1
+ require 'support/helper'
2
+
3
+ describe 'MyJohnDeereApi::AccessTokenError' do
4
+ it 'inherits from StandardError' do
5
+ error = MyJohnDeereApi::AccessTokenError.new
6
+ assert_kind_of StandardError, error
7
+ end
8
+
9
+ it 'has a default message' do
10
+ error = MyJohnDeereApi::AccessTokenError.new
11
+ assert_includes error.message, 'Access Token must be supplied'
12
+ end
13
+ end
@@ -0,0 +1,56 @@
1
+ require 'support/helper'
2
+
3
+ class CaseConversionHelperSample
4
+ include JD::Helpers::CaseConversion
5
+ end
6
+
7
+ describe 'Helpers::CaseConversion' do
8
+ let(:object) { CaseConversionHelperSample.new }
9
+
10
+ describe '#underscore' do
11
+ it 'converts from camelcase' do
12
+ string = object.send(:underscore, 'camelCaseExample')
13
+ assert_equal 'camel_case_example', string
14
+ end
15
+
16
+ it 'handles leading uppercase' do
17
+ string = object.send(:underscore, 'CamelCaseExample')
18
+ assert_equal 'camel_case_example', string
19
+ end
20
+
21
+ it 'converts spaces to underscores' do
22
+ string = object.send(:underscore, 'camel case Example')
23
+ assert_equal 'camel_case_example', string
24
+ end
25
+
26
+ it 'removes duplicate underscores after processing' do
27
+ string = object.send(:underscore, 'camel Case Example')
28
+ assert_equal 'camel_case_example', string
29
+ end
30
+
31
+ it 'is a private method' do
32
+ assert_raises(NoMethodError) { object.underscore('test') }
33
+ end
34
+ end
35
+
36
+ describe '#camelize' do
37
+ it 'converts from underscored' do
38
+ string = object.send(:camelize, 'this_is_a_test')
39
+ assert_equal 'thisIsATest', string
40
+ end
41
+
42
+ it 'converts from spaced' do
43
+ string = object.send(:camelize, 'this is a test')
44
+ assert_equal 'thisIsATest', string
45
+ end
46
+
47
+ it 'honors original capitalization' do
48
+ string = object.send(:camelize, 'This is a test')
49
+ assert_equal 'ThisIsATest', string
50
+ end
51
+
52
+ it 'is a private method' do
53
+ assert_raises(NoMethodError) { object.camelize('test') }
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,52 @@
1
+ require 'support/helper'
2
+ require 'json'
3
+
4
+ describe 'MyJohnDeereApi::Model::Flag' do
5
+ let(:record) do
6
+ {
7
+ "@type"=>"Flag",
8
+ "geometry"=>"{\"type\": \"Point\", \"coordinates\": [-93.14959274063109, 41.66881548411553] }",
9
+ "archived"=>true,
10
+ "proximityAlertEnabled"=>true,
11
+ "notes"=>"Our flag is a very, very, very nice flag!",
12
+ "id"=>"123456",
13
+ "links"=>[
14
+ {"@type"=>"Link", "rel"=>"field", "uri"=>"https://sandboxapi.deere.com/platform/organizations/123456/fields/123456"},
15
+ {"@type"=>"Link", "rel"=>"createdBy", "uri"=>"https://sandboxapi.deere.com/platform/users/bobsmith"},
16
+ {"@type"=>"Link", "rel"=>"lastModifiedBy", "uri"=>"https://sandboxapi.deere.com/platform/users/jonsmith"},
17
+ ]
18
+ }
19
+ end
20
+
21
+ describe '#initialize' do
22
+ def link_for label
23
+ record['links'].detect{|link| link['rel'] == label}['uri'].gsub('https://sandboxapi.deere.com/platform', '')
24
+ end
25
+
26
+ it 'sets the attributes from the given record' do
27
+ field = JD::Model::Flag.new(record)
28
+
29
+ assert_nil field.accessor
30
+
31
+ # basic attributes
32
+ assert_equal JSON.parse(record['geometry']), field.geometry
33
+ assert_equal record['archived'], field.archived?
34
+ assert_equal record['proximityAlertEnabled'], field.proximity_alert_enabled?
35
+ assert_equal record['notes'], field.notes
36
+ assert_equal record['id'], field.id
37
+
38
+ # links to other things
39
+ assert_kind_of Hash, field.links
40
+ assert_equal link_for('field'), field.links['field']
41
+ assert_equal link_for('createdBy'), field.links['created_by']
42
+ assert_equal link_for('lastModifiedBy'), field.links['last_modified_by']
43
+ end
44
+
45
+ it 'accepts an optional accessor' do
46
+ accessor = 'mock-accessor'
47
+
48
+ field = JD::Model::Flag.new(record, accessor)
49
+ assert_equal accessor, field.accessor
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,28 @@
1
+ require 'support/helper'
2
+
3
+ describe 'MyJohnDeereApi::Request::Collection::Base' do
4
+ let(:client) { JD::Client.new(API_KEY, API_SECRET, environment: :sandbox, access: [ACCESS_TOKEN, ACCESS_SECRET]) }
5
+ let(:accessor) { VCR.use_cassette('catalog') { client.send(:accessor) } }
6
+
7
+ describe '#initialize(access_token)' do
8
+ it 'accepts an access token' do
9
+ collection = JD::Request::Collection::Base.new(accessor)
10
+ assert_kind_of OAuth::AccessToken, collection.accessor
11
+ end
12
+
13
+ it 'accepts associations' do
14
+ collection = JD::Request::Collection::Base.new(accessor, organization: '123')
15
+
16
+ assert_kind_of Hash, collection.associations
17
+ assert_equal '123', collection.associations[:organization]
18
+ end
19
+ end
20
+
21
+ it 'uses the Enumerable module' do
22
+ collection = JD::Request::Collection::Base.new(accessor)
23
+
24
+ [:each, :first, :map, :detect, :select].each do |method_name|
25
+ assert collection.respond_to?(method_name)
26
+ end
27
+ end
28
+ end
@@ -2,7 +2,7 @@ require 'support/helper'
2
2
  require 'yaml'
3
3
  require 'json'
4
4
 
5
- describe 'MyJohnDeereApi::Request::Fields' do
5
+ describe 'MyJohnDeereApi::Request::Collection::Fields' do
6
6
  let(:organization_id) do
7
7
  contents = File.read('test/support/vcr/get_organizations.yml')
8
8
  body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
@@ -11,7 +11,7 @@ describe 'MyJohnDeereApi::Request::Fields' do
11
11
 
12
12
  let(:client) { JD::Client.new(API_KEY, API_SECRET, environment: :sandbox, access: [ACCESS_TOKEN, ACCESS_SECRET]) }
13
13
  let(:accessor) { VCR.use_cassette('catalog') { client.send(:accessor) } }
14
- let(:collection) { JD::Request::Fields.new(accessor, organization: organization_id) }
14
+ let(:collection) { JD::Request::Collection::Fields.new(accessor, organization: organization_id) }
15
15
 
16
16
  describe '#initialize(access_token)' do
17
17
  it 'accepts an access token' do
@@ -19,7 +19,7 @@ describe 'MyJohnDeereApi::Request::Fields' do
19
19
  end
20
20
 
21
21
  it 'accepts associations' do
22
- collection = JD::Request::Organizations.new(accessor, organization: '123')
22
+ collection = JD::Request::Collection::Fields.new(accessor, organization: '123')
23
23
 
24
24
  assert_kind_of Hash, collection.associations
25
25
  assert_equal '123', collection.associations[:organization]
@@ -0,0 +1,90 @@
1
+ require 'support/helper'
2
+ require 'yaml'
3
+ require 'json'
4
+
5
+ describe 'MyJohnDeereApi::Request::Collection::Flags' do
6
+ let(:organization_id) do
7
+ contents = File.read('test/support/vcr/get_organizations.yml')
8
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
9
+ JSON.parse(body)['values'].first['id']
10
+ end
11
+
12
+ let(:field_id) do
13
+ contents = File.read('test/support/vcr/get_fields.yml')
14
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
15
+ JSON.parse(body)['values'].first['id']
16
+ end
17
+
18
+ let(:client) { JD::Client.new(API_KEY, API_SECRET, environment: :sandbox, access: [ACCESS_TOKEN, ACCESS_SECRET]) }
19
+ let(:accessor) { VCR.use_cassette('catalog') { client.send(:accessor) } }
20
+ let(:collection) { JD::Request::Collection::Flags.new(accessor, organization: organization_id, field: field_id) }
21
+
22
+ describe '#initialize(access_token)' do
23
+ it 'accepts an access token' do
24
+ assert_kind_of OAuth::AccessToken, collection.accessor
25
+ end
26
+
27
+ it 'accepts associations' do
28
+ collection = JD::Request::Collection::Flags.new(accessor, organization: '123', field: '456')
29
+
30
+ assert_kind_of Hash, collection.associations
31
+ assert_equal '123', collection.associations[:organization]
32
+ assert_equal '456', collection.associations[:field]
33
+ end
34
+ end
35
+
36
+ describe '#resource' do
37
+ it 'returns /organizations/{org_id}/fields/{field_id}/flags' do
38
+ assert_equal "/organizations/#{organization_id}/fields/#{field_id}/flags", collection.resource
39
+ end
40
+ end
41
+
42
+ describe '#all' do
43
+ it 'returns all records' do
44
+ all = VCR.use_cassette('get_flags', record: :new_episodes) { collection.all }
45
+
46
+ assert_kind_of Array, all
47
+ assert_equal collection.count, all.size
48
+
49
+ all.each do |item|
50
+ assert_kind_of JD::Model::Flag, item
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#count' do
56
+ let(:server_response) do
57
+ contents = File.read('test/support/vcr/get_flags.yml')
58
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
59
+ JSON.parse(body)
60
+ end
61
+
62
+ let(:server_count) { server_response['total'] }
63
+
64
+ it 'returns the total count of records in the collection' do
65
+ count = VCR.use_cassette('get_flags') { collection.count }
66
+
67
+ assert_equal server_count, count
68
+ end
69
+ end
70
+
71
+ describe 'results' do
72
+ let(:flag_geometries) do
73
+ contents = File.read('test/support/vcr/get_flags.yml')
74
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
75
+ JSON.parse(body)['values'].map{|v| JSON.parse(v['geometry'])}
76
+ end
77
+
78
+ it 'returns all records as a single enumerator' do
79
+ count = VCR.use_cassette('get_flags') { collection.count }
80
+ geometries = VCR.use_cassette('get_flags', record: :new_episodes) { collection.map{|item| item.geometry} }
81
+
82
+ assert_kind_of Array, geometries
83
+ assert_equal count, geometries.size
84
+
85
+ flag_geometries.each do |expected_geometry|
86
+ assert_includes geometries, expected_geometry
87
+ end
88
+ end
89
+ end
90
+ end
@@ -2,10 +2,10 @@ require 'support/helper'
2
2
  require 'yaml'
3
3
  require 'json'
4
4
 
5
- describe 'MyJohnDeereApi::Request::Organizations' do
5
+ describe 'MyJohnDeereApi::Request::Collection::Organizations' do
6
6
  let(:client) { JD::Client.new(API_KEY, API_SECRET, environment: :sandbox, access: [ACCESS_TOKEN, ACCESS_SECRET]) }
7
7
  let(:accessor) { VCR.use_cassette('catalog') { client.send(:accessor) } }
8
- let(:collection) { JD::Request::Organizations.new(accessor) }
8
+ let(:collection) { JD::Request::Collection::Organizations.new(accessor) }
9
9
 
10
10
  describe '#initialize(access_token)' do
11
11
  it 'accepts an access token' do
@@ -1,28 +1,21 @@
1
1
  require 'support/helper'
2
2
 
3
3
  describe 'MyJohnDeereApi::Request::Collection' do
4
- let(:client) { JD::Client.new(API_KEY, API_SECRET, environment: :sandbox, access: [ACCESS_TOKEN, ACCESS_SECRET]) }
5
- let(:accessor) { VCR.use_cassette('catalog') { client.send(:accessor) } }
6
-
7
- describe '#initialize(access_token)' do
8
- it 'accepts an access token' do
9
- collection = JD::Request::Collection.new(accessor)
10
- assert_kind_of OAuth::AccessToken, collection.accessor
4
+ describe 'loading dependencies' do
5
+ it 'loads Request::Collection::Base' do
6
+ assert JD::Request::Collection::Base
11
7
  end
12
8
 
13
- it 'accepts associations' do
14
- collection = JD::Request::Collection.new(accessor, organization: '123')
15
-
16
- assert_kind_of Hash, collection.associations
17
- assert_equal '123', collection.associations[:organization]
9
+ it 'loads Request::Collection::Organizations' do
10
+ assert JD::Request::Collection::Organizations
18
11
  end
19
- end
20
12
 
21
- it 'uses the Enumerable module' do
22
- collection = JD::Request::Collection.new(accessor)
13
+ it 'loads Request::Collection::Fields' do
14
+ assert JD::Request::Collection::Fields
15
+ end
23
16
 
24
- [:each, :first, :map, :detect, :select].each do |method_name|
25
- assert collection.respond_to?(method_name)
17
+ it 'loads Request::Collection::Flags' do
18
+ assert JD::Request::Collection::Flags
26
19
  end
27
20
  end
28
- end
21
+ end
@@ -0,0 +1,9 @@
1
+ require 'support/helper'
2
+
3
+ describe 'MyJohnDeereApi Errors' do
4
+ describe 'loading dependencies' do
5
+ it 'loads AccessTokenError' do
6
+ assert JD::AccessTokenError
7
+ end
8
+ end
9
+ end
@@ -5,5 +5,9 @@ describe 'MyJohnDeereApi::Helpers' do
5
5
  it 'loads Helpers::UriPath' do
6
6
  assert JD::Helpers::UriPath
7
7
  end
8
+
9
+ it 'loads Helpers::CaseConversion' do
10
+ assert JD::Helpers::CaseConversion
11
+ end
8
12
  end
9
13
  end
@@ -9,5 +9,9 @@ describe 'MyJohnDeereApi::Model' do
9
9
  it 'loads Model::Field' do
10
10
  assert JD::Model::Field
11
11
  end
12
+
13
+ it 'loads Model::Flag' do
14
+ assert JD::Model::Flag
15
+ end
12
16
  end
13
17
  end
@@ -5,13 +5,5 @@ describe 'MyJohnDeereApi::Request' do
5
5
  it 'loads Request::Collection' do
6
6
  assert JD::Request::Collection
7
7
  end
8
-
9
- it 'loads Request::Organizations' do
10
- assert JD::Request::Organizations
11
- end
12
-
13
- it 'loads Request::Fields' do
14
- assert JD::Request::Fields
15
- end
16
8
  end
17
9
  end
@@ -0,0 +1,47 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://sandboxapi.deere.com/platform/organizations/444563/fields/11911a5a-ff81-40ef-b10d-0af9457fe474/flags
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/vnd.deere.axiom.v3+json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ User-Agent:
15
+ - OAuth gem v0.5.4
16
+ Authorization:
17
+ - OAuth oauth_consumer_key="johndeere-wgmADngYCRmfpEbVgSyc709wnyRux5J7PAv8SE7B",
18
+ oauth_nonce="dRV3ofkbPhDbjsPS2SpKYg5gUuiFuMnyw73JVhlYo", oauth_signature="Ksz7EKYSxTn9aDfwo48wNcUYoCQ%3D",
19
+ oauth_signature_method="HMAC-SHA1", oauth_timestamp="1578607741", oauth_token="47bbb9c9-41a8-4bec-8127-e3c5760af2f6",
20
+ oauth_version="1.0"
21
+ response:
22
+ status:
23
+ code: 200
24
+ message: OK
25
+ headers:
26
+ Date:
27
+ - Thu, 09 Jan 2020 22:09:02 GMT
28
+ Content-Type:
29
+ - application/vnd.deere.axiom.v3+json;charset=UTF-8
30
+ X-Deere-Handling-Server:
31
+ - ip-10-214-44-105
32
+ X-Frame-Options:
33
+ - SAMEORIGIN
34
+ X-Deere-Elapsed-Ms:
35
+ - '52'
36
+ Cache-Control:
37
+ - no-store
38
+ Content-Language:
39
+ - en-US
40
+ Transfer-Encoding:
41
+ - chunked
42
+ body:
43
+ encoding: UTF-8
44
+ string: '{"links":[{"rel":"self","uri":"https://sandboxapi.deere.com/platform/organizations/444563/fields"}],"total":1,"values":[{"@type": "Flag","geometry": "{\"type\": \"Point\", \"coordinates\": [-93.14959274063109, 41.66881548411553] }","notes": "A big rock on the left after entering the field","metaData": [{"name": "HARVESTABILITY","value": 1},{"name": "STAND_COUNT","value": 1}],"archived": false,"proximityAlertEnabled": false,"links": [{"rel": "owningOrganization","uri": "https://sandboxapi.deere.com/platform/organizations/1234"},{"rel": "flagCategoryWithPrefrences","uri": "https://sandboxapi.deere.com/platform/flagCategories/47a229fc-aa09-4618-956c-1c29ae884326?embed=preferences"},{"rel": "createdBy","uri": "https://sandboxapi.deere.com/platform/users/johndeeresystem"},{"rel": "lastModifiedBy","uri": "https://sandboxapi.deere.com/platform/users/john"},{"rel": "field","uri": "https://sandboxapi.deere.com/platform/organizations/1234/fields/7b387eaa-187f-4bd8-acbc-c81748b6ad3b"}],"id": "688c20bb-9609-4590-95c9-649ba65c06df","createdTime": "2018-07-01T21:00:11Z","lastModifiedTime": "2018-07-01T21:10:10Z"}]}'
45
+ http_version:
46
+ recorded_at: Thu, 09 Jan 2020 22:09:02 GMT
47
+ recorded_with: VCR 5.0.0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: my_john_deere_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaime. Bellmyer
@@ -100,25 +100,36 @@ files:
100
100
  - lib/my_john_deere_api/client.rb
101
101
  - lib/my_john_deere_api/consumer.rb
102
102
  - lib/my_john_deere_api/errors.rb
103
+ - lib/my_john_deere_api/errors/access_token_error.rb
103
104
  - lib/my_john_deere_api/helpers.rb
105
+ - lib/my_john_deere_api/helpers/case_conversion.rb
104
106
  - lib/my_john_deere_api/helpers/uri_path.rb
105
107
  - lib/my_john_deere_api/model.rb
106
108
  - lib/my_john_deere_api/model/field.rb
109
+ - lib/my_john_deere_api/model/flag.rb
107
110
  - lib/my_john_deere_api/model/organization.rb
108
111
  - lib/my_john_deere_api/request.rb
109
112
  - lib/my_john_deere_api/request/collection.rb
110
- - lib/my_john_deere_api/request/fields.rb
111
- - lib/my_john_deere_api/request/organizations.rb
113
+ - lib/my_john_deere_api/request/collection/base.rb
114
+ - lib/my_john_deere_api/request/collection/fields.rb
115
+ - lib/my_john_deere_api/request/collection/flags.rb
116
+ - lib/my_john_deere_api/request/collection/organizations.rb
112
117
  - lib/my_john_deere_api/version.rb
118
+ - test/lib/my_john_deere_api/errors/test_access_token_error.rb
119
+ - test/lib/my_john_deere_api/helpers/test_case_conversion.rb
113
120
  - test/lib/my_john_deere_api/helpers/test_uri_path.rb
114
121
  - test/lib/my_john_deere_api/model/test_field.rb
122
+ - test/lib/my_john_deere_api/model/test_flag.rb
115
123
  - test/lib/my_john_deere_api/model/test_organization.rb
124
+ - test/lib/my_john_deere_api/request/collection/test_base.rb
125
+ - test/lib/my_john_deere_api/request/collection/test_fields.rb
126
+ - test/lib/my_john_deere_api/request/collection/test_flags.rb
127
+ - test/lib/my_john_deere_api/request/collection/test_organizations.rb
116
128
  - test/lib/my_john_deere_api/request/test_collection.rb
117
- - test/lib/my_john_deere_api/request/test_fields.rb
118
- - test/lib/my_john_deere_api/request/test_organizations.rb
119
129
  - test/lib/my_john_deere_api/test_authorize.rb
120
130
  - test/lib/my_john_deere_api/test_client.rb
121
131
  - test/lib/my_john_deere_api/test_consumer.rb
132
+ - test/lib/my_john_deere_api/test_errors.rb
122
133
  - test/lib/my_john_deere_api/test_helpers.rb
123
134
  - test/lib/my_john_deere_api/test_model.rb
124
135
  - test/lib/my_john_deere_api/test_request.rb
@@ -128,6 +139,7 @@ files:
128
139
  - test/support/vcr/catalog.yml
129
140
  - test/support/vcr/get_access_token.yml
130
141
  - test/support/vcr/get_fields.yml
142
+ - test/support/vcr/get_flags.yml
131
143
  - test/support/vcr/get_organizations.yml
132
144
  - test/support/vcr/get_request_token.yml
133
145
  - test/test_my_john_deere_api.rb