clever-ruby 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +5 -0
  3. data/lib/clever-ruby.rb +3 -0
  4. data/lib/clever-ruby/api_operations/nested_list.rb +46 -0
  5. data/lib/clever-ruby/api_resource.rb +67 -27
  6. data/lib/clever-ruby/clever_object.rb +8 -2
  7. data/lib/clever-ruby/district.rb +25 -11
  8. data/lib/clever-ruby/event.rb +1 -1
  9. data/lib/clever-ruby/nested_resource.rb +40 -0
  10. data/lib/clever-ruby/school.rb +1 -1
  11. data/lib/clever-ruby/section.rb +1 -1
  12. data/lib/clever-ruby/student.rb +13 -1
  13. data/lib/clever-ruby/teacher.rb +1 -1
  14. data/lib/clever-ruby/util.rb +16 -17
  15. data/lib/clever-ruby/version.rb +1 -1
  16. data/test/data/vcr_cassettes/district_count.yml +6 -6
  17. data/test/data/vcr_cassettes/{districts_events.yml → district_events.yml} +29 -164
  18. data/test/data/vcr_cassettes/district_find_by_page.yml +12 -12
  19. data/test/data/vcr_cassettes/district_find_multiple.yml +12 -12
  20. data/test/data/vcr_cassettes/district_find_one.yml +12 -12
  21. data/test/data/vcr_cassettes/{districts_schools.yml → district_schools.yml} +25 -148
  22. data/test/data/vcr_cassettes/district_sections.yml +2289 -0
  23. data/test/data/vcr_cassettes/district_students.yml +2339 -0
  24. data/test/data/vcr_cassettes/{districts_teachers.yml → district_teachers.yml} +25 -148
  25. data/test/data/vcr_cassettes/districts.yml +12 -12
  26. data/test/data/vcr_cassettes/districts_event_pages.yml +76 -469
  27. data/test/data/vcr_cassettes/districts_school_pages.yml +31 -154
  28. data/test/data/vcr_cassettes/districts_section_pages.yml +284 -407
  29. data/test/data/vcr_cassettes/districts_student_pages.yml +165 -288
  30. data/test/data/vcr_cassettes/districts_teacher_pages.yml +81 -204
  31. data/test/data/vcr_cassettes/error_handling.yml +17 -58
  32. data/test/data/vcr_cassettes/event_count.yml +7 -7
  33. data/test/data/vcr_cassettes/event_find_by_page.yml +16 -22
  34. data/test/data/vcr_cassettes/event_find_multiple.yml +19 -28
  35. data/test/data/vcr_cassettes/event_find_one.yml +16 -22
  36. data/test/data/vcr_cassettes/events.yml +16 -22
  37. data/test/data/vcr_cassettes/school_count.yml +6 -6
  38. data/test/data/vcr_cassettes/school_district.yml +140 -0
  39. data/test/data/vcr_cassettes/school_events.yml +181 -0
  40. data/test/data/vcr_cassettes/school_find_by_page.yml +13 -13
  41. data/test/data/vcr_cassettes/school_find_multiple.yml +14 -14
  42. data/test/data/vcr_cassettes/school_find_one.yml +13 -13
  43. data/test/data/vcr_cassettes/school_sections.yml +1119 -0
  44. data/test/data/vcr_cassettes/school_students.yml +1033 -0
  45. data/test/data/vcr_cassettes/school_teachers.yml +257 -0
  46. data/test/data/vcr_cassettes/schools.yml +13 -13
  47. data/test/data/vcr_cassettes/schools_optional_attributes.yml +7 -7
  48. data/test/data/vcr_cassettes/section_count.yml +6 -6
  49. data/test/data/vcr_cassettes/section_district.yml +393 -0
  50. data/test/data/vcr_cassettes/section_events.yml +434 -0
  51. data/test/data/vcr_cassettes/section_find_by_page.yml +34 -34
  52. data/test/data/vcr_cassettes/section_find_multiple.yml +14 -14
  53. data/test/data/vcr_cassettes/section_find_one.yml +14 -14
  54. data/test/data/vcr_cassettes/section_school.yml +396 -0
  55. data/test/data/vcr_cassettes/section_students.yml +456 -0
  56. data/test/data/vcr_cassettes/section_teacher.yml +394 -0
  57. data/test/data/vcr_cassettes/sections.yml +34 -34
  58. data/test/data/vcr_cassettes/student_count.yml +6 -6
  59. data/test/data/vcr_cassettes/student_district.yml +202 -0
  60. data/test/data/vcr_cassettes/student_events.yml +243 -0
  61. data/test/data/vcr_cassettes/student_find_by_page.yml +83 -83
  62. data/test/data/vcr_cassettes/student_find_multiple.yml +14 -14
  63. data/test/data/vcr_cassettes/student_find_one.yml +14 -14
  64. data/test/data/vcr_cassettes/student_school.yml +205 -0
  65. data/test/data/vcr_cassettes/student_sections.yml +269 -0
  66. data/test/data/vcr_cassettes/student_teacher.yml +161 -0
  67. data/test/data/vcr_cassettes/student_teachers.yml +245 -0
  68. data/test/data/vcr_cassettes/students.yml +83 -83
  69. data/test/data/vcr_cassettes/teacher_count.yml +6 -6
  70. data/test/data/vcr_cassettes/teacher_district.yml +218 -0
  71. data/test/data/vcr_cassettes/teacher_events.yml +259 -0
  72. data/test/data/vcr_cassettes/teacher_find_by_page.yml +13 -13
  73. data/test/data/vcr_cassettes/teacher_find_multiple.yml +14 -14
  74. data/test/data/vcr_cassettes/teacher_find_one.yml +13 -13
  75. data/test/data/vcr_cassettes/teacher_school.yml +221 -0
  76. data/test/data/vcr_cassettes/teacher_sections.yml +291 -0
  77. data/test/data/vcr_cassettes/teacher_students.yml +293 -0
  78. data/test/data/vcr_cassettes/teachers.yml +13 -13
  79. data/test/integration/api_operations/list_test.rb +1 -1
  80. data/test/integration/district_test.rb +17 -49
  81. data/test/integration/error_handling_test.rb +1 -1
  82. data/test/integration/nested_resource_test.rb +27 -0
  83. data/test/unit/api_resource_test.rb +32 -0
  84. data/test/unit/optional_attributes_test.rb +7 -13
  85. metadata +60 -14
  86. data/test/data/vcr_cassettes/districts_sections.yml +0 -818
  87. data/test/data/vcr_cassettes/districts_students.yml +0 -436
  88. data/test/data/vcr_cassettes/districts_students_filtered.yml +0 -170
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NmI3NzcwOGI0ZjVjNTRmMDRiZTg5YjZiZjAyNWZjNzkzNTUxNTg2Yg==
4
+ NTMxM2FkNGQzYzQ0YTJjZjE0YzhkMGM0ZDAyNjg2MTg3MjFlYzU0Ng==
5
5
  data.tar.gz: !binary |-
