lessonly-ruby 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 05e500d1cfe48a8a50cb16f50f921c652887474b
4
+ data.tar.gz: 5e7e36a9db0d0040d82048302004b9abde2438ed
5
+ SHA512:
6
+ metadata.gz: 757b43c94fe0649d9a81130e8ec366a1ae537235493458ae4b6356f359b4fc389f617b98895e129823b826823b85928adfd9bc487f06cb503069a95edd6c8e5f
7
+ data.tar.gz: 3fff06a332fa0c36678b048253a1dbdbbd8d8d17ec018b38584a953a141f27f77c6d1cb3a61dc3d153a869ee5191fd45d9f753eb222799a70ddb5dc132e08737
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,2 @@
1
+ rvm:
2
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in aptible-auth.gemspec
4
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Aptible, Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Procfile ADDED
@@ -0,0 +1 @@
1
+ console: bundle exec pry -r lessonly
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # ![](https://raw.github.com/aptible/straptible/master/lib/straptible/rails/templates/public.api/icon-60px.png) Lessonly Ruby Client
2
+
3
+
4
+ Ruby client for [Lesson.ly](http://lesson.ly) API.
5
+
6
+
7
+ ## Installation
8
+
9
+ Add the following line to your application's Gemfile
10
+
11
+ ```ruby
12
+ gem 'lessonly-ruby'
13
+ ```
14
+
15
+ And then run `bundle install`.
16
+
17
+ ## Usage
18
+
19
+ First, configure your client:
20
+
21
+ ```ruby
22
+ require 'lessonly'
23
+
24
+ Lessonly.configure do |config|
25
+ config.root_url = 'https://api.lesson.ly/api/v1'
26
+ config.api_key = `LESSONLY API KEY`
27
+ config.domain = `LESSONLY SUBDOMAIN`
28
+ end
29
+ ```
30
+
31
+ This is best done in an application initializer inside `config/initializers`.
32
+
33
+ From here, you can interact with the Lessonly API resources however you wish:
34
+
35
+ ### Users
36
+
37
+ ```ruby
38
+ all_users = Lessonly::User.all
39
+
40
+ skylar = Lessonly::User.find(user_id)
41
+ skylar.name # "Skylar Anderson"
42
+ skylar.email # "skylar@aptible.com"
43
+
44
+ frank = Lessonly::User.create({ name: 'Frank Macreery', email: 'frank@aptible.com', role: 'learner' })
45
+ frank.name # "Frank Macreery"
46
+ ```
47
+
48
+ ### Groups
49
+
50
+ ```ruby
51
+ all_groups = Lessonly::Group.all
52
+ developers = Lessonly::Group.find(group_id)
53
+ ```
54
+
55
+ ### Add a user to a group
56
+
57
+ ```ruby
58
+ developers = Lessonly::Group.find(group_id)
59
+
60
+ developers.create_membership(skylar) # Add Skylar to developers group
61
+ developers.create_membership(frank) # Add Frank to developers group
62
+ ```
63
+
64
+ ### Courses
65
+
66
+ ```ruby
67
+ all_courses = Lessonly::Course.all
68
+
69
+ course = Lessonly::Course.find(course_id)
70
+ course.create_assignment(skylar, 1.year.from_now) # Skylar assigned to course, due in 1 year
71
+
72
+ course.assignments.count # 1
73
+ course.assignments.first.user.name # "Skylar"
74
+ course.assignments.first.user.email # "skylar@aptible.com"
75
+
76
+ course.lessons.count # 1
77
+ course.lessons.first.title # "Developer Lesson"
78
+ ```
79
+
80
+ ### Assign a course to a user
81
+
82
+ ```ruby
83
+ course = Lessonly::Course.find(course_id)
84
+ user = Lessonly::User.find(user_id)
85
+
86
+ course.create_assignment(skylar, 1.month.from_now) # User assigned to course, due in a month
87
+ ```
88
+
89
+ ## Contributing
90
+
91
+ 1. Fork the project.
92
+ 1. Commit your changes, with specs.
93
+ 1. Ensure that your code passes specs (`rake spec`) and meets Aptible's Ruby style guide (`rake rubocop`).
94
+ 1. Create a new pull request on GitHub.
95
+
96
+ ## Copyright and License
97
+
98
+ MIT License, see [LICENSE](LICENSE.md) for details.
99
+
100
+ Copyright (c) 2014 [Aptible](https://www.aptible.com) and contributors.
101
+
102
+ [<img src="https://s.gravatar.com/avatar/9b58236204e844e3181e43e05ddb0809?s=60" style="border-radius: 50%;" alt="@sandersonet" />](https://github.com/sandersonet)
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'aptible/tasks'
4
+ Aptible::Tasks.load_tasks
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'English'
6
+ require 'lessonly/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'lessonly-ruby'
10
+ spec.version = Lessonly::VERSION
11
+ spec.authors = ['Skylar Anderson']
12
+ spec.email = ['skylar@aptible.com']
13
+ spec.description = 'Ruby client for Lesson.ly API'
14
+ spec.summary = 'Ruby client for Lesson.ly API'
15
+ spec.homepage = 'https://github.com/aptible/lessonly-ruby'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files`.split($RS)
19
+ spec.test_files = spec.files.grep(%r{^spec\/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'gem_config'
23
+ spec.add_dependency 'sawyer', '~> 0.5.3'
24
+ spec.add_dependency 'activesupport'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.3'
27
+ spec.add_development_dependency 'aptible-tasks'
28
+ spec.add_development_dependency 'rake'
29
+ spec.add_development_dependency 'rspec'
30
+ spec.add_development_dependency 'webmock'
31
+ spec.add_development_dependency 'pry'
32
+ spec.add_development_dependency 'sinatra'
33
+ end
data/lib/lessonly.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'gem_config'
2
+ require 'lessonly/defaults'
3
+
4
+ module Lessonly
5
+ include GemConfig::Base
6
+
7
+ with_configuration do
8
+ has :root_url,
9
+ classes: String,
10
+ default: ENV['LESSONLY_ROOT_URL'] || 'https://api.lesson.ly/api/v1'
11
+
12
+ has :api_key,
13
+ classes: String,
14
+ default: ENV['LESSONLY_API_KEY'] || ''
15
+
16
+ has :domain,
17
+ classes: String,
18
+ default: ENV['LESSONLY_DOMAIN'] || ''
19
+ end
20
+ end
21
+
22
+ require 'lessonly/client'
23
+ require 'lessonly/resource'
@@ -0,0 +1,62 @@
1
+ require 'sawyer'
2
+ require 'lessonly/serializer'
3
+ require 'base64'
4
+
5
+ module Lessonly
6
+ class Client
7
+ include Lessonly::Defaults
8
+ attr_reader :agent
9
+ attr_reader :last_response
10
+
11
+ def get(url, query = {})
12
+ request :get, url, nil, query: query
13
+ end
14
+
15
+ def post(url, resource, query = {})
16
+ request(:post, url, resource, query: query)
17
+ end
18
+
19
+ def put(url, resource, query = {})
20
+ request :put, url, resource, query: query
21
+ end
22
+
23
+ def delete(url, resource)
24
+ request :delete, url, resource
25
+ end
26
+
27
+ def patch(url, resource, query = {})
28
+ request :patch, url, resource, query: query
29
+ end
30
+
31
+ def agent
32
+ @agent ||= Sawyer::Agent.new(api_endpoint, sawyer_options) do |http|
33
+ http.headers[:accept] = media_type
34
+ http.headers[:user_agent] = user_agent
35
+ http.headers[:authorization] = "Basic #{auth_token}"
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def auth_token
42
+ Base64.strict_encode64("#{domain}:#{api_key}")
43
+ end
44
+
45
+ def sawyer_options
46
+ {
47
+ faraday: Faraday.new(connection_options),
48
+ serializer: Lessonly::Serializer.any_json
49
+ }
50
+ end
51
+
52
+ def request(method, path, data, options = {})
53
+ options[:headers] ||= {}
54
+ unless method == :get
55
+ options[:headers][:content_type] = 'application/json'
56
+ end
57
+
58
+ @last_response = agent.call(method, path, data, options)
59
+ @last_response.data
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,34 @@
1
+ require 'lessonly/version'
2
+
3
+ module Lessonly
4
+ module Defaults
5
+ def api_key
6
+ Lessonly.configuration.api_key
7
+ end
8
+
9
+ def api_endpoint
10
+ Lessonly.configuration.root_url
11
+ end
12
+
13
+ def domain
14
+ Lessonly.configuration.domain
15
+ end
16
+
17
+ def user_agent
18
+ "Lessonly Ruby Gem #{Lessonly::VERSION} made by Aptible"
19
+ end
20
+
21
+ def media_type
22
+ 'application/json'
23
+ end
24
+
25
+ def connection_options
26
+ {
27
+ headers: {
28
+ accept: media_type,
29
+ user_agent: user_agent
30
+ }
31
+ }
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ module Lessonly
2
+ class Exception < ::StandardError
3
+ attr_accessor :cause
4
+
5
+ def initialize(message, attrs = {})
6
+ self.cause = attrs[:cause]
7
+ super(message)
8
+ end
9
+ end
10
+
11
+ class ResponseError < Exception
12
+ attr_accessor :response
13
+ attr_accessor :body
14
+
15
+ def initialize(message, attrs = {})
16
+ self.response = attrs[:response]
17
+ self.body = attrs[:body]
18
+
19
+ if body.present? && body.key?(:error)
20
+ error = body[:error]
21
+ message = "#{message} (#{error})"
22
+ elsif response
23
+ message = "#{message} (\"#{response.inspect}\")"
24
+ end
25
+
26
+ super(message, attrs)
27
+ end
28
+ end
29
+
30
+ class ResourceNotFoundError < ResponseError; end
31
+ end
@@ -0,0 +1,102 @@
1
+ require 'active_support'
2
+ require 'active_support/inflector'
3
+ require 'active_support/core_ext'
4
+ require 'lessonly/response'
5
+
6
+ module Lessonly
7
+ class Resource < Sawyer::Resource
8
+ def self.all(query = {})
9
+ client.get collection_path, query: query
10
+ end
11
+
12
+ def self.find(id)
13
+ find_by_href("#{collection_path}/#{id}")
14
+ end
15
+
16
+ def self.find_by_href(href)
17
+ client.get(href)
18
+ end
19
+
20
+ def self.create(params, query = {})
21
+ client.post collection_path, new(client.agent, params), query: query
22
+ end
23
+
24
+ def self.collection_path
25
+ basename
26
+ end
27
+
28
+ # rubocop:disable PredicateName
29
+ def self.has_many(relation)
30
+ define_has_many_getter(relation)
31
+ # TODO: define_has_many_setter(relation)
32
+ end
33
+ # rubocop:enable PredicateName
34
+
35
+ def self.define_has_many_getter(relation)
36
+ define_method relation do
37
+ if (memoized = instance_variable_get("@#{relation}"))
38
+ memoized
39
+ else
40
+ entries = client.get("#{href}/#{relation}")
41
+ instance_variable_set("@#{relation}", entries)
42
+ entries
43
+ end
44
+ end
45
+ end
46
+
47
+ # rubocop:disable PredicateName
48
+ def self.has_one(relation, options = {})
49
+ define_method relation do
50
+ if (memoized = instance_variable_get("@#{relation}"))
51
+ memoized
52
+ else
53
+ klass = options[:klass] || "Lessonly::#{relation.classify}"
54
+
55
+ id_attr = options[:using] ? options[:using] : "#{relation}_id"
56
+ relation_id = instance_variable_get('@attrs')[id_attr]
57
+
58
+ if relation_id
59
+ item = klass.constantize.find(relation_id)
60
+ instance_variable_set("@#{relation}", item)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ # rubocop:enable PredicateName
66
+
67
+ def self.basename
68
+ name.split('::').last.underscore.dasherize.pluralize
69
+ end
70
+
71
+ def update(params)
72
+ self.attrs = attrs.merge(params)
73
+ client.put href, self
74
+ end
75
+
76
+ def destroy
77
+ client.delete href, self
78
+ end
79
+
80
+ def reload
81
+ self.class.find_by_href(href)
82
+ end
83
+
84
+ def href
85
+ "#{self.class.collection_path}/#{id}"
86
+ end
87
+
88
+ def self.client
89
+ @client ||= Lessonly::Client.new
90
+ end
91
+
92
+ def client
93
+ self.class.client
94
+ end
95
+ end
96
+ end
97
+
98
+ require 'lessonly/resource/assignment'
99
+ require 'lessonly/resource/course'
100
+ require 'lessonly/resource/group'
101
+ require 'lessonly/resource/lesson'
102
+ require 'lessonly/resource/user'
@@ -0,0 +1,5 @@
1
+ module Lessonly
2
+ class Assignment < Resource
3
+ has_one :user, klass: 'Lessonly::User', using: :assignee_id
4
+ end
5
+ end
@@ -0,0 +1,33 @@
1
+ module Lessonly
2
+ class Course < Resource
3
+ has_many :assignments
4
+
5
+ def initialize(agent, data = {})
6
+ super(agent, data)
7
+
8
+ define_has_many_lessons if @attrs[:lessons]
9
+ end
10
+
11
+ def define_has_many_lessons
12
+ self.lessons = @attrs[:lessons].map do |l|
13
+ Lessonly::Lesson.new(agent, l.attrs)
14
+ end
15
+ end
16
+
17
+ def create_assignment(user, due_by = 1.year.from_now)
18
+ self.assignments = assignments.push(
19
+ Lessonly::Assignment.new(agent, assignee_id: user.id, due_by: due_by)
20
+ )
21
+
22
+ client.put "#{href}/assignments",
23
+ Resource.new(agent, assignments: assignments)
24
+ end
25
+
26
+ def destroy_assignment(user)
27
+ self.assignments = assignments.select { |a| a.assignee_id != user.id }
28
+
29
+ client.put "#{href}/assignments",
30
+ Resource.new(agent, assignments: assignments)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,18 @@
1
+ module Lessonly
2
+ class Group < Resource
3
+ def destroy_membership(user)
4
+ return unless members.any?
5
+
6
+ new_members = members.map do |m|
7
+ m.remove = true if m.id == user.id
8
+ end
9
+
10
+ update(members: new_members)
11
+ end
12
+
13
+ def create_membership(user)
14
+ self.members = members.push(user)
15
+ update(members: members)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ module Lessonly
2
+ class Lesson < Resource
3
+ has_many :assignments
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Lessonly
2
+ class User < Resource
3
+ end
4
+ end
@@ -0,0 +1,70 @@
1
+ require 'logger'
2
+ require 'lessonly/exceptions'
3
+ require 'pry'
4
+
5
+ module Sawyer
6
+ class Response
7
+ # rubocop:disable MethodLength
8
+ def initialize(agent, res, options = {})
9
+ if res.status >= 400
10
+ fail Lessonly::ResponseError.new(
11
+ res.status.to_s,
12
+ response: res,
13
+ body: agent.decode_body(res.body),
14
+ cause: res.status
15
+ )
16
+ end
17
+
18
+ @res = res
19
+ @agent = agent
20
+ @status = res.status
21
+ @headers = res.headers
22
+ @env = res.env
23
+ @rels = process_rels
24
+ @started = options[:sawyer_started]
25
+ @ended = options[:sawyer_ended]
26
+ @data = if @headers[:content_type] =~ /json|msgpack/
27
+ process_data(@agent.decode_body(res.body))
28
+ else
29
+ res.body
30
+ end
31
+
32
+ log_response
33
+ end
34
+ # rubocop:enable MethodLength
35
+
36
+ def log_response
37
+ # puts @env
38
+ end
39
+
40
+ def process_data(data)
41
+ @type = type_from_data(data) || @type
42
+ fail 'No type!' unless @type
43
+
44
+ data = data[@type.to_sym] if data.key?(@type.to_sym)
45
+
46
+ case data
47
+ when Hash then klass_from_type(data).new(agent, data)
48
+ when Array then data.map { |hash| process_data(hash) }
49
+ when nil then nil
50
+ else data
51
+ end
52
+ end
53
+
54
+ def klass_from_type(result)
55
+ # Get sub object type if exists, otherwise
56
+ # defer to parent type
57
+ type = type_from_data(result) || @type
58
+ "Lessonly::#{type.classify}".constantize
59
+ end
60
+
61
+ def type_from_data(data)
62
+ # Create user type: `create_user`
63
+ # Delete user type: `delete_user`
64
+ # Course assignment type: `course_assignments`
65
+ # Use the last segment of type to determine resource class
66
+ return nil unless data.key? :type
67
+ data[:type].split('_').last
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,19 @@
1
+ module Lessonly
2
+ class Serializer < Sawyer::Serializer
3
+ def encode_object(resource)
4
+ resource
5
+ # return resource.serialize if resource.respond_to? :serialize
6
+ # case resource
7
+ # when Hash then encode_hash(resource)
8
+ # when Array then resource.map { |o| encode_object(o) }
9
+ # else resource
10
+ # end
11
+ end
12
+
13
+ def time_field?(key, value)
14
+ time_fields = %w(created updated start stop initalPeriodStart
15
+ currentPeriodStart currentPeriodEnd)
16
+ value && time_fields.include?(key)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module Lessonly
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lessonly::Course do
4
+ context '#all' do
5
+ it 'should return all courses' do
6
+ courses = Lessonly::Course.all
7
+ expect(courses.count).to eq 3
8
+ expect(courses.first.title).to eq 'HIPAA Basic'
9
+ expect(courses.first.id).to eq 1
10
+ end
11
+ end
12
+
13
+ context '#find' do
14
+ it 'should find a single course' do
15
+ course = Lessonly::Course.find(1)
16
+ expect(course.title).to eq 'HIPAA Advanced'
17
+ end
18
+ end
19
+
20
+ context '#lessons' do
21
+ it 'should have many lessons' do
22
+ course = Lessonly::Course.find(1)
23
+
24
+ expect(course.lessons.first).to be_a Lessonly::Lesson
25
+ expect(course.lessons.first.title).to eq 'Basic HIPAA Lesson'
26
+ end
27
+ end
28
+
29
+ context '#assignments' do
30
+ it 'should have many assignments' do
31
+ course = Lessonly::Course.find(1)
32
+ assignments = course.assignments
33
+
34
+ expect(assignments.count).to eq 1
35
+ end
36
+
37
+ it 'should serialize assignment assignees as user' do
38
+ course = Lessonly::Course.find(1)
39
+ assignee = course.assignments.first.user
40
+
41
+ expect(assignee).to be_a Lessonly::User
42
+ expect(assignee.name).to eq 'Chas Ballew'
43
+ end
44
+ end
45
+
46
+ context '#create_assignment' do
47
+ it 'should create a user assignment' do
48
+ course = Lessonly::Course.find(1)
49
+ user = Lessonly::User.find(3)
50
+
51
+ course.create_assignment(user)
52
+
53
+ expect(course.assignments.map(&:assignee_id)).to include(user.id)
54
+ expect(course.assignments.count).to eq 2
55
+ end
56
+ end
57
+
58
+ context '#destroy_assignment' do
59
+ it 'should remove a user assignment' do
60
+ course = Lessonly::Course.find(1)
61
+ user = Lessonly::User.find(1)
62
+
63
+ course.destroy_assignment(user)
64
+
65
+ expect(course.assignments.count).to eq 0
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lessonly::Group do
4
+ context '#all' do
5
+ it 'should return all groups' do
6
+ groups = Lessonly::Group.all
7
+ expect(groups.count).to eq 1
8
+ end
9
+ end
10
+
11
+ context '#find' do
12
+ it 'should find a single group' do
13
+ group = Lessonly::Group.find(1)
14
+ expect(group.name).to eq 'Developers'
15
+ end
16
+ end
17
+
18
+ context '#create_membership' do
19
+ it 'should add a user to the group\'s members' do
20
+ group = Lessonly::Group.find(1)
21
+ user = Lessonly::User.find(3)
22
+
23
+ group.create_membership(user)
24
+
25
+ expect(group.members.map(&:name)).to include(user.name)
26
+ expect(group.members.count).to eq(3)
27
+ end
28
+ end
29
+
30
+ context '#destroy_membership' do
31
+ it 'should remove a user from the group\'s members' do
32
+ group = Lessonly::Group.find(1)
33
+ user = Lessonly::User.find(1)
34
+
35
+ group.destroy_membership(user)
36
+
37
+ member = group.members.find { |m| m.id == user.id }
38
+ expect(member.remove).to eq(true)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ require 'webmock/rspec'
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+
6
+ require 'lessonly'
7
+ require 'support/fake_lessonly'
8
+
9
+ WebMock.disable_net_connect!
10
+
11
+ RSpec.configure do |c|
12
+ c.before(:example) do
13
+ WebMock.stub_request(:any, /api.lesson.ly/).to_rack(FakeLessonly)
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ require 'sinatra/base'
2
+
3
+ class FakeLessonly < Sinatra::Base
4
+ resources = %w(users groups courses lessons)
5
+
6
+ resources.each do |resource|
7
+ get "/api/v1/#{resource}" do
8
+ json_response 200, "get_#{resource}.json"
9
+ end
10
+
11
+ get "/api/v1/#{resource}/:resource_id" do
12
+ json_response 200, "get_#{resource}_#{params[:resource_id]}.json"
13
+ end
14
+
15
+ put "/api/v1/#{resource}/:resource_id" do
16
+ json_response 204, "put_#{resource}_#{params[:resource_id]}.json"
17
+ end
18
+ end
19
+
20
+ get '/api/v1/courses/:course_id/assignments' do
21
+ json_response 200, "get_courses_#{params[:course_id]}_assignments.json"
22
+ end
23
+
24
+ put '/api/v1/courses/:course_id/assignments' do
25
+ json_response 204, "put_courses_#{params[:course_id]}_assignments.json"
26
+ end
27
+
28
+ private
29
+
30
+ def json_response(response_code, file_name)
31
+ content_type :json
32
+ status response_code
33
+ File.open(File.dirname(__FILE__) + '/fixtures/' + file_name, 'rb').read
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ {
2
+ "type":"courses",
3
+ "courses":[
4
+ {
5
+ "id":1,
6
+ "title":"HIPAA Basic"
7
+ },
8
+ {
9
+ "id":2,
10
+ "title":"HIPAA Advanced"
11
+ },
12
+ {
13
+ "id":3,
14
+ "title":"HIPAA for Security Officers"
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "type":"course",
3
+ "id":1,
4
+ "title":"HIPAA Advanced",
5
+ "assignees_count":4,
6
+ "completed_count":0,
7
+ "description":"Advanced HIPAA training for software developers.",
8
+ "lessons":[
9
+ {
10
+ "id":1,
11
+ "title":"Basic HIPAA Lesson",
12
+ "assignees_count":0,
13
+ "completed_count":0
14
+ },
15
+ {
16
+ "id":2,
17
+ "title":"Advanced HIPAA Lesson",
18
+ "assignees_count":0,
19
+ "completed_count":0
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "type":"update_course_assignments",
3
+ "assignments":[
4
+ {
5
+ "id": 1,
6
+ "assignee_id": 1,
7
+ "due_by": "09/30/2020",
8
+ "reassigned_at": "09/30/2020",
9
+ "completed_at": null,
10
+ "status": "Incomplete",
11
+ "score": 0
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "type":"groups",
3
+ "groups":[
4
+ {
5
+ "id":1,
6
+ "name":"Developers"
7
+ }
8
+ ]
9
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "type":"group",
3
+ "id":1,
4
+ "name":"Developers",
5
+ "members":[
6
+ {
7
+ "id":1,
8
+ "name":"Chas Ballew"
9
+ },
10
+ {
11
+ "id":2,
12
+ "name":"Skylar Anderson"
13
+ }
14
+ ],
15
+ "managers":[
16
+
17
+ ]
18
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "type":"users",
3
+ "users":[
4
+ {
5
+ "id":3,
6
+ "name":"Learner Smith",
7
+ "email":"learner@aptible.com",
8
+ "role":"learner"
9
+ },
10
+ {
11
+ "id":2,
12
+ "name":"Skylar Anderson",
13
+ "email":"skylar@aptible.com",
14
+ "role":"admin"
15
+ },
16
+ {
17
+ "id":1,
18
+ "name":"Chas Ballew",
19
+ "email":"chas@aptible.com",
20
+ "role":"admin"
21
+ }
22
+ ],
23
+ "total_users":3,
24
+ "total_pages":1,
25
+ "page":1,
26
+ "per_page":50
27
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "type": "user",
3
+ "id": 1,
4
+ "email": "chas@aptible.com",
5
+ "name": "Chas Ballew",
6
+ "role": "admin",
7
+ "custom_user_field_data": [ ]
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "type": "user",
3
+ "id": 3,
4
+ "email": "learner@aptible.com",
5
+ "name": "Learner Smith",
6
+ "role": "learner",
7
+ "custom_user_field_data": [ ]
8
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "type":"update_course_assignments",
3
+ "assignments":[
4
+ {
5
+ "id": 1,
6
+ "assignee_id": 1,
7
+ "due_by": "09/30/2020",
8
+ "reassigned_at": "09/30/2020",
9
+ "completed_at": null,
10
+ "status": "Incomplete",
11
+ "score": 0
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "type":"group",
3
+ "id":1,
4
+ "name":"Developers",
5
+ "members":[
6
+ {
7
+ "id":1,
8
+ "name":"Chas Ballew"
9
+ },
10
+ {
11
+ "id":2,
12
+ "name":"Skylar Anderson"
13
+ }
14
+ {
15
+ "id":3,
16
+ "name":"Learner Smith"
17
+ }
18
+ ],
19
+ "managers":[
20
+
21
+ ]
22
+ }
data/spec/user_spec.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lessonly::User do
4
+ context '#all' do
5
+ it 'should return all users' do
6
+ users = Lessonly::User.all
7
+ expect(users.count).to eq 3
8
+ end
9
+ end
10
+
11
+ context '#find' do
12
+ it 'should find a single user' do
13
+ user = Lessonly::User.find(1)
14
+ expect(user.name).to eq 'Chas Ballew'
15
+ end
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,236 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lessonly-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Skylar Anderson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gem_config
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sawyer
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.5.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 0.5.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: aptible-tasks
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
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
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: sinatra
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: Ruby client for Lesson.ly API
154
+ email:
155
+ - skylar@aptible.com
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - .gitignore
161
+ - .rspec
162
+ - .travis.yml
163
+ - Gemfile
164
+ - LICENSE.md
165
+ - Procfile
166
+ - README.md
167
+ - Rakefile
168
+ - lessonly-ruby.gemspec
169
+ - lib/lessonly.rb
170
+ - lib/lessonly/client.rb
171
+ - lib/lessonly/defaults.rb
172
+ - lib/lessonly/exceptions.rb
173
+ - lib/lessonly/resource.rb
174
+ - lib/lessonly/resource/assignment.rb
175
+ - lib/lessonly/resource/course.rb
176
+ - lib/lessonly/resource/group.rb
177
+ - lib/lessonly/resource/lesson.rb
178
+ - lib/lessonly/resource/user.rb
179
+ - lib/lessonly/response.rb
180
+ - lib/lessonly/serializer.rb
181
+ - lib/lessonly/version.rb
182
+ - spec/course_spec.rb
183
+ - spec/group_spec.rb
184
+ - spec/spec_helper.rb
185
+ - spec/support/fake_lessonly.rb
186
+ - spec/support/fixtures/get_courses.json
187
+ - spec/support/fixtures/get_courses_1.json
188
+ - spec/support/fixtures/get_courses_1_assignments.json
189
+ - spec/support/fixtures/get_groups.json
190
+ - spec/support/fixtures/get_groups_1.json
191
+ - spec/support/fixtures/get_users.json
192
+ - spec/support/fixtures/get_users_1.json
193
+ - spec/support/fixtures/get_users_3.json
194
+ - spec/support/fixtures/put_courses_1_assignments.json
195
+ - spec/support/fixtures/put_groups_1.json
196
+ - spec/user_spec.rb
197
+ homepage: https://github.com/aptible/lessonly-ruby
198
+ licenses:
199
+ - MIT
200
+ metadata: {}
201
+ post_install_message:
202
+ rdoc_options: []
203
+ require_paths:
204
+ - lib
205
+ required_ruby_version: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - '>='
208
+ - !ruby/object:Gem::Version
209
+ version: '0'
210
+ required_rubygems_version: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - '>='
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ requirements: []
216
+ rubyforge_project:
217
+ rubygems_version: 2.2.2
218
+ signing_key:
219
+ specification_version: 4
220
+ summary: Ruby client for Lesson.ly API
221
+ test_files:
222
+ - spec/course_spec.rb
223
+ - spec/group_spec.rb
224
+ - spec/spec_helper.rb
225
+ - spec/support/fake_lessonly.rb
226
+ - spec/support/fixtures/get_courses.json
227
+ - spec/support/fixtures/get_courses_1.json
228
+ - spec/support/fixtures/get_courses_1_assignments.json
229
+ - spec/support/fixtures/get_groups.json
230
+ - spec/support/fixtures/get_groups_1.json
231
+ - spec/support/fixtures/get_users.json
232
+ - spec/support/fixtures/get_users_1.json
233
+ - spec/support/fixtures/get_users_3.json
234
+ - spec/support/fixtures/put_courses_1_assignments.json
235
+ - spec/support/fixtures/put_groups_1.json
236
+ - spec/user_spec.rb