lightside 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/.gitignore +3 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +3 -0
  4. data/Guardfile +5 -0
  5. data/README.md +4 -0
  6. data/lib/lightside.rb +6 -0
  7. data/lib/lightside/config.rb +23 -0
  8. data/lib/lightside/exceptions.rb +12 -0
  9. data/lib/lightside/models/answer.rb +12 -0
  10. data/lib/lightside/models/answer_set.rb +12 -0
  11. data/lib/lightside/models/assignment_icon.rb +12 -0
  12. data/lib/lightside/models/assignment_tile_color.rb +12 -0
  13. data/lib/lightside/models/author.rb +12 -0
  14. data/lib/lightside/models/corpus.rb +16 -0
  15. data/lib/lightside/models/human_score.rb +12 -0
  16. data/lib/lightside/models/prediction_result.rb +12 -0
  17. data/lib/lightside/models/prediction_task.rb +25 -0
  18. data/lib/lightside/models/prompt.rb +12 -0
  19. data/lib/lightside/models/resolved_score.rb +12 -0
  20. data/lib/lightside/models/tag_answer_set.rb +12 -0
  21. data/lib/lightside/models/tag_prompt.rb +12 -0
  22. data/lib/lightside/models/trained_model.rb +12 -0
  23. data/lib/lightside/models/trained_model_evaluation.rb +12 -0
  24. data/lib/lightside/models/training_answer.rb +12 -0
  25. data/lib/lightside/models/training_task.rb +25 -0
  26. data/lib/lightside/pager.rb +72 -0
  27. data/lib/lightside/resources.rb +171 -0
  28. data/lib/lightside/version.rb +4 -0
  29. data/lightside.gemspec +27 -0
  30. data/spec/config_spec.rb +36 -0
  31. data/spec/fixtures/prompts.json +1 -0
  32. data/spec/fixtures/prompts/2.json +1 -0
  33. data/spec/fixtures/prompts_1.json +1 -0
  34. data/spec/fixtures/prompts_2.json +1 -0
  35. data/spec/fixtures/prompts_3.json +1 -0
  36. data/spec/fixtures/prompts_4.json +1 -0
  37. data/spec/pager_spec.rb +104 -0
  38. data/spec/resources_spec.rb +228 -0
  39. data/spec/spec_helper.rb +22 -0
  40. metadata +206 -0