6
- MGViMmNhMjI2Mjg4MDc5Nzc1ZDFmNjM5OTc1ODhkMGIyMmZmMDFlZA==
6
+ NDgzOWE5NzdhZjM2NWY4YjQyNzU1ZjY1NWQ5YThiZDlkM2IzNzgyYg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YmJhMTU5OThjMWQ2ZDJhYmI0NDY4MmEyNmQ5NGY2YmI4NDQ3NTZmMjY5M2Ux
10
- YjUwNzcwMGE5ZDEwOTA4YjcyMzA3OGY0OGYyYzlmZDJjNmI2NTgxOTE5NjRh
11
- ZmNkN2U3YTUwYjMzNTA3OGM1N2NlNzEyNzE2MDYzZmZmODc3MzA=
9
+ ODIyYTg2NTQwOTA4YWUyNjgxNjhhNjU3ZTk1YWNhYmMyZTA3NjYzM2NhZGJj
10
+ NGI2YWJlOTkyZTFhMTI0ZjlmN2U2MzExNzgyYjliY2JmN2Y1YzZhM2NmZjk0
11
+ ZjY2MjgzODk0ZWNiOTM3YjI5N2EyNDUxZmY5MTIxYTlmNTM0YTA=
12
12
  data.tar.gz: !binary |-
