clever-ruby 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MTI0OGY0NTY3MDg0ODc1NGE0OTJlNmE1NGQxMjVmZGJlNGFjMzFlMA==
4
+ OWYwYWY4NjMwMjdjYTY4MmIzNjE3ZDQ5NjkwMTNlYTQ5MTU5ZWQ2Mg==
5
5
  data.tar.gz: !binary |-
6
- ZTJjNGFhNTlkZTMxYWM0NjMxNjVjOGZmNmI1NjUyMTg4ZjIwZWI0YQ==
6
+ ZTVmYWMwZjFmZTRhZTQ2ZTc1ZGEwMDhmOGJmNTY2OTg3NThmYTFlZg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NGNiNGM5OGM3ZjYwNjYyZGIyMmZlM2VjZmFmNWQxNjdhMjBmY2M1ZDBlMDY0
10
- NWZhZTM4MTE3MmIyOTkxNTQ0ODdhODAxODVhNGI0N2U1OGY3NjdhMWM1Njc3
11
- ZTlmZTY0NjQxZjUyNTliNGRiZjI1MTIzZDllYzRiNDU2MjVjOWM=
9
+ ZTE1ZTAyNGY5ZWJmMThlZWZmNzY5NjQxYTdmNzVmOGM4MTA4MThjMmRiY2E2
10
+ MjRhZDZiOWUxYzRjNDY5ZjYzZWEyMmM1ZjdjYjFiMjMzNWE1YWYyODQ4N2Q2
11
+ ZjVkMDk2YjlmZTk1ZjJhOGM1YTMyYTIyMDlkZjlmNmEyYmU3M2I=
12
12
  data.tar.gz: !binary |-
13
- NGZjMjNkYjgxNGQxYWE0NWY2MGZkNjgzNzZmMThlZDIyZGI5MTk3OTcwMzI2
14
- OTJlZGMwZjQwZjI1NDMyNjVjZGZjN2E3ZTVhMDMyNzg3OWVjOGM1NGViNTBk
15
- MzdkNWE3ODhkZGExZGVlNzk4NWMyZGYwMDQwOGE5NjlkMDUyOTY=
13
+ NmRkYmU3M2FjNDIzNmUyNzg1NzVhMTU5MTA4YTUxNTk0Y2U3YTlhNjliZGJj
14
+ OTdiNDVmMTM1N2RhNjI2MmE3ZGVkNjU0ZTNhOGE4OGViMTJhYWZmYTFkZGZk
15
+ NTYxMDFiY2M3M2Q0NTYwNGZiMzdmZmFkZDM0OGE2ZmVmNDhmODg=
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ doc_coverage.txt
6
7
  .rvmrc
7
8
  .ruby-version
8
9
  .ruby-gemset
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup markdown
2
+ --title clever-ruby
data/CHANGELOG.md CHANGED
@@ -1,4 +1,9 @@
1
- ## 0.6.0 (2014-09-09)
1
+ ## 0.6.1 (2014-09-10)
2
+
3
+ * Add YARD documentation
4
+ * Remove unused Clever::Student.photo method
5
+
6
+ ## 0.6.0 (2014-09-10)
2
7
 
