active_public_resources 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/active_public_resources.gemspec +1 -0
  4. data/lib/active_public_resources/base_response_type.rb +7 -1
  5. data/lib/active_public_resources/base_return_type.rb +5 -3
  6. data/lib/active_public_resources/driver_response.rb +5 -0
  7. data/lib/active_public_resources/drivers/khan_academy.rb +1 -0
  8. data/lib/active_public_resources/drivers/quizlet.rb +1 -0
  9. data/lib/active_public_resources/drivers/schooltube.rb +1 -0
  10. data/lib/active_public_resources/drivers/vimeo.rb +1 -0
  11. data/lib/active_public_resources/drivers/youtube.rb +8 -7
  12. data/lib/active_public_resources/request_criteria.rb +6 -1
  13. data/lib/active_public_resources/response_types/exercise.rb +3 -2
  14. data/lib/active_public_resources/response_types/folder.rb +2 -8
  15. data/lib/active_public_resources/response_types/image.rb +3 -2
  16. data/lib/active_public_resources/response_types/quiz.rb +4 -3
  17. data/lib/active_public_resources/response_types/video.rb +4 -3
  18. data/lib/active_public_resources/return_types/file.rb +3 -3
  19. data/lib/active_public_resources/return_types/iframe.rb +3 -3
  20. data/lib/active_public_resources/return_types/image_url.rb +3 -3
  21. data/lib/active_public_resources/return_types/oembed.rb +2 -2
  22. data/lib/active_public_resources/return_types/url.rb +2 -2
  23. data/lib/active_public_resources/version.rb +1 -1
  24. data/lib/active_public_resources.rb +2 -0
  25. data/spec/lib/active_public_resources/client_spec.rb +1 -1
  26. data/spec/lib/active_public_resources/driver_response_spec.rb +151 -0
  27. data/spec/lib/active_public_resources/drivers/youtube_spec.rb +1 -1
  28. metadata +18 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f82492f1e5cfc67fee25365b48d83ce58efa170
4
- data.tar.gz: f45c20c7330389c2f59b8f3aad0e03b558780a7a
3
+ metadata.gz: a324e715f7ee235b96e91cf77d6b58154507ecd2
4
+ data.tar.gz: 93c73395724d5ae8d64be0e9cc2a6b649d6d3a2e
5
5
  SHA512:
6
- metadata.gz: 06100044d338f7837c23684f3ea49f7803242300a08497f90e45bceb1ed00826090dbc8e122d5ef2eeced25eb95019a2959473eccdc2c6baa63edd618d092e15
7
- data.tar.gz: bbbbe5c9448f2b80ffcd3c2f51f8a72a5f258b8437a4fd91d066ae78220bc15130c9cc4af4a12a17e64f390076f42d6e9b2701d30cd420a2b99e16605497df59
6
+ metadata.gz: eb36f13ff2951a32db75ac28ffa75e47a7f2ba11517488d64d764d379592c3a8b5bfad158ad235373b3169a32dc3599687dc7ed74e338b51977828a3db1efe4b
7
+ data.tar.gz: fd7a53620ad17cde8d643280bad3fcf706873f9e32b2064736906605db41040fe64d5dbde9acdfe1cddfd5113c87e7370c565636a49282177c00041386675a5c
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/instructure/active_public_resources.png)](https://travis-ci.org/instructure/active_public_resources)
4
4
  [![Code Climate](https://codeclimate.com/github/instructure/active_public_resources.png)](https://codeclimate.com/github/instructure/active_public_resources)
5
+ [![Gemnasium](https://gemnasium.com/instructure/active_public_resources.png)](https://gemnasium.com/instructure/active_public_resources)
6
+ [![Gem Version](https://badge.fury.io/rb/active_public_resources.png)](http://badge.fury.io/rb/active_public_resources)
5
7
 
6
8
  Active Public Resources is a collection of resources online which return embeddable or linkable
7
9
  resources. This gem normalizes the requests and responses into response type objects.
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "active_support", ">= 3.0.0"
22
+ spec.add_dependency "activemodel", ">= 3.0.0"
22
23
 
23
24
  # Drivers
24
25
  spec.add_dependency "vimeo", "~> 1.5.3"
@@ -1,11 +1,17 @@
1
1
  module ActivePublicResources
2
2
  module ResponseTypes
3
3
  class BaseResponseType
4
- attr_accessor :id, :title, :description, :return_types
4
+ include ::ActiveModel::Serialization
5
+
6
+ attr_accessor :id, :title, :description, :return_types, :kind
5
7
 
6
8
  def initialize
7
9
  @return_types = []
8
10
  end
11
+
12
+ def attributes
13
+ instance_values
14
+ end
9
15
  end
10
16
  end
11
17
  end
@@ -1,7 +1,9 @@
1
1
  module ActivePublicResources
2
2
  module ReturnTypes
3
3
  class BaseReturnType
4
- attr_accessor :url
4
+ include ::ActiveModel::Serialization
5
+
6
+ attr_accessor :url, :return_type
5
7
 
6
8
  def initialize(args)
7
9
  args.each do |k,v|
@@ -9,8 +11,8 @@ module ActivePublicResources
9
11
  end
10
12
  end
11
13
 
12
- def return_type
13
- raise NotImplementedError.new("You must implement return_type.")
14
+ def attributes
15
+ instance_values
14
16
  end
15
17
  end
16
18
  end
@@ -1,6 +1,8 @@
1
1
  module ActivePublicResources
2
2
  module Drivers
3
3
  class DriverResponse
4
+ include ::ActiveModel::Serializers::JSON
5
+
4
6
  attr_accessor :items, :criteria, :next_criteria, :total_items
5
7
 
6
8
  def initialize(args)
@@ -10,6 +12,9 @@ module ActivePublicResources
10
12
  @items ||= []
11
13
  end
12
14
 
15
+ def attributes
16
+ instance_values
17
+ end
13
18
  end
14
19
  end
15
20
  end
@@ -82,6 +82,7 @@ module ActivePublicResources
82
82
  video.description = data['description']
83
83
  video.thumbnail_url = data['image_url']
84
84
  video.url = data['url']
85
+ video.embed_url = "//www.youtube.com/embed/#{data['youtube_id']}?feature=oembed"
85
86
  video.duration = data['duration'] ? data['duration'].to_i : 0
86
87
  video.num_views = 0
87
88
  video.num_likes = 0
@@ -54,6 +54,7 @@ module ActivePublicResources
54
54
  quiz.title = data['title']
55
55
  quiz.description = data['description']
56
56
  quiz.url = data['url']
57
+ quiz.username = data['username']
57
58
  quiz.term_count = data['term_count']
58
59
  quiz.created_date = Time.at(data['created_date']).utc.to_date
59
60
  quiz.has_images = data['has_images']
@@ -68,6 +68,7 @@ module ActivePublicResources
68
68
  video.description = data['description']
69
69
  video.thumbnail_url = data['thumbnail_url']
70
70
  video.url = data['short_url']
71
+ video.embed_url = "//www.schooltube.com/embed/#{data['vkey']}"
71
72
  video.duration = data['duration'] ? data['duration'].to_i : 0
72
73
  video.num_views = data['view_count'] ? data['view_count'].to_i : 0
73
74
  video.num_likes = data['thumbs_up'] ? data['thumbs_up'].to_i : 0
@@ -150,6 +150,7 @@ module ActivePublicResources
150
150
  video.description = data['description']
151
151
  video.thumbnail_url = data['thumbnails']['thumbnail'][0]['_content']
152
152
  video.url = data['urls']['url'][0]['_content']
153
+ video.embed_url = "//player.vimeo.com/video/#{data['id']}"
153
154
  video.duration = data['duration'].to_i
154
155
  video.num_views = data['number_of_plays'].to_i
155
156
  video.num_likes = data['number_of_likes'].to_i
@@ -33,9 +33,9 @@ module ActivePublicResources
33
33
  when APR::RequestCriteria::SORT_RELEVANCE
34
34
  'relevance'
35
35
  when APR::RequestCriteria::SORT_RECENT
36
- 'relevance'
36
+ 'published'
37
37
  when APR::RequestCriteria::SORT_POPULAR
38
- 'relevance'
38
+ 'viewCount'
39
39
  else
40
40
  'relevance'
41
41
  end
@@ -62,13 +62,13 @@ module ActivePublicResources
62
62
  end
63
63
 
64
64
  def next_criteria(request_criteria, results)
65
- page = results['feed']['openSearch$startIndex']['$t'].to_i
66
- per_page = results['feed']['openSearch$itemsPerPage']['$t'].to_i
67
- total = results['feed']['openSearch$totalResults']['$t'].to_i
68
- if ((page * per_page) < total)
65
+ start_index = results['feed']['openSearch$startIndex']['$t'].to_i
66
+ per_page = results['feed']['openSearch$itemsPerPage']['$t'].to_i
67
+ total = results['feed']['openSearch$totalResults']['$t'].to_i
68
+ if (start_index + per_page) < total
69
69
  return RequestCriteria.new({
70
70
  :query => request_criteria.query,
71
- :page => page + 1,
71
+ :page => start_index + per_page,
72
72
  :per_page => per_page
73
73
  })
74
74
  end
@@ -82,6 +82,7 @@ module ActivePublicResources
82
82
  video.description = data['media$group']['media$description']['$t']
83
83
  video.thumbnail_url = data['media$group']['media$thumbnail'][0]['url']
84
84
  video.url = data['media$group']['media$player']['url']
85
+ video.embed_url = "//www.youtube.com/embed/#{video_id}?feature=oembed"
85
86
  video.duration = data['media$group']['yt$duration']['seconds'].to_i
86
87
  video.num_views = data['yt$statistics'] ? data['yt$statistics']['viewCount'].to_i : 0
87
88
  video.num_likes = data['yt$rating'] ? data['yt$rating']['numLikes'].to_i : 0
@@ -1,6 +1,7 @@
1
1
  module ActivePublicResources
2
2
  class RequestCriteria
3
-
3
+ include ::ActiveModel::Serialization
4
+
4
5
  SORTS = [
5
6
  SORT_RELEVANCE = 'relevance',
6
7
  SORT_RECENT = 'recent',
@@ -47,5 +48,9 @@ module ActivePublicResources
47
48
  end
48
49
  end
49
50
  end
51
+
52
+ def attributes
53
+ instance_values
54
+ end
50
55
  end
51
56
  end
@@ -3,8 +3,9 @@ module ActivePublicResources
3
3
  class Exercise < BaseResponseType
4
4
  attr_accessor :thumbnail_url, :url
5
5
 
6
- def kind
7
- 'exercise'
6
+ def initialize
7
+ super
8
+ @kind = 'exercise'
8
9
  end
9
10
  end
10
11
  end
@@ -1,17 +1,11 @@
1
1
  module ActivePublicResources
2
2
  module ResponseTypes
3
3
  class Folder < BaseResponseType
4
- attr_accessor :parent_id, :videos, :exercises, :images
4
+ attr_accessor :parent_id
5
5
 
6
6
  def initialize
7
7
  super
8
- @videos = []
9
- @exercises = []
10
- @images = []
11
- end
12
-
13
- def kind
14
- 'folder'
8
+ @kind = 'folder'
15
9
  end
16
10
  end
17
11
  end
@@ -3,8 +3,9 @@ module ActivePublicResources
3
3
  class Image < BaseResponseType
4
4
  attr_accessor :url, :width, :height
5
5
 
6
- def kind
7
- 'image'
6
+ def initialize
7
+ super
8
+ @kind = 'image'
8
9
  end
9
10
  end
10
11
  end
@@ -1,10 +1,11 @@
1
1
  module ActivePublicResources
2
2
  module ResponseTypes
3
3
  class Quiz < BaseResponseType
4
- attr_accessor :url, :term_count, :created_date, :has_images, :subjects
4
+ attr_accessor :url, :term_count, :username, :created_date, :has_images, :subjects
5
5
 
6
- def kind
7
- 'quiz'
6
+ def initialize
7
+ super
8
+ @kind = 'quiz'
8
9
  end
9
10
  end
10
11
  end
@@ -1,11 +1,12 @@
1
1
  module ActivePublicResources
2
2
  module ResponseTypes
3
3
  class Video < BaseResponseType
4
- attr_accessor :thumbnail_url, :url, :duration, :width, :height, :username,
4
+ attr_accessor :thumbnail_url, :url, :embed_url, :duration, :width, :height, :username,
5
5
  :num_views, :num_likes, :num_comments, :created_date
6
6
 
7
- def kind
8
- 'video'
7
+ def initialize
8
+ super
9
+ @kind = 'video'
9
10
  end
10
11
  end
11
12
  end
@@ -2,9 +2,9 @@ module ActivePublicResources
2
2
  module ReturnTypes
3
3
  class File < BaseReturnType
4
4
  attr_accessor :text, :content_type
5
-
6
- def return_type
7
- 'file'
5
+
6
+ def initialize(args)
7
+ super(args.merge(:return_type => 'file'))
8
8
  end
9
9
  end
10
10
  end
@@ -2,9 +2,9 @@ module ActivePublicResources
2
2
  module ReturnTypes
3
3
  class Iframe < BaseReturnType
4
4
  attr_accessor :title, :width, :height
5
-
6
- def return_type
7
- 'iframe'
5
+
6
+ def initialize(args)
7
+ super(args.merge(:return_type => 'iframe'))
8
8
  end
9
9
  end
10
10
  end
@@ -2,9 +2,9 @@ module ActivePublicResources
2
2
  module ReturnTypes
3
3
  class ImageUrl < BaseReturnType
4
4
  attr_accessor :text, :width, :height
5
-
6
- def return_type
7
- 'image_url'
5
+
6
+ def initialize(args)
7
+ super(args.merge(:return_type => 'image_url'))
8
8
  end
9
9
  end
10
10
  end
@@ -3,8 +3,8 @@ module ActivePublicResources
3
3
  class Oembed < BaseReturnType
4
4
  attr_accessor :endpoint
5
5
 
6
- def return_type
7
- 'oembed'
6
+ def initialize(args)
7
+ super(args.merge(:return_type => 'oembed'))
8
8
  end
9
9
  end
10
10
  end
@@ -3,8 +3,8 @@ module ActivePublicResources
3
3
  class Url < BaseReturnType
4
4
  attr_accessor :text, :title, :target
5
5
 
6
- def return_type
7
- 'url'
6
+ def initialize(args)
7
+ super(args.merge(:return_type => 'url'))
8
8
  end
9
9
  end
10
10
  end
@@ -1,3 +1,3 @@
1
1
  module ActivePublicResources
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,6 +1,8 @@
1
1
  require "active_support"
2
2
  require "active_support/core_ext/object/blank"
3
3
  require "active_support/core_ext/string/inflections"
4
+ require "active_model"
5
+
4
6
  require "active_public_resources/version"
5
7
  require "active_public_resources/client"
6
8
  require "active_public_resources/request_criteria"
@@ -32,7 +32,7 @@ describe APR::Client do
32
32
  it "should perform request", :vcr, :record => :none do
33
33
  results = client.perform_request(:youtube, criteria)
34
34
  next_criteria = results.next_criteria
35
- next_criteria.page.should eq(2)
35
+ next_criteria.page.should eq(26)
36
36
  next_criteria.per_page.should eq(25)
37
37
  results.total_items.should eq(1000000)
38
38
  results.items.length.should eq(25)
@@ -0,0 +1,151 @@
1
+ require 'spec_helper'
2
+
3
+ describe APR::Drivers::DriverResponse do
4
+
5
+ it "should render json" do
6
+ request_criteria = APR::RequestCriteria.new({
7
+ :query => "education",
8
+ :page => 1,
9
+ :per_page => 25,
10
+ :sort => APR::RequestCriteria::SORT_RELEVANCE,
11
+ :content_filter => APR::RequestCriteria::CONTENT_FILTER_NONE
12
+ })
13
+
14
+ next_criteria = APR::RequestCriteria.new({
15
+ :query => "education",
16
+ :page => 2,
17
+ :per_page => 25,
18
+ :sort => APR::RequestCriteria::SORT_RELEVANCE,
19
+ :content_filter => APR::RequestCriteria::CONTENT_FILTER_NONE
20
+ })
21
+
22
+ driver_response = APR::Drivers::DriverResponse.new(
23
+ :criteria => request_criteria,
24
+ :next_criteria => next_criteria,
25
+ :total_items => 5500,
26
+ :items => [ exercise, folder, image, quiz, video ]
27
+ )
28
+
29
+ data = JSON.parse(driver_response.to_json)['driver_response']
30
+ data['criteria']['query'].should eq('education')
31
+ data['next_criteria']['page'].should eq(2)
32
+ data['total_items'].should eq(5500)
33
+ data['items'].length.should eq(5)
34
+ data['items'][0]['kind'].should eq('exercise')
35
+ data['items'][0]['title'].should eq(exercise.title)
36
+ data['items'][0]['return_types'][0]['text'].should eq(exercise.title)
37
+ data['items'][1]['kind'].should eq('folder')
38
+ data['items'][1]['title'].should eq(folder.title)
39
+ data['items'][2]['kind'].should eq('image')
40
+ data['items'][2]['title'].should eq(image.title)
41
+ data['items'][3]['kind'].should eq('quiz')
42
+ data['items'][3]['title'].should eq(quiz.title)
43
+ data['items'][3]['return_types'][0]['text'].should eq(quiz.title)
44
+ data['items'][4]['kind'].should eq('video')
45
+ data['items'][4]['title'].should eq(video.title)
46
+ data['items'][4]['return_types'][0]['text'].should eq(video.title)
47
+ end
48
+
49
+ private
50
+
51
+ def video
52
+ video = APR::ResponseTypes::Video.new
53
+ video.id = 1
54
+ video.title = 'Video Title'
55
+ video.description = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.'
56
+ video.thumbnail_url = 'http://placekitten.com/50/50.png'
57
+ video.url = 'http://example.com/videos/1'
58
+ video.duration = 150
59
+ video.num_views = 1100
60
+ video.num_likes = 600
61
+ video.num_comments = 300
62
+ video.created_date = Date.today
63
+ video.username = 'joe'
64
+ video.width = 640
65
+ video.height = 360
66
+ video.return_types << APR::ReturnTypes::Url.new({
67
+ :url => 'http://example.com/videos/1',
68
+ :text => 'Video Title',
69
+ :title => 'Video Title'
70
+ })
71
+ video.return_types << APR::ReturnTypes::Url.new({
72
+ :url => "//player.vimeo.com/video/1",
73
+ :text => 'Video Title',
74
+ :title => 'Video Title',
75
+ :width => 640,
76
+ :height => 360
77
+ })
78
+ video
79
+ end
80
+
81
+ def folder
82
+ folder = APR::ResponseTypes::Folder.new
83
+ folder.id = 1
84
+ folder.title = 'Programming'
85
+ folder.description = 'Programming videos'
86
+ folder.parent_id = 'root'
87
+ folder
88
+ end
89
+
90
+ def exercise
91
+ exercise = APR::ResponseTypes::Exercise.new
92
+ exercise.id = 1
93
+ exercise.title = 'Exercise Title'
94
+ exercise.description = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.'
95
+ exercise.thumbnail_url = 'http://placekitten.com/50/50.png'
96
+ exercise.url = 'http://example.com/exercise/1'
97
+ exercise.return_types << APR::ReturnTypes::Url.new({
98
+ :url => 'http://example.com/exercise/1',
99
+ :text => 'Exercise Title',
100
+ :title => 'Exercise Title'
101
+ })
102
+ exercise
103
+ end
104
+
105
+ def image
106
+ image = APR::ResponseTypes::Image.new
107
+ image.id = 1
108
+ image.title = 'Image Title'
109
+ image.description = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.'
110
+ image.url = 'http://placekitten.com/50/50.png'
111
+ image.width = 50
112
+ image.height = 50
113
+ image
114
+ end
115
+
116
+ def quiz
117
+ quiz = APR::ResponseTypes::Quiz.new
118
+ quiz.id = 1
119
+ quiz.title = 'Quiz Title'
120
+ quiz.description = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.'
121
+ quiz.url = 'http://placekitten.com/50/50.png'
122
+ quiz.return_types << APR::ReturnTypes::Url.new({
123
+ :url => 'http://placekitten.com/50/50.png',
124
+ :text => "Quiz Title",
125
+ :title => "Quiz Title"
126
+ })
127
+ quiz.return_types << APR::ReturnTypes::Url.new({
128
+ :url => "https://quizlet.com/1/flashcards/embedv2",
129
+ :text => "Flashcards",
130
+ :title => "Quiz Title",
131
+ :width => "100%",
132
+ :height => 410
133
+ })
134
+ quiz.return_types << APR::ReturnTypes::Url.new({
135
+ :url => "https://quizlet.com/1/scatter/embedv2",
136
+ :text => "Scatter",
137
+ :title => "Quiz Title",
138
+ :width => "100%",
139
+ :height => 410
140
+ })
141
+ quiz.return_types << APR::ReturnTypes::Url.new({
142
+ :url => "https://quizlet.com/1/spacerace/embedv2",
143
+ :text => "Space Race",
144
+ :title => "Quiz Title",
145
+ :width => "100%",
146
+ :height => 410
147
+ })
148
+ quiz
149
+ end
150
+
151
+ end
@@ -15,7 +15,7 @@ describe APR::Drivers::Youtube do
15
15
  search_criteria = APR::RequestCriteria.new({:query => "education"})
16
16
  results = driver.perform_request(search_criteria)
17
17
  next_criteria = results.next_criteria
18
- next_criteria.page.should eq(2)
18
+ next_criteria.page.should eq(26)
19
19
  next_criteria.per_page.should eq(25)
20
20
  results.total_items.should eq(1000000)
21
21
  results.items.length.should eq(25)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_public_resources
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
  - Eric Berry
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-03 00:00:00.000000000 Z
11
+ date: 2013-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_support
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activemodel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 3.0.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: vimeo
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -93,6 +107,7 @@ files:
93
107
  - lib/active_public_resources/return_types/url.rb
94
108
  - lib/active_public_resources/version.rb
95
109
  - spec/lib/active_public_resources/client_spec.rb
110
+ - spec/lib/active_public_resources/driver_response_spec.rb
96
111
  - spec/lib/active_public_resources/driver_spec.rb
97
112
  - spec/lib/active_public_resources/drivers/khan_academy_spec.rb
98
113
  - spec/lib/active_public_resources/drivers/quizlet_spec.rb
@@ -149,6 +164,7 @@ specification_version: 4
149
164
  summary: Normalized searching and browsing of public resources
150
165
  test_files:
151
166
  - spec/lib/active_public_resources/client_spec.rb
167
+ - spec/lib/active_public_resources/driver_response_spec.rb
152
168
  - spec/lib/active_public_resources/driver_spec.rb
153
169
  - spec/lib/active_public_resources/drivers/khan_academy_spec.rb
154
170
  - spec/lib/active_public_resources/drivers/quizlet_spec.rb