13
- OWJhZjIzMDVjNzlkODM4NmVhMjJiYzcxYTk5MTM3NmIyOWFhY2NkYTI3MzBl
14
- ZWFhMWYxMTlhNzMxY2RhMzQ1YzQyMTc4NGVjOTQxMmFjZDM4NjczYWUwOWI4
15
- MjY5Y2YyMzhmODNjNjFiOGE0MzYzY2JkODU1YmFhMjZlNmJkYmQ=
13
+ YjE5MzgwMTJiMWRjYTYyMjQ3N2MzOTMwM2VkODcxZTViZjdhNTkyYjM0Y2Iw
14
+ Y2FjMjE2MjI2ZGQ4MWFlNTkwZWVmMDMxZTM1ZTBkZDkzYTkwZTc1OGY1OGVj
15
+ NzNiOGFmN2U1OTNkYzhhMjAxNDg3ZWIzZjIwNzFiNWU3MDljZmU=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.7.0 (2014-09-12)
2
+
3
+ * Make nested resources support full queries, including find and count
4
+ * Make tests more robust to data changes
5
+
1
6
  ## 0.6.2 (2014-09-12)
2
7
 
3
8
  * Update dependencies
data/lib/clever-ruby.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # rubocop:disable FileName
2
2
  require 'rest_client'
3
3
  require 'multi_json'
4
+ require 'active_support/inflector'
4
5
  require 'open-uri'
5
6
  require 'set'
6
7
  require 'uri'
@@ -10,6 +11,7 @@ require 'clever-ruby/version'
10
11
 
11
12
  # API operations
12
13
  require 'clever-ruby/api_operations/list'
14
+ require 'clever-ruby/api_operations/nested_list'
13
15
  require 'clever-ruby/api_operations/pagelist'
14
16
  require 'clever-ruby/api_operations/results_list'
15
17
  require 'clever-ruby/api_operations/page'
@@ -22,6 +24,7 @@ require 'clever-ruby/configuration'
22
24
  # Resources
23
25
  require 'clever-ruby/clever_object'
24
26
  require 'clever-ruby/api_resource'
27
+ require 'clever-ruby/nested_resource'
25
28
  require 'clever-ruby/district'
26
29
  require 'clever-ruby/school'
27
30
  require 'clever-ruby/student'
@@ -0,0 +1,46 @@
1
+ module Clever
2
+ module APIOperations
3
+ # Methods for interacting with the API on nested resources
4
+ module NestedList
5
+ # Query a nested list with Clever API params, overriding initialized keys
6
+ # @api public
7
+ # @note You don't need to call this if you aren't using additional filters;
8
+ # instead just iterate on the NestedResource itself.
9
+ # @param filters [Hash] Parameters to use
10
+ # @return [Clever::APIOperations::ResultList] list of results
11
+ # @example
12
+ # # Without any overriding
13
+ # district = Clever::Districts.retrieve id
14
+ # district.schools.find(starting_after: lower_bound).each do |school|
15
+ # puts school.name
16
+ # end
17
+ #
18
+ # # With overriding
19
+ # district = Clever::Districts.retrieve id
20
+ # schools = district.schools(starting_after: lower_bound)
21
+ # # The above filter has been overridden for the query below!
22
+ # schools.find(starting_after: even_lower_bound).each do |school|
23
+ # puts school.name
24
+ # end
25
+ def find(filters = {})
26
+ filters = @filters.merge filters
27
+ Clever::APIOperations::PageList.new(@uri, filters).to_results_list
28
+ end
29
+
30
+ # Request the number of elements in a nested list from the API
31
+ # @note This does not count a data structure in memory; it runs an HTTP query!
32
+ # @api public
33
+ # @param filters [Hash] Parameters to use
34
+ # @return [Integer] Results
35
+ # @example
36
+ # district = Clever::Districts.retrieve id
37
+ # num_schools_in_district = district.schools.count
38
+ def count(filters = {})
39
+ filters = @filters.merge filters
40
+ filters[:count] = true
41
+ response = Clever.request :get, @uri, filters
42
+ response[:count]
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,6 +1,45 @@
1
1
  module Clever
2
2
  # Superclass of API resources in the Clever API
3
3
  class APIResource < CleverObject