3
8
  * Add ActiveRecord-style find and count methods to all APIResources (#37)
4
9
 
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Build Status](https://drone.ops.clever.com/github.com/Clever/clever-ruby/status.svg?branch=master)](https://drone.ops.clever.com/github.com/Clever/clever-ruby)
4
4
 
5
- Ruby bindings to the Clever API.
5
+ Ruby bindings to the Clever API. [Documentation](http://rubydoc.info/gems/clever-ruby/frames)
6
6
 
7
7
  ## Installation
8
8
 
@@ -24,6 +24,19 @@ Or install it yourself as:
24
24
  $ gem install clever-ruby
25
25
  ```
26
26
 
27
+ ## Usage
28
+
29
+ Configure clever-ruby to use your Clever token:
30
+
31
+ ```ruby
32
+ Clever.configure do |config|
33
+ config.token = 'YOUR-API-TOKEN'
34
+ end
35
+ ```
36
+
37
+ See the [documentation](http://rubydoc.info/gems/clever-ruby/frames) for
38
+ further details.
39
+
27
40
  ## Run tests
28
41
 
29
42
  To run all tests:
@@ -46,16 +59,22 @@ $ rake lint
46
59
 
47
60
  Running specific tests is not currently supported.
48
61
 
49
- ## Usage
62
+ ## Documentation
50
63
 
51
- Configure clever-ruby to use your Clever API key:
64
+ To generate it to `./doc`:
52
65
 
53
- ```ruby
54
- Clever.configure do |config|
55
- config.api_key = 'YOUR-API-KEY'
56
- end
66
+ ```bash
67
+ $ rake doc
57
68
  ```
58
69
 
70
+ To see documentation coverage:
71
+
72
+ ```bash
73
+ $ rake doc-coverage
74
+ ```
75
+
76
+ and then view `doc_coverage.txt`.
77
+
59
78
  ## Contributing
60
79
 
61
80
  1. Fork it
data/Rakefile CHANGED
@@ -9,13 +9,18 @@ Rake::TestTask.new(:test) do |test|
9
9
  test.verbose = true
10
10
  end
11
11
 
12
- require 'rdoc/task'
12
+ require 'yard'
13
13
  require 'clever-ruby/version'
14
- Rake::RDocTask.new do |rdoc|
15
- rdoc.rdoc_dir = 'rdoc'
16
- rdoc.title = "clever-ruby #{Clever::VERSION}"
17
- rdoc.rdoc_files.include('README*')
18
- rdoc.rdoc_files.include('lib/**/*.rb')
14
+ YARD::Rake::YardocTask.new :doc
15
+
16
+ require 'yardstick/rake/measurement'
17
+ Yardstick::Rake::Measurement.new(:'doc-coverage') do |measurement|
18
+ measurement.output = 'doc_coverage.txt'
19
+ end
20
+
21
+ require 'yardstick/rake/verify'
22
+ Yardstick::Rake::Verify.new(:'doc-coverage-verify') do |verify|
23
+ verify.threshold = 100
19
24
  end
20
25
 
21
26
  require 'rubocop/rake_task'
@@ -28,4 +33,6 @@ end
28
33
  task default: [] do
29
34
  Rake::Task[:test].execute
30
35
  Rake::Task[:lint].execute
36
+ Rake::Task[:'doc-coverage'].execute
37
+ Rake::Task[:'doc-coverage-verify'].execute
31
38
  end
data/clever-ruby.gemspec CHANGED
@@ -25,7 +25,9 @@ Gem::Specification.new do |gem|
25
25
  gem.add_development_dependency 'rake'
26
26
  gem.add_development_dependency 'minitest', '~> 4.4.0'
27
27
  gem.add_development_dependency 'shoulda', '~> 3.3.2'
28
- gem.add_development_dependency 'rdoc', '~> 3.12'
28
+ gem.add_development_dependency 'yard', '~> 0.8.7'
29
+ gem.add_development_dependency 'yardstick', '~> 0.9.9'
30
+ gem.add_development_dependency 'redcarpet', '~> 3.1.2'
29
31
  gem.add_development_dependency 'vcr', '~> 2.4.0'
30
32
  gem.add_development_dependency 'webmock', '~> 1.9.0'
31
33
  gem.add_development_dependency 'pry', '~> 0.10.1'
@@ -3,7 +3,16 @@ module Clever
3
3
  # A list of API resource instances
4
4
  module List
5
5
  # Class methods for those that include List
6
+ # @api public
6
7
  module ClassMethods
8
+ # Get all elements of a resource
9
+ # @api public
10
+ # @deprecated This can be costly since it places all matching elements
11
+ # in memory. Instead just iterate over the collection using each.
12
+ # @param filters [Hash] parameters to apply, as per the Clever API spec
13
+ # @return [Array] array of all elements matching the request
14
+ # @example
15
+ # Clever::District.all
7
16
  def all(filters = {})
8
17
  accum = []
9
18
  Clever::APIOperations::PageList.new(url, filters).each do |page|
@@ -12,6 +21,25 @@ module Clever
12
21
  accum
13
22
  end
14
23
 
24
+ # Get elements of a resource. Supports 1 or more ids, or open-ended query
25
+ # @api public
26
+ # @param id [String, Array, nil] ID or array of ids to match, or nil
27
+ # for query
28
+ # @param filters [Hash, nil] Query parameters to pass, as per Clever API spec
29
+ # @return [Clever::APIResource, Clever::APIOperations::ResultsList]
30
+ # single resource or iterable list of results
31
+ # @raise [ArgumentError] Bad ID/IDs provided
32
+ # @example
33
+ # # Get first 20 clever districts
34
+ # districts = Clever::District.find.take 20
35
+ #
36
+ # # Get specific district
37
+ # id = '...'
38
+ # district = Clever::District.find id
39
+ #
40
+ # # Get districts with given ids
41
+ # ids = ['...', '...']
42
+ # districts = Clever::District.find ids
15
43
  def find(id = nil, filters = {})
16
44
  if id.is_a? Array
17
45
  unless id.select { |e| !Clever::Util.valid_id? e }.empty?
@@ -30,6 +58,12 @@ module Clever
30
58
  end
31
59
  end
32
60
 
61
+ # Requests number of elements matching the query
62
+ # @api public
63
+ # @param filters [Hash, nil] Query parameters to pass, as per Clever API spec
64
+ # @return [Integer] Number of elements matching
65
+ # @example
66
+ # num_districts = Clever::District.count
33
67
  def count(filters = {})
34
68
  filters[:count] = true
35
69
  response = Clever.request :get, url, filters
@@ -37,6 +71,9 @@ module Clever
37
71
  end
38
72
  end
39
73
 
74
+ # Add ClassMethods to classes that include List
75
+ # @api private
76
+ # @return [nil]
40
77
  def self.included(base)
41
78
  base.extend ClassMethods
42
79
  end
@@ -4,6 +4,11 @@ module Clever
4
4
  class Page
5
5
  include Enumerable
6
6
 
7
+ # Request a page of data and store the results in this instance
8
+ # @api private
9
+ # @return [Clever::APIOperations::Page]
10
+ # @example
11
+ # page = Page.new '/v1.1/districts'
7
12
  def initialize(uri, filters = {})
8
13
  @uri = uri
9
14
  @filters = filters
@@ -16,16 +21,31 @@ module Clever
16
21
  end
17
22
  end
18
23
 
19
- # Gets next page if one is present, nil otherwise.
24
+ # Gets next page if one is present, nil otherwise
25
+ # @api private
26
+ # @return [Clever::APIOperations::Page, nil] Next page, or nil if last
27
+ # @example
28
+ # next_page = page.next
29
+ # unless next_page.nil?
30
+ # next_page.each do |elem| puts elem; end
20
31
  def next
21
32
  @links.key?(:next) ? Page.new(@links[:next]) : nil
22
33
  end
23
34
 
35
+ # Iterate over all elements in the page
36
+ # @api private
37
+ # @return [Array] List of all elements
38
+ # @example
39
+ # page.each { |elem| puts elem }
24
40
  def each(&blk)
25
41
  @list.each(&blk)
26
42
  end
27
43
 
28
- # TODO: remove this
44
+ # Get all elements in page
45
+ # @api private
46
+ # @return [Array] List of all elements
47
+ # @example
48
+ # all_elems = page.all
29
49
  def all
30
50
  accum = []
31
51
  each do |elem|
@@ -4,11 +4,23 @@ module Clever
4
4
  class PageList
5
5
  include Enumerable
6
6
 
7
+ # Create a new PageList, without making any requests immediately
8
+ # @api private
9
+ # @return [PageList]
7
10
  def initialize(uri, filters = {})
8
11
  @uri = uri
9
12
  @filters = filters
10
13
  end
11
14
 
15
+ # Iterate through each page, making requests as you iterate
16
+ # @api private
17
+ # @return [nil]
18
+ # @example
19
+ # pagelist.each do |page|
20
+ # page.each do |elem|
21
+ # puts elem
22
+ # end
23
+ # end
12
24
  def each
13
25
  page = Page.new @uri, @filters
14
26
  until page.nil?
@@ -17,6 +29,11 @@ module Clever
17
29
  end
18
30
  end
19
31
 
32
+ # Convert PageList into a ResultsList for easier iteration
33
+ # @api private
34
+ # @return [Clever::APIOperations::ResultsList]
35
+ # @example
36
+ # pagelist.to_results_list.each { |elem| puts elem }
20
37
  def to_results_list
21
38
  Clever::APIOperations::ResultsList.new self
22
39
  end
@@ -4,10 +4,21 @@ module Clever
4
4
  class ResultsList
5
5
  include Enumerable
6
6
 
7
+ # Create a results list from a PageList
8
+ # @api private
9
+ # @return [ResultsList]
7
10
  def initialize(pagelist)
8
11
  @pages = pagelist
9
12
  end
10
13
 
14
+ # Iterate over results list
15
+ # @api public
16
+ # @return [nil]
17
+ # @example
18
+ # results = Clever::District.find # returns a ResultsList
19
+ # results.each do |district|
20
+ # puts district.name
21
+ # end
11
22
  def each
12
23
  @pages.each do |page|
13
24
  page.each do |elem|
@@ -1,6 +1,9 @@
1
1
  module Clever
2
2
  # Superclass of API resources in the Clever API
3
3
  class APIResource < CleverObject
4
+ # Get URL for a resource
5
+ # @api private
6
+ # @return [String] url to query for a resource
4
7
  def self.url
5
8
  if self == APIResource
6
9
  fail NotImplementedError, 'APIResource is an abstract class. You should perform actions '\
@@ -10,6 +13,9 @@ module Clever
10
13
  "v1.1/#{CGI.escape shortname.downcase}s"
11
14
  end
12
15
 
16
+ # Get URL for an instance of a resource
17
+ # @api private
18
+ # @return [String] url to query for an instance of a resource
13
19
  def url
14
20
  id = self['id']
15
21
  unless id
@@ -20,28 +26,56 @@ module Clever
20
26
  "#{self.class.url}/#{CGI.escape id}"
21
27
  end
22
28
 
29
+ # Request the current resource data and update this object
30
+ # @api private
31
+ # @return [APIResource] The updated resource instance
23
32
  def refresh
24
33
  response = Clever.request :get, url
25
34
  refresh_from response[:data]
26
35
  self
27
36
  end
28
37
 
38
+ # Get hypermedia links for this resource instance
39
+ # @api private
40
+ # @return [Array] list of links for this resource instance
29
41
  def links
30
42
  response = Clever.request :get, url
31
43
  response[:links]
32
44
  end
33
45
 
46
+ # Get an instance of a resource
47
+ # @api public
48
+ # @param id [String] ID of the instance to find
49
+ # @return [APIResource] resource instance
50
+ # @example
51
+ # id = '...'
52
+ # district = Clever::District.retrieve id
34
53
  def self.retrieve(id)
35
54
  instance = new id
36
55
  instance.refresh
37
56
  instance
38
57
  end
39
58
 
59
+ # Request resource instances by following hypermedia links
60
+ # @api private
61
+ # @return [Array] List of resources found
40
62
  def get_linked_resources(resource_type, filters = {})
41
63
  Util.convert_to_clever_object Clever.request(:get, get_uri(resource_type), filters)[:data]
42
64
  end
43
65
 
44
- class << self; attr_reader :linked_resources; end
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
71
+ end
72
+
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'
45
79
  def initialize(id)
46
80
  super id
47
81
 
@@ -10,27 +10,48 @@ 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
14
+ # @api private
15
+ # @return [CleverObject]
13
16
  def initialize(id = nil)
14
17
  @values = {}
15
18
  @values[:id] = id if id
16
19
  end
17
20
 
21
+ # Construct a CleverObject from the values it should contain. Requires :id
22
+ # @api private
23
+ # @return [CleverObject]
18
24
  def self.construct_from(values)
19
25
  obj = new values[:id]
20
26
  obj.refresh_from values
21
27
  obj
22
28
  end
23
29
 
30
+ # Convert to a pretty-printed JSON string
31
+ # @api public
32
+ # @return [String] JSON representation of the CleverObject
33
+ # @example
34
+ # puts obj.to_s
24
35
  def to_s
25
36
  Clever::JSON.dump @values, pretty: true
26
37
  end
27
38
 
39
+ # Convert this object to a detailed human-readable string
40
+ # @api public
41
+ # @return [String] Detailed representation of the CleverObject
42
+ # @example
43
+ # puts obj.inspect
28
44
  def inspect
29
45
  id_string = (respond_to?(:id) && !id.nil?) ? " id=#{id}" : ''
30
46
  "#<#{self.class}:0x#{object_id.to_s(16)}#{id_string}> JSON: " +
31
47
  Clever::JSON.dump(@values, pretty: true)
32
48
  end
33
49
 
50
+ # Populate this object with the values passed in
51
+ # @api private
52
+ # @param values [Hash] values to set
53
+ # @param partial [Boolean] whether to replace existing keys or start fresh
54
+ # @return [CleverObject]
34
55
  def refresh_from(values, partial = false)
35
56
  removed = partial ? Set.new : Set.new(@values.keys - values.keys)
36
57
  added = Set.new(values.keys - @values.keys)
@@ -50,49 +71,114 @@ module Clever
50
71
  end
51
72
  end
52
73
 
74
+ # Access a value by key
75
+ # @api public
76
+ # @param k [String, Symbol] Key to access
77
+ # @return [Object] Value at that key
78
+ # @example
79
+ # district = Clever::District.retrieve id
80
+ # puts district[:name]
53
81
  def [](k)
54
82
  k = k.to_sym if k.is_a? String
55
83
  @values[k]
56
84
  end
57
85
 
86
+ # Set an attribute
87
+ # @api public
88
+ # @param k [String, Symbol] Key to set
89
+ # @param v [Object] Value to set
90
+ # @return [Object]
91
+ # @example
92
+ # district = Clever::District.retrieve id
93
+ # district[:name] = "New district name"
58
94
  def []=(k, v)
59
95
  send :"#{k}=", v
60
96
  end
61
97
 
98
+ # Get list of keys in object
99
+ # @api public
100
+ # @return [Array] list of keys
101
+ # @example
102
+ # district = Clever::District.retrieve id
103
+ # puts district.keys
62
104
  def keys
63
105
  @values.keys
64
106
  end
65
107
 
108
+ # Get list of values in object
109
+ # @api public
110
+ # @return [Array] list of values
111
+ # @example
112
+ # district = Clever::District.retrieve id
113
+ # puts district.values
66
114
  def values
67
115
  @values.values
68
116
  end
69
117
 
118
+ # Convert to a JSON string
119
+ # @api public
120
+ # @return [String] JSON representation of the CleverObject
121
+ # @example
122
+ # district = Clever::District.retrieve id
123
+ # puts district.to_json
70
124
  def to_json
71
125
  Clever::JSON.dump @values
72
126
  end
73
127
 
128
+ # Unsure
129
+ # @todo Figure out what this is intended for and how it should behave
130
+ # @api private
131
+ # @return [Object]
74
132
  def as_json(*a)
75
133
  @values.as_json(*a)
76
134
  end
77
135
 
136
+ # Convert to a Hash
137
+ # @api public
138
+ # @return [Hash] Hash representation of the CleverObject
139
+ # @example
140
+ # district = Clever::District.retrieve id
141
+ # data = district.to_hash
78
142
  def to_hash
79
143
  @values
80
144
  end
81
145
 
146
+ # Iterate over key-value pairs in the Object
147
+ # @api public
148
+ # @return [Hash] Values in the object
149
+ # @example
150
+ # district = Clever::District.retrieve id
151
+ # district.each do |k, v|
152
+ # puts "#{k}: #{v}"
153
+ # end
82
154
  def each(&blk)
83
155
  @values.each(&blk)
84
156
  end
85
157
 
158
+ # Compare two CleverObjects by values
159
+ # @api public
160
+ # @param other [CleverObject] Object to compare
161
+ # @return [Boolean] equality
162
+ # @example
163
+ # districtOne = Clever::District.retrieve id
164
+ # districtTwo = Clever::District.retrieve id
165
+ # districtOne == districtTwo #=> true
86
166
  def ==(other)
87
167
  values == other.values if other.respond_to? :values
88
168
  end
89
169
 
90
170
  protected
91
171
 
172
+ # Fetch CleverObject's metaclass
173
+ # @api private
174
+ # @return [Object]
92
175
  def metaclass
93
176
  class << self; self; end
94
177
  end
95
178
 
179
+ # Remove accessors
180
+ # @api private
181
+ # @return [Object]
96
182
  def remove_accessors(keys)
97
183
  metaclass.instance_eval do
98
184
  keys.each do |k|
@@ -104,6 +190,9 @@ module Clever
104
190
  end
105
191
  end
106
192
 
193
+ # Add accessors
194
+ # @api private
195
+ # @return [Object]
107
196
  def add_accessors(keys)
108
197
  metaclass.instance_eval do
109
198
  keys.each do |k|
@@ -115,12 +204,21 @@ module Clever
115
204
  end
116
205
  end
117
206
 
207
+ # Defines attributes that the CleverObject can optionally have
208
+ # @api private
209
+ # @return [Array] List of optional attributes
118
210
  def optional_attributes
119
211
  fail NotImplementedError 'Please define #optional_attributes as a list of the '\
120
212
  'attributes on this resource that may not be present and thus should return nil' \
121
213
  'instead of raising a NoMethodError.'
122
214
  end
123
215
 
216
+ # Automatically adds methods for accessing keys with dot notation
217
+ # @api private
218
+ # @return [Object]
219
+ # @example
220
+ # district = Clever::District.retrieve id
221
+ # district.name = "New district name"
124
222
  def method_missing(name, *args)
125
223
  return @values[name] if @values.key? name
126
224
  return nil if optional_attributes.include? name
@@ -1,8 +1,24 @@
1
1
  module Clever
2
2
  # Configuration for accessing the Clever API over HTTP
3
3
  class Configuration
4
- attr_accessor :api_key, :token, :api_base
4
+ # Access API Key
5
+ # @api private
6
+ # @return [String]
7
+ attr_accessor :api_key
5
8
 
9
+ # Access API Token
10
+ # @api private
11
+ # @return [String]
12
+ attr_accessor :token
13
+
14
+ # Access API base URL
15
+ # @api private
16
+ # @return [String]
17
+ attr_accessor :api_base
18
+
19
+ # Initialize configuration
20
+ # @api private
21
+ # @return [Clever::Configuration]
6
22
  def initialize
7
23
  @api_key = nil
8
24
  @token = nil
@@ -4,11 +4,15 @@ module Clever
4
4
  include Clever::APIOperations::List
5
5
  @linked_resources = [:schools, :teachers, :sections, :students, :events]
6
6
 
7
+ # @see Clever::CleverObject.optional_attributes
8
+ # @api private
9
+ # @return [Array]
7
10
  def optional_attributes
8
11
  # All of a district's attributes are required.
9
12
  []
10
13
  end
11
14
 
15
+ # TODO: remove
12
16
  [:school_pages, :teacher_pages, :section_pages, :student_pages, :event_pages].each do |name|
13
17
  define_method(name) do |filters = {}|
14
18
  Clever::APIOperations::PageList.new get_uri(name.to_s.gsub('_page', '')), filters
@@ -17,6 +21,9 @@ module Clever
17
21
 
18
22
  private
19
23
 
24
+ # Get the URI for a hypermedia link
25
+ # @api private
26
+ # @return [String]
20
27
  def get_uri(resource_type)
21
28
  refresh
22
29
  links.find { |link| link[:rel] == resource_type }[:uri]
@@ -1,11 +1,37 @@
1
1
  module Clever
2
2
  # Represents an error outputted bythe Clever API
3
3
  class CleverError < StandardError
4
+ # Access error Message
5
+ # @api public
6
+ # @return [String]
7
+ # @example
8
+ # puts err.message
4
9
  attr_reader :message
10
+
11
+ # Access HTTP status of error
12
+ # @api public
13
+ # @return [Integer]
14
+ # @example
15
+ # puts err.http_status
5
16
  attr_reader :http_status
17
+
18
+ # Access HTTP body of error
19
+ # @api public
20
+ # @return [String]
21
+ # @example
22
+ # puts err.http_body
6
23
  attr_reader :http_body
24
+
25
+ # Access JSON body of error
26
+ # @api public
27
+ # @return [String]
28
+ # @example
29
+ # puts err.json_body
7
30
  attr_reader :json_body
8
31
 
32
+ # Create CleverError instance
33
+ # @api private
34
+ # @return [Clever::CleverError]
9
35
  def initialize(message = nil, http_status = nil, http_body = nil, json_body = nil)
10
36
  @message = message
11
37
  @http_status = http_status
@@ -13,6 +39,11 @@ module Clever
13
39
  @json_body = json_body
14
40
  end
15
41
 
42
+ # Output CleverError instance as a human-readable string
43
+ # @api public
44
+ # @return [String]
45
+ # @example
46
+ # puts err.to_s
16
47
  def to_s
17
48
  status_string = @http_status.nil? ? '' : "(Status #{@http_status}) "
18
49
  "#{status_string}#{@message}"
@@ -1,8 +1,14 @@
1
1
  module Clever
2
2
  # An invalid request to the Clever API
3
3
  class InvalidRequestError < CleverError
4
+ # Access param
5
+ # @api private
6
+ # @return [Object]
4
7
  attr_accessor :param
5
8
 
9
+ # Create new InvalidRequestError
10
+ # @api private
11
+ # @return [Clever::InvalidRequestError]
6
12
  def initialize(message, param, http_status = nil, http_body = nil, json_body = nil)
7
13
  super message, http_status, http_body, json_body
8
14
  @param = param
@@ -3,30 +3,55 @@ module Clever
3
3
  class Event < APIResource
4
4
  include Clever::APIOperations::List
5
5
 
6
+ # Optional attributes
7
+ # @see Clever::CleverObject.optional_attributes
8
+ # @api private
9
+ # @return [Array]
6
10
  def optional_attributes
7
11
  []
8
12
  end
9
13
 
14
+ # Get object corresponding to this event
15
+ # @api public
16
+ # @return [CleverObject]
17
+ # @example
18
+ # district = event.object
10
19
  def object
11
20
  klass = Util.types_to_clever_class type_pieces[0]
12
21
  klass ||= CleverObject
13
22
  klass.construct_from data[:object]
14
23
  end
15
24
 
25
+ # Get previous attributes before the event
26
+ # @api public
27
+ # @return [Hash]
28
+ # @example
29
+ # prev = event.previous_attributes
16
30
  def previous_attributes
17
31
  data[:previous_attributes]
18
32
  end
19
33
 
34
+ # Get action taken in Event
35
+ # @api public
36
+ # @return [String]
37
+ # @example
38
+ # action = event.action
20
39
  def action
21
40
  type_pieces[1]
22
41
  end
23
42
 
43
+ # Get URL for events endpoint
44
+ # @api private
45
+ # @return [String]
24
46
  def self.url
25
47
  'v1.1/events'
26
48
  end
27
49
 
28
50
  private
29
51
 
52
+ # Split type of Event into pieces
53
+ # @api private
54
+ # @return [Array]
30
55
  def type_pieces
31
56
  type.split '.'
32
57
  end
@@ -2,18 +2,30 @@ module Clever
2
2
  # Helpers for handling JSON responses
3
3
  module JSON
4
4
  if MultiJson.respond_to? :dump
5
+ # Dump as a JSON string
6
+ # @api private
7
+ # @return [String]
5
8
  def self.dump(*args)
6
9
  MultiJson.dump(*args)
7
10
  end
8
11
 
12
+ # Load a JSON string to an object
13
+ # @api private
14
+ # @return [Object]
9
15
  def self.load(*args)
10
16
  MultiJson.load(*args, symbolize_keys: true)
11
17
  end
12
18
  else
19
+ # Dump as a JSON string
20
+ # @api private
21
+ # @return [String]
13
22
  def self.dump(*args)
14
23
  MultiJson.encode(*args)
15
24
  end
16
25
 
26
+ # Load a JSON string to an object
27
+ # @api private
28
+ # @return [Object]
17
29
  def self.load(*args)
18
30
  MultiJson.decode(*args, symbolize_keys: true)
19
31
  end
@@ -4,6 +4,10 @@ module Clever
4
4
  include Clever::APIOperations::List
5
5
  @linked_resources = [:teachers, :students, :sections, :districts, :events]
6
6
 
7
+ # Optional attributes
8
+ # @see Clever::CleverObject.optional_attributes
9
+ # @api private
10
+ # @return [Array]
7
11
  def optional_attributes
8
12
  [:state_id, :sis_id, :nces_id, :low_grade, :high_grade, :principal, :location, :phone]
9
13
  end
@@ -4,6 +4,10 @@ module Clever
4
4
  include Clever::APIOperations::List
5
5
  @linked_resources = [:teachers, :students, :schools, :districts, :events]
6
6
 
7
+ # Optional attributes
8
+ # @see Clever::CleverObject.optional_attributes
9
+ # @api private
10
+ # @return [Array]
7
11
  def optional_attributes
8
12
  [:teacher, :course_name, :course_description, :course_number, :period, :grade, :term]
9
13
  end
@@ -4,21 +4,13 @@ module Clever
4
4
  include Clever::APIOperations::List
5
5
  @linked_resources = [:teachers, :sections, :schools, :districts, :events, :contacts]
6
6
 
7
+ # Optional attributes
8
+ # @see Clever::CleverObject.optional_attributes
9
+ # @api private
10
+ # @return [Array]
7
11
  def optional_attributes
8
12
  [:student_number, :state_id, :location, :gender, :dob, :grade, :frl_status,
9
13
  :race, :hispanic_ethnicity, :email, :credentials]
10
14
  end
11
-
12
- def photo
13
- return @values[:photo] if @values.key? :photo
14
- response = Clever.request :get, photo_url
15
- @values[:photo] = response[:data][:data]
16
- end
17
-
18
- private
19
-
20
- def photo_url
21
- url + '/photo'
22
- end
23
15
  end
24
16
  end
@@ -4,6 +4,10 @@ module Clever
4
4
  include Clever::APIOperations::List
5
5
  @linked_resources = [:sections, :students, :schools, :districts, :events, :grade_levels]
6
6
 
7
+ # Optional attributes
8
+ # @see Clever::CleverObject.optional_attributes
9
+ # @api private
10
+ # @return [Array]
7
11
  def optional_attributes
8
12
  [:email, :teacher_number, :title]
9
13
  end
@@ -1,10 +1,17 @@
1
1
  module Clever
2
- # LibraryhHelper methods
2
+ # Library helper methods
3
3
  module Util
4
+ # Check if a given ID is a valid format (MongoDB BSON ObjectID)
5
+ # @api private
6
+ # @param id [String] ID to check
7
+ # @return [Boolean] Whether or not it was valid
4
8
  def self.valid_id?(id)
5
9
  id.is_a?(String) && !(/^[0-9a-fA-F]{24}$/.match(id).nil?)
6
10
  end
7
11
 
12
+ # Replace APIResource objects with their ids in data structures
13
+ # @api private
14
+ # @return [Object] Original data structure with objects replaced by ids
8
15
  def self.objects_to_ids(h)
9
16
  case h
10
17
  when APIResource
@@ -20,6 +27,9 @@ module Clever
20
27
  end
21
28
  end
22
29
 
30
+ # Convert the name of a resource to its APIResource class
31
+ # @api private
32
+ # @return [APIResource]
23
33
  def self.types_to_clever_class(type)
24
34
  types = {
25
35
  'students' => Student,
@@ -32,6 +42,9 @@ module Clever
32
42
  types.fetch type
33
43
  end
34
44
 
45
+ # Convert an object containing data from Clever into a CleverObject
46
+ # @api private
47
+ # @return [CleverObject]
35
48
  def self.convert_to_clever_object(resp)
36
49
  case resp
37
50
  when Array
@@ -48,6 +61,9 @@ module Clever
48
61
  end
49
62
  end
50
63
 
64
+ # Check if a file is readable
65
+ # @api private
66
+ # @return [Boolean]
51
67
  def self.file_readable(file)
52
68
  File.open(file) {}
53
69
  rescue
@@ -56,10 +72,16 @@ module Clever
56
72
  true
57
73
  end
58
74
 
75
+ # URL encode a key
76
+ # @api private
77
+ # @return [String]
59
78
  def self.encode_key(key)
60
79
  URI.escape key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
61
80
  end
62
81
 
82
+ # Flatten a params hash into an array
83
+ # @api private
84
+ # @return [Array]
63
85
  def self.flatten_params(params, parent_key = nil)
64
86
  result = []
65
87
  params.each do |key, value|
@@ -75,6 +97,9 @@ module Clever
75
97
  result
76
98
  end
77
99
 
100
+ # Flatten a nested params array into a flat array
101
+ # @api private
102
+ # @return [Array]
78
103
  def self.flatten_params_array(value, calculated_key)
79
104
  result = []
80
105
  value.each do |elem|
@@ -1,4 +1,4 @@
1
1
  # Clever Ruby library
2
2
  module Clever
3
- VERSION = '0.6.0'
3
+ VERSION = '0.6.1'
4
4
  end
data/lib/clever-ruby.rb CHANGED
@@ -40,27 +40,50 @@ require 'clever-ruby/errors/invalid_request_error'
40
40
  # Clever Ruby library
41
41
  module Clever
42
42
  class << self
43
+ # Global configuration for using Clever
44
+ # @api public
45
+ # @example Configure your API key
46
+ # Clever.configure do |config|
47
+ # config.api_key = 'YOUR-API-KEY'
48
+ # end
49
+ # @return [Object]
43
50
  def configure
44
51
  yield configuration
45
52
  end
46
53
 
54
+ # Retrieve your stored API key
55
+ # @api private
56
+ # @return [String] API key
47
57
  def api_key
48
58
  configuration.api_key
49
59
  end
50
60
 
61
+ # Retrieve your stored API token
62
+ # @api private
63
+ # @return [String] API token
51
64
  def token
52
65
  configuration.token
53
66
  end
54
67
 
68
+ # Retrieve the global Clever configuration object
69
+ # @api private
70
+ # @return [Hash] API configuration object
55
71
  def configuration
56
72
  @configuration ||= Clever::Configuration.new
57
73
  end
58
74
 
75
+ # Retrieve the URL of the Clever API being used
76
+ # @api private
77
+ # @return [String] API url
59
78
  def api_url(url = '')
60
79
  configuration.api_base + url
61
80
  end
62
81
  end
63
82
 
83
+ # Convert a hash of params to a query string. Does not prepend the leading '?'
84
+ # @api private
85
+ # @param params [Hash] Parameters to stringify
86
+ # @return [String] Query string
64
87
  def self.convert_to_query_string(params = nil)
65
88
  if params && params.count
66
89
  params_arr = Util.flatten_params(params).map do |p|
@@ -72,6 +95,12 @@ module Clever
72
95
  end
73
96
  end
74
97
 
98
+ # Generate the URL and payload for a request based on data about the request
99
+ # @api private
100
+ # @param method [Symbol] HTTP method used
101
+ # @param url [String] URL to send to
102
+ # @param params [Hash] Parameters to send
103
+ # @return [String, String] URL and payload to send via HTTP
75
104
  def self.create_payload(method, url, params)
76
105
  case method.to_s.downcase.to_sym
77
106
  when :get, :head, :delete
@@ -88,6 +117,9 @@ module Clever
88
117
  [url, payload]
89
118
  end
90
119
 
120
+ # Create options hash that specifies an HTTP request from request data
121
+ # @api private
122
+ # @return [Hash] parameters for executing a request
91
123
  def self.create_request_opts(method, url, params, headers)
92
124
  params = Util.objects_to_ids params
93
125
  url = api_url url
@@ -110,6 +142,10 @@ module Clever
110
142
  opts
111
143
  end
112
144
 
145
+ # Confirm API key or token are globally configured
146
+ # @api private
147
+ # @return [nil]
148
+ # @raise [AuthenticationError] Error if no authentication present
113
149
  def self.check_authorization
114
150
  unless Clever.api_key || Clever.token
115
151
  fail AuthenticationError, 'No API key provided. (HINT: set your API key using '\
@@ -118,6 +154,14 @@ module Clever
118
154
  end
119
155
  end
120
156
 
157
+ # Send an HTTP request to the Clever API
158
+ # @api private
159
+ # @param method [Symbol] HTTP method used
160
+ # @param url [String] URL to send to
161
+ # @param params [Hash] parameters to send with the request
162
+ # @param headers [Hash] headers to send with the request
163
+ # @return [Hash] parsed JSON response
164
+ # @raise [APIError] Error if API fails to return valid JSON
121
165
  def self.request(method, url, params = nil, headers = {})
122
166
  check_authorization
123
167
  opts = create_request_opts method, url, params, headers
@@ -138,6 +182,11 @@ module Clever
138
182
 
139
183
  private
140
184
 
185
+ # Execute an HTTP request safely
186
+ # @api private
187
+ # @param opts [Hash] Definition of the request to make
188
+ # @return [String] Request results
189
+ # @raise [APIConnectionError] Request failure
141
190
  def self.execute_request(opts)
142
191
  begin
143
192
  request = RestClient::Request.execute opts
@@ -164,6 +213,11 @@ module Clever
164
213
  request
165
214
  end
166
215
 
216
+ # Translate errors thrown by RestClient into standardized APIConnectionErrors
217
+ # @api private
218
+ # @param e [Error] Error to handle
219
+ # @return [nil]
220
+ # @raise [APIConnectionError] Standardized error for request failures
167
221
  def self.handle_restclient_error(e)
168
222
  case e
169
223
  when RestClient::ServerBrokeConnection, RestClient::RequestTimeout
@@ -180,6 +234,12 @@ module Clever
180
234
  fail APIConnectionError, message
181
235
  end
182
236
 
237
+ # Translate errors returned as JSON by the Clever API into CleverErrors
238
+ # @api private
239
+ # @param rcode [Integer] response code
240
+ # @param rbody [String] response body
241
+ # @return [nil]
242
+ # @raise [CleverError] Clever error corresponding to the failure observed
183
243
  def self.handle_api_error(rcode, rbody)
184
244
  begin
185
245
  error_obj = Clever::JSON.load rbody
@@ -201,6 +261,9 @@ module Clever
201
261
  end
202
262
  end
203
263
 
264
+ # Generate an InvalidRequestError
265
+ # @api private
266
+ # @return [InvalidRequestError]
204
267
  def self.invalid_request_error(error, rcode, rbody, error_obj)
205
268
  if error.is_a? Hash
206
269
  InvalidRequestError.new error[:message], error[:param], rcode, rbody, error_obj
@@ -209,10 +272,16 @@ module Clever
209
272
  end
210
273
  end
211
274
 
275
+ # Generate an AuthenticationError
276
+ # @api private
277
+ # @return [AuthenticationError]
212
278
  def self.authentication_error(error, rcode, rbody, error_obj)
213
279
  AuthenticationError.new error[:message], rcode, rbody, error_obj
214
280
  end
215
281
 
282
+ # Generate an APIError
283
+ # @api private
284
+ # @return [APIError]
216
285
  def self.api_error(error, rcode, rbody, error_obj)
217
286
  APIError.new error[:message], rcode, rbody, error_obj
218
287
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clever-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clever Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-10 00:00:00.000000000 Z
11
+ date: 2014-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -81,19 +81,47 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: 3.3.2
83
83
  - !ruby/object:Gem::Dependency
84
- name: rdoc
84
+ name: yard
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ~>
88
88
  - !ruby/object:Gem::Version
89
- version: '3.12'
89
+ version: 0.8.7
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ~>
95
95
  - !ruby/object:Gem::Version
96
- version: '3.12'
96
+ version: 0.8.7
97
+ - !ruby/object:Gem::Dependency
98
+ name: yardstick
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 0.9.9
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 0.9.9
111
+ - !ruby/object:Gem::Dependency
112
+ name: redcarpet
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 3.1.2
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 3.1.2
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: vcr
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -175,6 +203,7 @@ files:
175
203
  - .drone.yml
176
204
  - .gitignore
177
205
  - .rubocop.yml
206
+ - .yardopts
178
207
  - CHANGELOG.md
179
208
  - Gemfile
180
209
  - LICENSE