lessonly-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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