4
+ @resources = []
5
+
6
+ class << self
7
+ # Get valid API resources
8
+ # @api private
9
+ # @return [Array] List of valid API resource classes
10
+ attr_reader :resources
11
+
12
+ # Get a list of nested resources in the Clever API for this resource
13
+ # @api private
14
+ # @return [Array] List of resources nested under this resource
15
+ attr_reader :linked_resources
16
+ end
17
+
18
+ # Registers valid API resources
19
+ # @api private
20
+ # @return [Object]
21
+ def self.inherited(child_class)
22
+ @resources << child_class
23
+ super
24
+ end
25
+
26
+ # Get a canonical name for a resource
27
+ # @api private
28
+ # @return [String]
29
+ def self.shortname
30
+ name.split('::')[-1].downcase.singularize
31
+ end
32
+
33
+ # Convert the name of a resource to its APIResource subclass
34
+ # @api private
35
+ # @return [APIResource]
36
+ def self.named(name)
37
+ name = name.to_s.downcase.singularize
38
+ matching = resources.select { |res| res.shortname == name }
39
+ return nil if matching.empty?
40
+ matching.first
41
+ end
42
+
4
43
  # Get URL for a resource
5
44
  # @api private
6
45
  # @return [String] url to query for a resource
@@ -9,8 +48,7 @@ module Clever
9
48
  fail NotImplementedError, 'APIResource is an abstract class. You should perform actions '\
10
49
  'on its subclasses (School, Student, etc.)'
11
50
  end
12
- shortname = name.split('::')[-1]
13
- "v1.1/#{CGI.escape shortname.downcase}s"
51
+ "v1.1/#{CGI.escape shortname.pluralize}"
14
52
  end
15
53
 
16
54
  # Get URL for an instance of a resource
@@ -32,16 +70,17 @@ module Clever
32
70
  def refresh
33
71
  response = Clever.request :get, url
34
72
  refresh_from response[:data]
73
+
74
+ @links = response[:links].map do
75
+ |link| { :"#{link[:rel]}" => link[:uri] }
76
+ end.reduce({}, :merge)
35
77
  self
36
78
  end
37
79
 
38
80
  # Get hypermedia links for this resource instance
39
81
  # @api private
40
82
  # @return [Array] list of links for this resource instance
41
- def links
42
- response = Clever.request :get, url
43
- response[:links]
44
- end
83
+ attr_reader :links
45
84
 
46
85
  # Get an instance of a resource
47
86
  # @api public
@@ -56,33 +95,34 @@ module Clever
56
95
  instance
57
96
  end
58
97
 
59
- # Request resource instances by following hypermedia links
98
+ # Get the URI for a hypermedia link
60
99
  # @api private
61
- # @return [Array] List of resources found
62
- def get_linked_resources(resource_type, filters = {})
63
- Util.convert_to_clever_object Clever.request(:get, get_uri(resource_type), filters)[:data]
64
- end
65
-
66
- class << self
67
- # Get a list of nested resources in the Clever API for this resource
68
- # @api private
69
- # @return [Array] List of resources nested under this resource
70
- attr_reader :linked_resources
100
+ # @return [String]
101
+ def get_link_uri(resource_type)
102
+ refresh if links.nil?
103
+ links[resource_type.to_sym]
71
104
  end
72
105
 
73
- # Create an instance of APIResource, defining links to nested resources
74
- # @api public
75
- # @param [String] id of object to instantiate
76
- # @return [APIResoruce] resource instance
77
- # @example
78
- # Clever::District.new '531fabe082d522cds8e22'
106
+ # Construct an APIResource. Generates methods for nested resources
107
+ # @abstract
108
+ # @api private
109
+ # @return [APIResource]
79
110
  def initialize(id)
80
111
  super id
112
+ return if self.class.linked_resources.nil?
81
113
 
82
- resources = self.class.linked_resources || []
83
- resources.each do |resource|
84
- self.class.send :define_method, resource do |filters = {}|
85
- get_linked_resources resource.to_s, filters
114
+ self.class.linked_resources.each do |resource|
115
+ if Clever::Util.singular? resource.to_s
116
+ # Get single resource
117
+ self.class.send :define_method, resource do
118
+ response = Clever.request :get, get_link_uri(resource)
119
+ return Util.convert_to_clever_object response
120
+ end
121
+ else
122
+ # Get list of nested resources
123
+ self.class.send :define_method, resource do |filters = {}|
124
+ Clever::NestedResource.new get_link_uri(resource), filters
125
+ end
86
126
  end
87
127
  end
88
128
  end
@@ -10,9 +10,11 @@ module Clever
10
10
  # The default :id method is deprecated and isn't useful to us
11
11
  undef :id if method_defined? :id
12
12
 