@@ -0,0 +1,3 @@
1
+ .ruby-version
2
+ .ruby-gemset
3
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec(:name => 'lightside')
@@ -0,0 +1,5 @@
1
+ guard :rspec do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
@@ -0,0 +1,4 @@
1
+ lightside
2
+ =========
3
+
4
+ LightSide Ruby API
@@ -0,0 +1,6 @@
1
+ require 'json'
2
+ require 'ostruct'
3
+ require 'rest_client'
4
+
5
+ Gem.find_files("lightside/*.rb").each { |f| require f}
6
+ Gem.find_files("lightside/models/*.rb").each { |f| require f}
@@ -0,0 +1,23 @@
1
+ module LightSide
2
+
3
+ def self.configure
4
+ @configuration ||= LightSide::Config
5
+ yield @configuration if block_given?
6
+ @configuration
7
+ end
8
+
9
+ class Config
10
+ singleton_class.class_eval do
11
+ attr_accessor :auth_token, :base_url
12
+ end
13
+
14
+ def self.headers
15
+ { "Authorization" => "Token #{auth_token}", "Content-Type" => "application/json" }
16
+ end
17
+
18
+ def self.configured?
19
+ auth_token && base_url
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+
3
+ class ResourceNotFound < StandardError; end
4
+ class ResourceNotCreated < StandardError; end
5
+
6
+ class NotConfigured < StandardError
7
+ def to_s
8
+ "one ore more configuration settings is missing"
9
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class Answer
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "answers"
7
+ self.readonly_attributes = %w( url predicted prediction_results created modified )
8
+ self.writable_attributes = %w( parent author answer_set text author_comments reviewer_commentss submission viewed auth_token )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class AnswerSet
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "answer-sets"
7
+ self.readonly_attributes = %w( url owner answers prediction_tasks created modified )
8
+ self.writable_attributes = %w( prompt icon tile_color auth_token trained_models tags )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class AssignmentIcon
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "assignment-icons"
7
+ self.readonly_attributes = %w( url name description image created )
8
+ self.writable_attributes = %w( )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class AssignmentTileColor
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "assignment-tile-colors"
7
+ self.readonly_attributes = %w( url color )
8
+ self.writable_attributes = %w( )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class Author
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "authors"
7
+ self.readonly_attributes = %w( url owner answers created modified )
8
+ self.writable_attributes = %w( designator email auth_token active )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ module LightSide
2
+ class Corpus
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "corpora"
7
+ self.readonly_attributes = %w( url owner training_answers created modified )
8
+ self.writable_attributes = %w( prompt description active )
9
+ end
10
+
11
+ def training_answer_ids
12
+ training_answers.map { |url| url.split("/").last }
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class HumanScore
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "human-scores"
7
+ self.readonly_attributes = %w( url created modified )
8
+ self.writable_attributes = %w( training_answer label )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class PredictionResult
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "prediction-results"
7
+ self.readonly_attributes = %w( url answer prediction_task trained_model distribution label possible_labels created modified )
8
+ self.writable_attributes = %w( )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ module LightSide
2
+ class PredictionTask
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "prediction-tasks"
7
+ self.readonly_attributes = %w( url process task_id owner status messages prediction_results created modified )
8
+ self.writable_attributes = %w( answer_set )
9
+ end
10
+
11
+ def process_start
12
+ RestClient.post(process, "", Config.headers) do |response, request, result|
13
+ case response.code
14
+ when 200, 202
15
+ return JSON.parse(response)
16
+ when 404
17
+ raise ResourceNotFound, "could not find #{name} with ID=#{id}"
18
+ else
19
+ raise JSON.parse(response)["detail"]
20
+ end
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class Prompt
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "prompts"
7
+ self.readonly_attributes = %w( url owner parent corpora answer_sets created modified )
8
+ self.writable_attributes = %w( title text instructions description lower upper default_models alignments tags active )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class ResolvedScore
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "resolved-scores"
7
+ self.readonly_attributes = %w( url created modified )
8
+ self.writable_attributes = %w( training_answer label )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class TagPrompt
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "tags/prompts"
7
+ self.readonly_attributes = %w( name num_times )
8
+ self.writable_attributes = %w( )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class TagAnswerSet
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "tags/answer_sets"
7
+ self.readonly_attributes = %w( name num_times )
8
+ self.writable_attributes = %w( )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class TrainedModel
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "trained-models"
7
+ self.readonly_attributes = %w( url corpus learner feature_set creation_method recipe_file active created modified )
8
+ self.writable_attributes = %w( name evaluations predictions )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class TrainedModelEvaluation
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "trained-model-evaluations"
7
+ self.readonly_attributes = %w( url trained_model accuracy entropy kappa weighted_kappa label created modified )
8
+ self.writable_attributes = %w( )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module LightSide
2
+ class TrainingAnswer
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "training-answers"
7
+ self.readonly_attributes = %w( url created modified )
8
+ self.writable_attributes = %w( corpus text )
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ module LightSide
2
+ class TrainingTask
3
+ include LightSide::Resources
4
+
5
+ setup do
6
+ self.resource_base = "training-tasks"
7
+ self.readonly_attributes = %w( url process task_id owner status messages trained_model created modified )
8
+ self.writable_attributes = %w( corpus )
9
+ end
10
+
11
+ def process_start
12
+ RestClient.post(process, "", Config.headers) do |response, request, result|
13
+ case response.code
14
+ when 200, 202
15
+ yield JSON.parse(response)
16
+ when 404
17
+ raise ResourceNotFound, "could not find #{name} with ID=#{id}"
18
+ else
19
+ raise JSON.parse(response)["detail"]
20
+ end
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,72 @@
1
+ module LightSide
2
+ class Pager
3
+ include Enumerable
4
+
5
+ attr_accessor :collection, :next_url, :params, :previous_url, :resource_builder, :resource_url, :url
6
+
7
+ def initialize(model_class, params={})
8
+ self.resource_url = model_class.resource_url
9
+ self.resource_builder = lambda { |hash| model_class.new(hash) }
10
+ self.params = { page: 1 }.merge(params)
11
+ self.collection = []
12
+ self.url = resource_path
13
+ end
14
+
15
+ def count
16
+ collection.length
17
+ end
18
+
19
+ def each
20
+ collection.each { |instance| yield instance }
21
+ end
22
+
23
+ def fetch
24
+ self.collection = []
25
+ fetch_page
26
+ self
27
+ end
28
+
29
+ def fetch_page
30
+ RestClient.get(url, Config.headers) do |response, request, result|
31
+ case response.code
32
+ when 200
33
+ parsed_response = JSON.parse(response)
34
+ self.next_url = parsed_response["next"]
35
+ self.previous_url = parsed_response["previous"]
36
+ parsed_response["results"].each do |resource|
37
+ collection << resource_builder.call(resource)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def less?
44
+ !!previous_url
45
+ end
46
+
47
+ def more?
48
+ !!next_url
49
+ end
50
+
51
+ def next
52
+ raise "no more results" unless more?
53
+ self.url = next_url
54
+ fetch
55
+ end
56
+
57
+ def page_number
58
+ params.fetch(:page, 1).to_i
59
+ end
60
+
61
+ def previous
62
+ raise "no more results" unless less?
63
+ self.url = previous_url
64
+ fetch
65
+ end
66
+
67
+ def resource_path
68
+ URI.join(resource_url, "?#{URI.encode_www_form(params)}").to_s
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,171 @@
1
+ module LightSide
2
+ module Resources
3
+
4
+ def initialize(hash={})
5
+ set_attributes_from_hash(hash)
6
+ end
7
+
8
+ def attributes
9
+ self.class.attributes.inject({}) do |memo, attr|
10
+ memo.merge(attr => self.__send__(attr))
11
+ end
12
+ end
13
+
14
+ def delete
15
+ self.class.delete_resource(id)
16
+ end
17
+
18
+ def id
19
+ url && url.split("/").last
20
+ end
21
+
22
+ def reload
23
+ self.class.resource(id) do |hash|
24
+ set_attributes_from_hash(hash)
25
+ end
26
+ self
27
+ end
28
+
29
+ def update
30
+ save
31
+ end
32
+
33
+ def save
34
+ json = JSON.generate(writable_attributes)
35
+ if id
36
+ self.class.update_resource(id, json) { |hash| set_attributes_from_hash(hash) }
37
+ else
38
+ self.class.create_resource(json) { |hash| set_attributes_from_hash(hash) }
39
+ end
40
+ self
41
+ end
42
+
43
+ def set_attributes_from_hash(hash)
44
+ self.class.attributes.each do |attr|
45
+ self.__send__("#{attr.to_s}=", hash.fetch(attr, nil))
46
+ end
47
+ end
48
+
49
+ def to_s
50
+ %w(id url errors).map(&:to_sym).inject("#{self.class.name}") do |memo, attr|
51
+ val = self.__send__(attr)
52
+ memo << " #{attr}:#{val}" if val
53
+ memo
54
+ end
55
+ end
56
+
57
+ def writable_attributes
58
+ self.class.writable_attributes.inject({}) do |memo, attr|
59
+ memo.merge(attr => self.__send__(attr))
60
+ end
61
+ end
62
+
63
+ def self.included(base)
64
+ base.extend(ClassMethods)
65
+ base.singleton_class.class_eval { attr_accessor :resource_base, :readonly_attributes, :writable_attributes }
66
+ end
67
+
68
+ module ClassMethods
69
+ def all
70
+ resources
71
+ end
72
+
73
+ def attributes
74
+ @readonly_attributes.to_a + @writable_attributes.to_a + ["errors"]
75
+ end
76
+
77
+ def create(data)
78
+ create_resource(data) { |hash| new(hash) }
79
+ end
80
+
81
+ def create_resource(data)
82
+ RestClient.post(resource_url, data, Config.headers) do |response, request, result|
83
+ case response.code
84
+ when 201
85
+ yield JSON.parse(response)
86
+ when 400
87
+ yield JSON.parse(data).merge!("errors" => JSON.parse(response))
88
+ else
89
+ raise response
90
+ end
91
+ end
92
+ end
93
+
94
+ def delete(id)
95
+ delete_resource(id)
96
+ end
97
+
98
+ def delete_resource(id)
99
+ RestClient.delete(resource_url(id), Config.headers) do |response, request, result|
100
+ case response.code
101
+ when 204
102
+ return true
103
+ when 404
104
+ raise ResourceNotFound, "could not find #{name} with ID=#{id}"
105
+ else
106
+ raise response
107
+ end
108
+ end
109
+ end
110
+
111
+ def find(id)
112
+ resource(id) { |hash| new(hash) }
113
+ end
114
+
115
+ def page(page_num)
116
+ LightSide::Pager.new(self, { page: Integer(page_num) }).fetch
117
+ end
118
+
119
+ def query(query_params)
120
+ resources(query_params)
121
+ end
122
+
123
+ def resource_url(id=nil)
124
+ raise LightSide::NotConfigured unless Config.configured?
125
+ [Config.base_url, "#{resource_base}/#{id}"].join("/")
126
+ end
127
+
128
+ def resources(params={})
129
+ LightSide::Pager.new(self, params).fetch
130
+ end
131
+
132
+ def resource(id)
133
+ RestClient.get(resource_url(id), Config.headers) do |response, request, result|
134
+ case response.code
135
+ when 200
136
+ yield JSON.parse(response)
137
+ when 404
138
+ raise ResourceNotFound, "could not find #{name} with ID=#{id}"
139
+ else
140
+ raise response
141
+ end
142
+ end
143
+ end
144
+
145
+ def setup
146
+ yield
147
+ attributes.each { |attr| attr_accessor attr.to_s }
148
+ end
149
+
150
+ def update(id, data)
151
+ update_resource(id, data) { |hash| new(hash) }
152
+ end
153
+
154
+ def update_resource(id, data)
155
+ RestClient.put(resource_url(id), data, Config.headers) do |response, request, result|
156
+ case response.code
157
+ when 200
158
+ yield JSON.parse(response)
159
+ when 400
160
+ yield ({"errors" => JSON.parse(response)})
161
+ when 404
162
+ raise ResourceNotFound, "could not find #{name} with ID=#{id}"
163
+ else
164
+ raise response
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ end
171
+ end
@@ -0,0 +1,4 @@
1
+ module LightSide
2
+ VERSION = '0.0.1'
3
+ end
4
+
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../lib/lightside/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'lightside'
5
+ s.version = LightSide::VERSION
6
+ s.date = '2013-12-02'
7
+ s.summary = 'LightSide API'
8
+ s.description = 'Ruby wrapper for LightSide Web API'
9
+ s.authors = ['Tom Head']
10
+ s.email = 'tom.head@revolutionprep.com'
11
+ s.homepage = 'http://github.com/RevolutionK12/lightside'
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ s.homepage = ""
16
+ s.license = 'MIT'
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'rest-client'
20
+
21
+ s.add_development_dependency 'rspec'
22
+ s.add_development_dependency 'webmock'
23
+ s.add_development_dependency 'pry'
24
+ s.add_development_dependency 'pry-nav'
25
+ s.add_development_dependency 'guard'
26
+ s.add_development_dependency 'guard-rspec'
27
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe LightSide::Config do
4
+ let(:auth_token) { "abc123" }
5
+ let(:base_url) { "https://api.example.com/api/" }
6
+
7
+ it "can set auth_token" do
8
+ LightSide.configure do |config|
9
+ config.auth_token = auth_token
10
+ end
11
+ expect( LightSide::Config.auth_token ).to eq auth_token
12
+ end
13
+
14
+ it "can set base_url" do
15
+ LightSide.configure do |config|
16
+ config.base_url = base_url
17
+ end
18
+ expect( LightSide::Config.base_url ).to eq base_url
19
+ end
20
+
21
+ context ".configured?" do
22
+ context "when auth_token is missing" do
23
+ it "returns false" do
24
+ LightSide::Config.auth_token = nil
25
+ expect( LightSide::Config.configured? ).to be_false
26
+ end
27
+ end
28
+
29
+ context "when base_url is missing" do
30
+ it "returns false" do
31
+ LightSide::Config.base_url = nil
32
+ expect( LightSide::Config.configured? ).to be_false
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1 @@
1
+ {"count": 2, "next": null, "previous": null, "results": [{"url": "https://api.example.com/api/prompts/2", "owner": 2, "parent": null, "title": "ASAP Dataset #2: Persuasive Essay on Censorship", "text": "ASAP Dataset #2: Persuasive Essay on Censorship", "instructions": "", "description": "<blockquote>\"All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.\" <footer>&mdash; Katherine Paterson, Author</footer></blockquote>\r\n\r\n<p>Write a persuasive essay to a newspaper reflecting your vies on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading.</p>", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/2", "https://api.example.com/api/trained-models/3"], "tags": [], "corpora": ["https://api.example.com/api/corpora/2"], "answer_sets": ["https://api.example.com/api/answer-sets/2"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}, {"url": "https://api.example.com/api/prompts/1", "owner": 2, "parent": null, "title": "ASAP Dataset #1: Persuasive Essay on Computers", "text": "ASAP Dataset #1: Persuasive Essay on Computers", "instructions": "", "description": "More and more people use computers, but not everyone agrees that this benefits society. Those who support advances in technology believe that computers have a positive effect on people. They teach hand-eye coordination, give people the ability to learn about faraway places and people, and even allow people to talk online with other people. Others have different ideas. Some experts are concerned that people are spending too much time on their computers and less time exercising, enjoying nature, and interacting with family and friends. \n\nWrite a letter to your local newspaper in which you state your opinion on the effects computers have on people. Persuade the readers to agree with you.", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/1"], "tags": [], "corpora": ["https://api.example.com/api/corpora/1"], "answer_sets": ["https://api.example.com/api/answer-sets/1"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}]}
@@ -0,0 +1 @@
1
+ {"url": "https://api.example.com/api/prompts/2", "owner": 2, "parent": null, "title": "ASAP Dataset #2: Persuasive Essay on Censorship", "text": "ASAP Dataset #2: Persuasive Essay on Censorship", "instructions": "", "description": "<blockquote>\"All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.\" <footer>&mdash; Katherine Paterson, Author</footer></blockquote>\r\n\r\n<p>Write a persuasive essay to a newspaper reflecting your vies on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading.</p>", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/2", "https://api.example.com/api/trained-models/3"], "tags": [], "corpora": ["https://api.example.com/api/corpora/2"], "answer_sets": ["https://api.example.com/api/answer-sets/2"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}
@@ -0,0 +1 @@
1
+ {"count": 2, "next": "https://api.example.com/api/prompts/?page=2", "previous": null, "results": [{"url": "https://api.example.com/api/prompts/2", "owner": 2, "parent": null, "title": "ASAP Dataset #2: Persuasive Essay on Censorship", "text": "ASAP Dataset #2: Persuasive Essay on Censorship", "instructions": "", "description": "<blockquote>\"All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.\" <footer>&mdash; Katherine Paterson, Author</footer></blockquote>\r\n\r\n<p>Write a persuasive essay to a newspaper reflecting your vies on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading.</p>", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/2", "https://api.example.com/api/trained-models/3"], "tags": [], "corpora": ["https://api.example.com/api/corpora/2"], "answer_sets": ["https://api.example.com/api/answer-sets/2"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}, {"url": "https://api.example.com/api/prompts/1", "owner": 2, "parent": null, "title": "ASAP Dataset #1: Persuasive Essay on Computers", "text": "ASAP Dataset #1: Persuasive Essay on Computers", "instructions": "", "description": "More and more people use computers, but not everyone agrees that this benefits society. Those who support advances in technology believe that computers have a positive effect on people. They teach hand-eye coordination, give people the ability to learn about faraway places and people, and even allow people to talk online with other people. Others have different ideas. Some experts are concerned that people are spending too much time on their computers and less time exercising, enjoying nature, and interacting with family and friends. \n\nWrite a letter to your local newspaper in which you state your opinion on the effects computers have on people. Persuade the readers to agree with you.", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/1"], "tags": [], "corpora": ["https://api.example.com/api/corpora/1"], "answer_sets": ["https://api.example.com/api/answer-sets/1"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}]}
@@ -0,0 +1 @@
1
+ {"count": 2, "next": "https://api.example.com/api/prompts/?page=2", "previous": "https://api.example.com/api/prompts/?page=1", "results": [{"url": "https://api.example.com/api/prompts/2", "owner": 2, "parent": null, "title": "ASAP Dataset #2: Persuasive Essay on Censorship", "text": "ASAP Dataset #2: Persuasive Essay on Censorship", "instructions": "", "description": "<blockquote>\"All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.\" <footer>&mdash; Katherine Paterson, Author</footer></blockquote>\r\n\r\n<p>Write a persuasive essay to a newspaper reflecting your vies on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading.</p>", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/2", "https://api.example.com/api/trained-models/3"], "tags": [], "corpora": ["https://api.example.com/api/corpora/2"], "answer_sets": ["https://api.example.com/api/answer-sets/2"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}, {"url": "https://api.example.com/api/prompts/1", "owner": 2, "parent": null, "title": "ASAP Dataset #1: Persuasive Essay on Computers", "text": "ASAP Dataset #1: Persuasive Essay on Computers", "instructions": "", "description": "More and more people use computers, but not everyone agrees that this benefits society. Those who support advances in technology believe that computers have a positive effect on people. They teach hand-eye coordination, give people the ability to learn about faraway places and people, and even allow people to talk online with other people. Others have different ideas. Some experts are concerned that people are spending too much time on their computers and less time exercising, enjoying nature, and interacting with family and friends. \n\nWrite a letter to your local newspaper in which you state your opinion on the effects computers have on people. Persuade the readers to agree with you.", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/1"], "tags": [], "corpora": ["https://api.example.com/api/corpora/1"], "answer_sets": ["https://api.example.com/api/answer-sets/1"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}]}
@@ -0,0 +1 @@
1
+ {"count": 2, "next": null, "previous": "https://api.example.com/api/prompts/?page=2", "results": [{"url": "https://api.example.com/api/prompts/2", "owner": 2, "parent": null, "title": "ASAP Dataset #2: Persuasive Essay on Censorship", "text": "ASAP Dataset #2: Persuasive Essay on Censorship", "instructions": "", "description": "<blockquote>\"All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.\" <footer>&mdash; Katherine Paterson, Author</footer></blockquote>\r\n\r\n<p>Write a persuasive essay to a newspaper reflecting your vies on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading.</p>", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/2", "https://api.example.com/api/trained-models/3"], "tags": [], "corpora": ["https://api.example.com/api/corpora/2"], "answer_sets": ["https://api.example.com/api/answer-sets/2"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}, {"url": "https://api.example.com/api/prompts/1", "owner": 2, "parent": null, "title": "ASAP Dataset #1: Persuasive Essay on Computers", "text": "ASAP Dataset #1: Persuasive Essay on Computers", "instructions": "", "description": "More and more people use computers, but not everyone agrees that this benefits society. Those who support advances in technology believe that computers have a positive effect on people. They teach hand-eye coordination, give people the ability to learn about faraway places and people, and even allow people to talk online with other people. Others have different ideas. Some experts are concerned that people are spending too much time on their computers and less time exercising, enjoying nature, and interacting with family and friends. \n\nWrite a letter to your local newspaper in which you state your opinion on the effects computers have on people. Persuade the readers to agree with you.", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/1"], "tags": [], "corpora": ["https://api.example.com/api/corpora/1"], "answer_sets": ["https://api.example.com/api/answer-sets/1"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}]}
@@ -0,0 +1 @@
1
+ {"count": 2, "next": "https://api.example.com/api/prompts/?page=2&all=true", "previous": "https://api.example.com/api/prompts/?page=1&all=true", "results": [{"url": "https://api.example.com/api/prompts/2", "owner": 2, "parent": null, "title": "ASAP Dataset #2: Persuasive Essay on Censorship", "text": "ASAP Dataset #2: Persuasive Essay on Censorship", "instructions": "", "description": "<blockquote>\"All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.\" <footer>&mdash; Katherine Paterson, Author</footer></blockquote>\r\n\r\n<p>Write a persuasive essay to a newspaper reflecting your vies on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading.</p>", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/2", "https://api.example.com/api/trained-models/3"], "tags": [], "corpora": ["https://api.example.com/api/corpora/2"], "answer_sets": ["https://api.example.com/api/answer-sets/2"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}, {"url": "https://api.example.com/api/prompts/1", "owner": 2, "parent": null, "title": "ASAP Dataset #1: Persuasive Essay on Computers", "text": "ASAP Dataset #1: Persuasive Essay on Computers", "instructions": "", "description": "More and more people use computers, but not everyone agrees that this benefits society. Those who support advances in technology believe that computers have a positive effect on people. They teach hand-eye coordination, give people the ability to learn about faraway places and people, and even allow people to talk online with other people. Others have different ideas. Some experts are concerned that people are spending too much time on their computers and less time exercising, enjoying nature, and interacting with family and friends. \n\nWrite a letter to your local newspaper in which you state your opinion on the effects computers have on people. Persuade the readers to agree with you.", "lower": null, "upper": null, "alignments": "", "default_models": ["https://api.example.com/api/trained-models/1"], "tags": [], "corpora": ["https://api.example.com/api/corpora/1"], "answer_sets": ["https://api.example.com/api/answer-sets/1"], "active": true, "created": "2013-10-03T00:00:00", "modified": "2013-10-03T00:00:00"}]}
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe LightSide::Pager do
4
+ let(:auth_token) { "abc123" }
5
+ let(:base_url) { "https://api.example.com/api" }
6
+ let(:headers) { {
7
+ "Accept" => "*/*; q=0.5, application/xml",
8
+ "Accept-Encoding" => "gzip, deflate",
9
+ "Authorization" => "Token #{auth_token}",
10
+ "Content-Type" => "application/json",
11
+ "User-Agent" => "Ruby"
12
+ } }
13
+
14
+ before do
15
+ LightSide.configure do |config|
16
+ config.auth_token = auth_token
17
+ config.base_url = base_url
18
+ end
19
+ end
20
+
21
+ context "when url is not supplied" do
22
+ let(:page_url) { "https://api.example.com/api/prompts/?page=1" }
23
+ let(:pager) { LightSide::Pager.new(LightSide::Prompt) }
24
+
25
+ it "starts at page 1" do
26
+ expect(pager.page_number).to eq 1
27
+ expect(pager.resource_path).to eq page_url
28
+ end
29
+ end
30
+
31
+ context "when retrieving by page number" do
32
+ let(:path) { "https://api.example.com/api/prompts/" }
33
+ let(:pager) { LightSide::Pager.new(LightSide::Prompt, params) }
34
+
35
+ context "without query params" do
36
+ let(:params) { {page: 2} }
37
+ let(:response_body) { File.new("spec/fixtures/prompts_2.json") }
38
+
39
+ before do
40
+ stub_request(:get, "#{base_url}/prompts/?page=2").with(:headers => headers).
41
+ to_return(:status => 200, :body => response_body, :headers => {})
42
+ end
43
+
44
+ it "starts at page 2" do
45
+ expect(pager.page_number).to eq 2
46
+ end
47
+
48
+ it "sets the next url" do
49
+ pager.fetch
50
+ expect(pager.next_url).to eq "#{base_url}/prompts/?page=2"
51
+ expect(pager.collection.map(&:class)).to eq [LightSide::Prompt]*2
52
+ end
53
+ end
54
+
55
+ context "with query params" do
56
+ let(:params) { {page: 2, all: true} }
57
+ let(:response_body) { File.new("spec/fixtures/prompts_4.json") }
58
+
59
+ before do
60
+ stub_request(:get, "#{base_url}/prompts/?page=2&all=true").with(:headers => headers).
61
+ to_return(:status => 200, :body => response_body, :headers => {})
62
+ end
63
+
64
+ it "starts at page 2" do
65
+ expect(pager.page_number).to eq 2
66
+ end
67
+
68
+ it "sets the next url" do
69
+ pager.fetch
70
+ expect(pager.next_url).to eq "#{base_url}/prompts/?page=2&all=true"
71
+ expect(pager.collection.map(&:class)).to eq [LightSide::Prompt]*2
72
+ end
73
+ end
74
+
75
+ context "#next" do
76
+ let(:params) { {page: 2} }
77
+ let(:response_body) { File.new("spec/fixtures/prompts_2.json") }
78
+
79
+ context "when next_url is missing" do
80
+ it "raises an exception" do
81
+ expect(pager.page_number).to eq 2
82
+ expect(pager.next_url).to be_nil
83
+ expect { pager.next }.to raise_error("no more results")
84
+ end
85
+ end
86
+
87
+ context "when next_url is present" do
88
+ let(:response_body_2) { File.new("spec/fixtures/prompts_3.json") }
89
+ let(:page_3_url) { "#{base_url}/prompts/?page=3" }
90
+
91
+ before do
92
+ stub_request(:get, "#{base_url}/prompts/?page=3").with(:headers => headers).
93
+ to_return(:status => 200, :body => response_body_2, :headers => {})
94
+ end
95
+
96
+ it "fetches the next set of results" do
97
+ pager.next_url = page_3_url
98
+ pager.next
99
+ expect(pager.collection).not_to be_empty
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,228 @@
1
+ require 'spec_helper'
2
+
3
+ describe LightSide::Resources do
4
+ let(:auth_token) { "abc123" }
5
+ let(:base_url) { "https://api.example.com/api" }
6
+ let(:prompts) { LightSide::Prompt.all }
7
+ let(:prompt) { prompts.first }
8
+ let(:headers) { {
9
+ "Accept" => "*/*; q=0.5, application/xml",
10
+ "Accept-Encoding" => "gzip, deflate",
11
+ "Authorization" => "Token #{auth_token}",
12
+ "Content-Type" => "application/json",
13
+ "User-Agent" => "Ruby"
14
+ } }
15
+
16
+ before do
17
+ LightSide.configure do |config|
18
+ config.auth_token = auth_token
19
+ config.base_url = base_url
20
+ end
21
+ end
22
+
23
+ context ".all" do
24
+ let(:response_body) { File.new("spec/fixtures/prompts.json") }
25
+
26
+ before do
27
+ stub_request(:get, "#{base_url}/prompts/?page=1").with(:headers => headers).
28
+ to_return(:status => 200, :body => response_body, :headers => {})
29
+ end
30
+
31
+ it "gets the first page of prompts" do
32
+ expect(prompts).to be_kind_of(LightSide::Pager)
33
+ expect(prompts.count).to eq 2
34
+ expect(prompt).to be_kind_of(LightSide::Prompt)
35
+ expect(prompt.url).to eq "https://api.example.com/api/prompts/2"
36
+ end
37
+ end
38
+
39
+ context ".page" do
40
+ let(:response_body) { File.new("spec/fixtures/prompts.json") }
41
+
42
+ before do
43
+ stub_request(:get, "#{base_url}/prompts/?page=2").with(:headers => headers).
44
+ to_return(:status => 200, :body => response_body, :headers => {})
45
+ end
46
+
47
+ context "when requesting without a page number" do
48
+ let(:prompts) { LightSide::Prompt.page }
49
+ it "raises an exception" do
50
+ expect { prompts }.to raise_error
51
+ end
52
+ end
53
+
54
+ context "when requesting with page number nil" do
55
+ let(:prompts) { LightSide::Prompt.page(nil) }
56
+ it "raises an exception" do
57
+ expect { prompts }.to raise_error
58
+ end
59
+ end
60
+
61
+ context "when requesting with page number 2" do
62
+ let(:prompts) { LightSide::Prompt.page(2) }
63
+ it "returns the second page of results" do
64
+ expect(prompts.collection.map(&:class)).to eq [LightSide::Prompt]*2
65
+ end
66
+ end
67
+ end
68
+
69
+ context ".find" do
70
+ context "with a valid ID" do
71
+ let(:response_body) { File.new("spec/fixtures/prompts/2.json") }
72
+ let(:prompt) { LightSide::Prompt.find(2) }
73
+
74
+ before do
75
+ stub_request(:get, "#{base_url}/prompts/2").
76
+ with(:headers => headers).
77
+ to_return(:status => 200, :body => response_body, :headers => {})
78
+ end
79
+
80
+ it "finds a prompt by its id" do
81
+ expect(prompt).to be_kind_of(LightSide::Prompt)
82
+ expect(prompt.url).to eq "https://api.example.com/api/prompts/2"
83
+ end
84
+ end
85
+
86
+ context "with an invalid ID" do
87
+ let(:prompt) { LightSide::Prompt.find(99) }
88
+
89
+ before do
90
+ stub_request(:get, "#{base_url}/prompts/99").with(:headers => headers).
91
+ to_return(:status => 404, :body => "", :headers => {})
92
+ end
93
+
94
+ it "raises an exception" do
95
+ expect { prompt }.to raise_error(LightSide::ResourceNotFound)
96
+ end
97
+ end
98
+ end
99
+
100
+ context ".create" do
101
+ context "with valid input" do
102
+ let(:response_body) { File.new("spec/fixtures/prompts/2.json") }
103
+ let(:data) { JSON.generate({
104
+ "title" => "new prompt title",
105
+ "text" => "This is the text of the prompt.",
106
+ "description" => "This prompt is an example.",
107
+ "lower" => nil,
108
+ "upper" => nil,
109
+ "default_models" => [],
110
+ "tags" => ["example", "period 2"]
111
+ }) }
112
+
113
+ before do
114
+ headers.merge!('Content-Length' => data.length)
115
+ stub_request(:post, "#{base_url}/prompts/").with(:headers => headers).
116
+ to_return(:status => 201, :body => response_body, :headers => {})
117
+ end
118
+
119
+ it "creates a prompt" do
120
+ prompt = LightSide::Prompt.create(data)
121
+ expect(prompt.url).to eq "https://api.example.com/api/prompts/2"
122
+ end
123
+ end
124
+
125
+ context "with invalid input" do
126
+ let(:error_hash) { {"text"=>["This field is required."], "title"=>["This field is required."]} }
127
+ let(:response_body) { JSON.generate(error_hash) }
128
+ let(:data) { JSON.generate({}) }
129
+
130
+ before do
131
+ headers.merge!('Content-Length' => data.length)
132
+ stub_request(:post, "#{base_url}/prompts/").with(:headers => headers).
133
+ to_return(:status => 400, :body => response_body, :headers => {})
134
+ end
135
+
136
+ it "returns an unsaved prompt and populates its error hash" do
137
+ prompt = LightSide::Prompt.create(data)
138
+ expect(prompt.errors).to eq error_hash
139
+ end
140
+ end
141
+ end
142
+
143
+ context ".update" do
144
+ context "with valid ID and input" do
145
+ let(:response_body) { File.new("spec/fixtures/prompts/2.json") }
146
+ let(:data) { JSON.generate({
147
+ "title" => "new prompt title",
148
+ "text" => "This is the text of the prompt.",
149
+ "description" => "This prompt is an example.",
150
+ "lower" => nil,
151
+ "upper" => nil,
152
+ "default_models" => [],
153
+ "tags" => ["example", "period 2"]
154
+ }) }
155
+
156
+ before do
157
+ headers.merge!('Content-Length' => data.length)
158
+ stub_request(:put, "#{base_url}/prompts/2").with(:headers => headers).
159
+ with(:body => data).
160
+ to_return(:status => 200, :body => response_body, :headers => {})
161
+ end
162
+
163
+ it "updates the prompt" do
164
+ prompt = LightSide::Prompt.update(2, data)
165
+ expect(prompt.url).to eq "https://api.example.com/api/prompts/2"
166
+ end
167
+ end
168
+
169
+ context "with valid ID and invalid input" do
170
+ let(:error_hash) { {"text"=>["This field is required."], "title"=>["This field is required."]} }
171
+ let(:response_body) { JSON.generate(error_hash) }
172
+ let(:data) { JSON.generate({}) }
173
+
174
+ before do
175
+ headers.merge!('Content-Length' => data.length)
176
+ stub_request(:put, "#{base_url}/prompts/2").with(:headers => headers).
177
+ with(:body => data).
178
+ to_return(:status => 400, :body => response_body, :headers => {})
179
+ end
180
+
181
+ it "return the prompt without updating and populates its error hash" do
182
+ prompt = LightSide::Prompt.update(2, data)
183
+ expect(prompt.errors).to eq error_hash
184
+ end
185
+ end
186
+
187
+ context "with invalid ID" do
188
+ let(:data) { JSON.generate({}) }
189
+ let(:prompt) { LightSide::Prompt.update(99, data) }
190
+
191
+ before do
192
+ headers.merge!('Content-Length' => data.length)
193
+ stub_request(:put, "#{base_url}/prompts/99").with(:headers => headers).
194
+ with(:body => data).
195
+ to_return(:status => 404, :body => "", :headers => {})
196
+ end
197
+
198
+ it "raises an exception" do
199
+ expect { prompt }.to raise_error(LightSide::ResourceNotFound)
200
+ end
201
+ end
202
+ end
203
+
204
+ context ".delete" do
205
+ context "with valid ID" do
206
+ before do
207
+ stub_request(:delete, "#{base_url}/prompts/2").with(:headers => headers).
208
+ to_return(:status => 204, :body => "", :headers => {})
209
+ end
210
+
211
+ it "returns true" do
212
+ expect(LightSide::Prompt.delete(2)).to eq true
213
+ end
214
+ end
215
+
216
+ context "with invalid ID" do
217
+ before do
218
+ stub_request(:delete, "#{base_url}/prompts/99").with(:headers => headers).
219
+ to_return(:status => 404, :body => "", :headers => {})
220
+ end
221
+
222
+ it "raises an exception" do
223
+ expect { LightSide::Prompt.delete(99) }.to raise_error(LightSide::ResourceNotFound)
224
+ end
225
+ end
226
+ end
227
+
228
+ end
@@ -0,0 +1,22 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
18
+
19
+ require 'webmock/rspec'
20
+ WebMock.disable_net_connect!
21
+
22
+ require 'lightside'
metadata ADDED
@@ -0,0 +1,206 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lightside
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tom Head
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-12-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: webmock
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: pry-nav
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: guard
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: guard-rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: Ruby wrapper for LightSide Web API
127
+ email: tom.head@revolutionprep.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .gitignore
133
+ - .rspec
134
+ - Gemfile
135
+ - Guardfile
136
+ - README.md
137
+ - lib/lightside.rb
138
+ - lib/lightside/config.rb
139
+ - lib/lightside/exceptions.rb
140
+ - lib/lightside/models/answer.rb
141
+ - lib/lightside/models/answer_set.rb
142
+ - lib/lightside/models/assignment_icon.rb
143
+ - lib/lightside/models/assignment_tile_color.rb
144
+ - lib/lightside/models/author.rb
145
+ - lib/lightside/models/corpus.rb
146
+ - lib/lightside/models/human_score.rb
147
+ - lib/lightside/models/prediction_result.rb
148
+ - lib/lightside/models/prediction_task.rb
149
+ - lib/lightside/models/prompt.rb
150
+ - lib/lightside/models/resolved_score.rb
151
+ - lib/lightside/models/tag_answer_set.rb
152
+ - lib/lightside/models/tag_prompt.rb
153
+ - lib/lightside/models/trained_model.rb
154
+ - lib/lightside/models/trained_model_evaluation.rb
155
+ - lib/lightside/models/training_answer.rb
156
+ - lib/lightside/models/training_task.rb
157
+ - lib/lightside/pager.rb
158
+ - lib/lightside/resources.rb
159
+ - lib/lightside/version.rb
160
+ - lightside.gemspec
161
+ - spec/config_spec.rb
162
+ - spec/fixtures/prompts.json
163
+ - spec/fixtures/prompts/2.json
164
+ - spec/fixtures/prompts_1.json
165
+ - spec/fixtures/prompts_2.json
166
+ - spec/fixtures/prompts_3.json
167
+ - spec/fixtures/prompts_4.json
168
+ - spec/pager_spec.rb
169
+ - spec/resources_spec.rb
170
+ - spec/spec_helper.rb
171
+ homepage: ''
172
+ licenses:
173
+ - MIT
174
+ post_install_message:
175
+ rdoc_options: []
176
+ require_paths:
177
+ - lib
178
+ required_ruby_version: !ruby/object:Gem::Requirement
179
+ none: false
180
+ requirements:
181
+ - - ! '>='
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ requirements: []
191
+ rubyforge_project:
192
+ rubygems_version: 1.8.25
193
+ signing_key:
194
+ specification_version: 3
195
+ summary: LightSide API
196
+ test_files:
197
+ - spec/config_spec.rb
198
+ - spec/fixtures/prompts.json
199
+ - spec/fixtures/prompts/2.json
200
+ - spec/fixtures/prompts_1.json
201
+ - spec/fixtures/prompts_2.json
202
+ - spec/fixtures/prompts_3.json
203
+ - spec/fixtures/prompts_4.json
204
+ - spec/pager_spec.rb
205
+ - spec/resources_spec.rb
206
+ - spec/spec_helper.rb