clever-ruby 0.6.2 → 0.7.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 (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