13
- # Create a CleverObject. Only for inheritance purposes
13
+ # Create an instance of CleverObject by id
14
+ # @abstract
14
15
  # @api private
15
- # @return [CleverObject]
16
+ # @param id [String, Hash] id, or values to instantiate from
17
+ # @return [CleverObject] resource instance
16
18
  def initialize(id = nil)
17
19
  @values = {}
18
20
  @values[:id] = id if id
@@ -194,9 +196,13 @@ module Clever
194
196
  # @api private
195
197
  # @return [Object]
196
198
  def add_accessors(keys)
199
+ obj = self
197
200
  metaclass.instance_eval do
198
201
  keys.each do |k|
199
202
  next if @@permanent_attributes.include? k
203
+ unless obj.class.linked_resources.nil?
204
+ next if obj.class.linked_resources.include? k
205
+ end
200
206
  k_eq = :"#{k}="
201
207
  define_method(k) { @values[k] }
202
208
  define_method(k_eq) { |v| @values[k] = v }
@@ -4,6 +4,30 @@ module Clever
4
4
  include Clever::APIOperations::List
5
5
  @linked_resources = [:schools, :teachers, :sections, :students, :events]
6
6
 
7
+ # Get admins for the current district
8
+ # @todo This is not implemented!
9
+ # @api public
10
+ # @raise [NotImplementedError]
11
+ # @return [Object]
12
+ # @example
13
+ # district = district.retrieve id
14
+ # admins = district.admins
15
+ def admins
16
+ fail NotImplementedError, 'admins nested resource not yet implemented.'
17
+ end
18
+
19
+ # Get status of the current district
20
+ # @todo This is not implemented!
21
+ # @api public
22
+ # @raise [NotImplementedError]
23
+ # @return [Object]
24
+ # @example
25
+ # district = district.retrieve id
26
+ # puts district.status
27
+ def status
28
+ fail NotImplementedError, 'status nested resource not yet implemented.'
29
+ end
30
+
7
31
  # @see Clever::CleverObject.optional_attributes
8
32
  # @api private
9
33
  # @return [Array]
@@ -15,18 +39,8 @@ module Clever
15
39
  # TODO: remove
16
40
  [:school_pages, :teacher_pages, :section_pages, :student_pages, :event_pages].each do |name|
17
41
  define_method(name) do |filters = {}|
18
- Clever::APIOperations::PageList.new get_uri(name.to_s.gsub('_page', '')), filters
42
+ Clever::APIOperations::PageList.new get_link_uri(name.to_s.gsub('_page', '')), filters
19
43
  end
20
44
  end
21
-
22
- private
23
-
24
- # Get the URI for a hypermedia link
25
- # @api private
26
- # @return [String]
27
- def get_uri(resource_type)
28
- refresh
29
- links.find { |link| link[:rel] == resource_type }[:uri]
30
- end
31
45
  end
32
46
  end
@@ -17,7 +17,7 @@ module Clever
17
17
  # @example
18
18
  # district = event.object
19
19
  def object
20
- klass = Util.types_to_clever_class type_pieces[0]
20
+ klass = APIResource.named type_pieces[0]
21
21
  klass ||= CleverObject
22
22
  klass.construct_from data[:object]
23
23
  end
@@ -0,0 +1,40 @@
1
+ module Clever
2
+ # An interface for querying nested resources
3
+ class NestedResource
4
+ include Clever::APIOperations::NestedList
5
+ include Enumerable
6
+
7
+ # Create a nested resource
8
+ # @api private
9
+ # @return [Clever::APIOperations::NestedList]
10
+ def initialize(uri, filters = {})
11
+ @uri = uri
12
+ @filters = filters
13
+ @results_list = Clever::APIOperations::PageList.new(uri, filters).to_results_list
14
+ end
15
+
16
+ # Query and iterate over results for the params provided during initialization
17
+ # @api public
18
+ # @return [Clever::APIOperations::NestedResource] self
19
+ # @example
20
+ # district = Clever::Districts.retrieve id
21
+ # district.schools.each { |school| puts school.name }
22
+ def each(&blk)
23
+ @results_list.each(&blk)
24
+ self
25
+ end
26
+
27
+ # Query for all results and count them
28
+ # @api public
29
+ # @note This queries for the actual elements! If you wish to just do a
30
+ # count query, use the count method
31
+ # @return [Integer]
32
+ # @example
33
+ # district = Clever::District.retrieve id
34
+ # num_schools_for_district = district.schools.length
35
+ def length
36
+ @results_list.count
37
+ end
38
+ alias_method :size, :length
39
+ end
40
+ end
@@ -2,7 +2,7 @@ module Clever
2
2
  # School resource
