clever-ruby 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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