3
3
  class School < APIResource
4
4
  include Clever::APIOperations::List
5
- @linked_resources = [:teachers, :students, :sections, :districts, :events]
5
+ @linked_resources = [:students, :district, :sections, :teachers, :events]
6
6
 
7
7
  # Optional attributes
8
8
  # @see Clever::CleverObject.optional_attributes
@@ -2,7 +2,7 @@ module Clever
2
2
  # Section resource
3
3
  class Section < APIResource
4
4
  include Clever::APIOperations::List
5
- @linked_resources = [:teachers, :students, :schools, :districts, :events]
5
+ @linked_resources = [:school, :district, :students, :teacher, :events]
6
6
 
7
7
  # Optional attributes
8
8
  # @see Clever::CleverObject.optional_attributes
@@ -2,7 +2,19 @@ module Clever
2
2
  # Student resource
3
3
  class Student < APIResource
4
4
  include Clever::APIOperations::List
5
- @linked_resources = [:teachers, :sections, :schools, :districts, :events, :contacts]
5
+ @linked_resources = [:school, :district, :sections, :teachers, :events]
6
+
7
+ # Get contacts for the current student
8
+ # @todo This is not implemented!
9
+ # @api public
10
+ # @raise [NotImplementedError]
11
+ # @return [Object]
12
+ # @example
13
+ # student = student.retrieve id
14
+ # contacts = student.admins
15
+ def contacts
16
+ fail NotImplementedError, 'contacts nested resource not implemented yet.'
17
+ end
6
18
 
7
19
  # Optional attributes
8
20
  # @see Clever::CleverObject.optional_attributes
@@ -2,7 +2,7 @@ module Clever
2
2
  # Teacher resource
3
3
  class Teacher < APIResource
4
4
  include Clever::APIOperations::List
5
- @linked_resources = [:sections, :students, :schools, :districts, :events, :grade_levels]
5
+ @linked_resources = [:school, :district, :students, :sections, :events]
6
6
 
7
7
  # Optional attributes
8
8
  # @see Clever::CleverObject.optional_attributes
@@ -1,6 +1,14 @@
1
1
  module Clever
2
2
  # Library helper methods
3
3
  module Util
4
+ # Check if a given word is singular
5
+ # @api private
6
+ # @param word [String] Word to check
7
+ # @return [Boolean] False if plural, true if singular
8
+ def self.singular?(word)
9
+ word.singularize == word
10
+ end
11
+
4
12
  # Check if a given ID is a valid format (MongoDB BSON ObjectID)
5
13
  # @api private
6
14
  # @param id [String] ID to check
@@ -27,21 +35,6 @@ module Clever
27
35
  end
28
36
  end
29
37
 
30
- # Convert the name of a resource to its APIResource class
31
- # @api private
32
- # @return [APIResource]
33
- def self.types_to_clever_class(type)
34
- types = {
35
- 'students' => Student,
36
- 'sections' => Section,
37
- 'teachers' => Teacher,
38
- 'districts' => District,
39
- 'schools' => School,
40
- 'events' => Event
41
- }
42
- types.fetch type
43
- end
44
-
45
38
  # Convert an object containing data from Clever into a CleverObject
46
39
  # @api private
47
40
  # @return [CleverObject]
@@ -52,8 +45,14 @@ module Clever
52
45
  when Hash
53
46
  # Try converting to a known object class. If none available, fall back to generic
54
47
  # APIResource.
55
- klass_name = %r{/v1.1/([a-z]+)/\S+$}.match(resp[:uri])[1]
56
- klass = types_to_clever_class klass_name if klass_name
48
+ if resp.key? :uri
49
+ uri = resp[:uri]
50
+ else
51
+ uri = resp[:links].select { |l| l[:rel] == 'self' }[0][:uri]
52
+ end
53
+
54
+ klass_name = %r{/v1.1/([a-z]+)/\S+$}.match(uri)[1]
55
+ klass = APIResource.named klass_name if klass_name
57
56
  klass ||= CleverObject
58
57
  klass.construct_from resp[:data]
59
58
  else