pupilfirst_xapi 0.1.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99a6dddb084209a85ef5d3f6ad55cf489fb50cf21b0a1f1c1e01a392079a13e9
4
- data.tar.gz: bff106abc8d633185bda3b156203ad901ae0beff5fdb544051014a462405fd67
3
+ metadata.gz: bdb9ed6c9957df10e29f9f8fac0d5a303ac6ed5f962d78bb27af84be1255f61d
4
+ data.tar.gz: 361c1a5767d137ee50a99a191bb9906b1ca295bf6074e2c3568b80a5cf5121ce
5
5
  SHA512:
6
- metadata.gz: b41c20f2967044b42d4d3f11c5307a5970e680f8313d200a91e98e948f0e7ae8053793c976d091372d78eb3a9ede6da505d0253265cd588c51707d355fe26ad5
7
- data.tar.gz: 8a526960635e5065792c221140153834f5eb3f01ab5ef66b221369b034e18510f094e972637702052a2a7a7bfe506fe1762838cf39d3f98a558b7878abf1d2f0
6
+ metadata.gz: ab2a1cba32a1cdc99afeabb7bffc99b022a695989817ac8fe27e7f11894635dedc7befa6a88308af5660ddae6cf9aec8a4d97270bf45e9fb17263eb710d8aa61
7
+ data.tar.gz: e58f22380039a0235534988affdaaa4f01b208b83e43857908d62e20c17d636b548b9a8da96a616e0bb9d1ed03a77b5627488d5c3d0e0bf8e560d658bcc2d24b
@@ -2,6 +2,7 @@ require "action_controller/railtie"
2
2
  require "active_job/railtie"
3
3
  require "growthtribe_xapi"
4
4
  require "pupilfirst_xapi/version"
5
+ require "pupilfirst_xapi/lrs"
5
6
  require "pupilfirst_xapi/outbox"
6
7
  require "pupilfirst_xapi/actors"
7
8
  require "pupilfirst_xapi/objects"
@@ -11,6 +12,7 @@ require "pupilfirst_xapi/statements"
11
12
  module PupilfirstXapi
12
13
  mattr_accessor :uri_for
13
14
  mattr_accessor :repository
15
+ mattr_accessor :lrs
14
16
 
15
17
  Statements.subscribe do |event_type|
16
18
  ActiveSupport::Notifications.subscribe("#{event_type}.pupilfirst") do |_name, _start, finish, _id, payload|
@@ -0,0 +1,24 @@
1
+ require 'xapi'
2
+
3
+ module PupilfirstXapi
4
+ class Lrs
5
+ def initialize(
6
+ end_point: ENV['LRS_ENDPOINT'],
7
+ key: ENV['LRS_KEY'],
8
+ secret: ENV['LRS_SECRET']
9
+ )
10
+ @lrs = end_point && key && secret &&
11
+ Xapi.create_remote_lrs(
12
+ end_point: end_point,
13
+ user_name: key,
14
+ password: secret
15
+ )
16
+ end
17
+
18
+ def call(statement)
19
+ return unless statement && @lrs
20
+
21
+ Xapi.post_statement(remote_lrs: @lrs, statement: statement)
22
+ end
23
+ end
24
+ end
@@ -4,12 +4,12 @@ require_relative 'objects/target'
4
4
 
5
5
  module PupilfirstXapi
6
6
  module Objects
7
- def self.course(course, uri)
8
- Course.new.call(course, uri)
7
+ def self.course(course, uri_for)
8
+ Course.new.call(course, uri_for)
9
9
  end
10
10
 
11
- def self.target(target, uri)
12
- Target.new.call(target, uri)
11
+ def self.target(target, uri_for)
12
+ Target.new.call(target, uri_for)
13
13
  end
14
14
  end
15
15
  end
@@ -1,13 +1,16 @@
1
1
  module PupilfirstXapi
2
2
  module Objects
3
3
  class Course
4
- def call(course, uri)
4
+ def call(course, uri_for)
5
+ uri = uri_for.call(course)
6
+
5
7
  Builder.new(
6
8
  id: uri,
7
9
  type: 'http://adlnet.gov/expapi/activities/product',
8
10
  name: course.name,
9
11
  description: course.description
10
12
  ).tap do |obj|
13
+ obj.with_extension('http://id.tincanapi.com/extension/ending-position', course.targets.count)
11
14
  if course.ends_at.present?
12
15
  duration = ActiveSupport::Duration.build(course.ends_at - course.created_at).iso8601
13
16
  obj.with_extension("http://id.tincanapi.com/extension/planned-duration", duration)
@@ -1,13 +1,19 @@
1
1
  module PupilfirstXapi
2
2
  module Objects
3
3
  class Target
4
- def call(target, uri)
4
+ def call(target, uri_for)
5
+ course = target.course
6
+ target_uri = uri_for.call(target)
7
+
5
8
  Builder.new(
6
- id: uri,
9
+ id: target_uri,
7
10
  type: "http://activitystrea.ms/schema/1.0/task",
8
11
  name: target.title,
9
12
  description: target.description
10
- ).call
13
+ ).tap do |obj|
14
+ obj.with_extension('http://id.tincanapi.com/extension/host', Objects.course(course, uri_for).as_json)
15
+ obj.with_extension('http://id.tincanapi.com/extension/position', target.sort_index)
16
+ end.call
11
17
  end
12
18
  end
13
19
  end
@@ -1,5 +1,4 @@
1
1
  require "active_job"
2
- require 'xapi'
3
2
 
4
3
  module PupilfirstXapi
5
4
  class Outbox
@@ -14,19 +13,11 @@ module PupilfirstXapi
14
13
 
15
14
  def outbox
16
15
  Outbox.new(
17
- lrs: remote_lrs,
16
+ lrs: PupilfirstXapi.lrs || PupilfirstXapi::Lrs.new,
18
17
  repository: PupilfirstXapi.repository,
19
18
  uri_for: PupilfirstXapi.uri_for
20
19
  )
21
20
  end
22
-
23
- def remote_lrs
24
- Xapi.create_remote_lrs(
25
- end_point: ENV['LRS_ENDPOINT'],
26
- user_name: ENV['LRS_KEY'],
27
- password: ENV['LRS_SECRET']
28
- )
29
- end
30
21
  end
31
22
 
32
23
  class << self
@@ -42,8 +33,7 @@ module PupilfirstXapi
42
33
  end
43
34
 
44
35
  def call(**payload)
45
- statement = statement_for(**payload)
46
- Xapi.post_statement(remote_lrs: @lrs, statement: statement) if statement
36
+ @lrs.call(statement_for(**payload))
47
37
  end
48
38
 
49
39
  private
@@ -13,7 +13,7 @@ module PupilfirstXapi
13
13
  Xapi.create_statement(
14
14
  actor: Actors.agent(actor),
15
15
  verb: Verbs::COMPLETED,
16
- object: Objects.course(course, @uri_for.call(course))
16
+ object: Objects.course(course, @uri_for)
17
17
  )
18
18
  end
19
19
  end
@@ -13,7 +13,7 @@ module PupilfirstXapi
13
13
  Xapi.create_statement(
14
14
  actor: Actors.agent(actor),
15
15
  verb: Verbs::REGISTERED,
16
- object: Objects.course(course, @uri_for.call(course))
16
+ object: Objects.course(course, @uri_for)
17
17
  )
18
18
  end
19
19
  end
@@ -16,7 +16,7 @@ module PupilfirstXapi
16
16
  Xapi.create_statement(
17
17
  actor: Actors.agent(actor),
18
18
  verb: Verbs::COMPLETED_ASSIGNMENT,
19
- object: Objects.target(target, @uri_for.call(target))
19
+ object: Objects.target(target, @uri_for)
20
20
  )
21
21
  end
22
22
  end
@@ -1,3 +1,3 @@
1
1
  module PupilfirstXapi
2
- VERSION = '0.1.0'
2
+ VERSION = '0.3.2'
3
3
  end
@@ -15,13 +15,20 @@ RSpec.describe "#xapi", type: :job, perform_jobs: true do
15
15
  description: 'These guides are designed to make you immediately productive with Rails',
16
16
  created_at: Time.new(2021,01,01),
17
17
  ends_at: nil,
18
- uri: 'https://guides.rubyonrails.org/')
18
+ uri: 'https://guides.rubyonrails.org/',
19
+ targets: [
20
+ double(:target, title: '1st target', description: 'Seems easy'),
21
+ double(:target, title: '2nd target', description: 'Seems not easy')
22
+ ]
23
+ )
19
24
  }
20
25
  let(:getting_started) {
21
26
  double(:target,
22
27
  title: 'Getting Started with Rails',
23
28
  description: 'This guide covers getting up and running with Ruby on Rails.',
24
- uri: 'https://guides.rubyonrails.org/getting_started.html')
29
+ uri: 'https://guides.rubyonrails.org/getting_started.html',
30
+ course: ror_guides
31
+ )
25
32
  }
26
33
  let(:good_one) { double(:timeline_event, target: getting_started, passed?: true) }
27
34
  let(:bad_one) { double(:timeline_event, target: getting_started, passed?: false) }
@@ -75,6 +82,7 @@ RSpec.describe "#xapi", type: :job, perform_jobs: true do
75
82
  name: {'en-US' => 'Ruby on Rails Guides'},
76
83
  description: {'en-US' => 'These guides are designed to make you immediately productive with Rails'},
77
84
  type: 'http://adlnet.gov/expapi/activities/product',
85
+ extensions: {"http://id.tincanapi.com/extension/ending-position"=>2}
78
86
  },
79
87
  },
80
88
  timestamp: timestamp.iso8601,
@@ -88,7 +96,7 @@ RSpec.describe "#xapi", type: :job, perform_jobs: true do
88
96
  'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
89
97
  'Authorization'=>'Basic a2V5OnNlY3JldA==',
90
98
  'Content-Type'=>'application/json',
91
- 'User-Agent'=>'Faraday v1.3.0',
99
+ 'User-Agent'=>'Faraday v1.3.1',
92
100
  'X-Experience-Api-Version'=>'1.0.1'
93
101
  }
94
102
  ).to_return(status: 204, body: "", headers: {})
data/spec/outbox_spec.rb CHANGED
@@ -4,8 +4,8 @@ module PupilfirstXapi
4
4
  RSpec.describe Outbox do
5
5
  let(:timestamp) { Time.now }
6
6
  let(:john) { double(:john, name: 'John Doe', email: 'john@doe.com') }
7
- let(:course) { double(:course, name: 'Rails for Begginers', description: 'Seems easy', created_at: 1.week.ago, ends_at: nil) }
8
- let(:target) { double(:target, title: '1st target', description: 'Seems easy') }
7
+ let(:course) { double(:course, id: 32, name: 'Rails for Begginers', description: 'Seems easy', created_at: 1.week.ago, ends_at: nil, targets: []) }
8
+ let(:target) { double(:target, title: '1st target', description: 'Seems easy', course: course, sort_index: 7) }
9
9
  let(:good_one) { double(:timeline_event, target: target, passed?: true) }
10
10
  let(:bad_one) { double(:timeline_event, target: target, passed?: false) }
11
11
 
data/spec/spec_helper.rb CHANGED
@@ -50,7 +50,9 @@ class FakeLrs
50
50
  end
51
51
  attr_reader :statements
52
52
 
53
- def save_statement(statement)
53
+ def call(statement)
54
+ return unless statement
55
+
54
56
  @statements << statement
55
57
  end
56
58
  end
@@ -5,7 +5,11 @@ module PupilfirstXapi
5
5
  RSpec.describe CourseCompleted do
6
6
  it do
7
7
  john = double(:john, name: 'John Doe', email: 'john@doe.com')
8
- course = double(:course, name: 'Rails for Begginers', description: 'Seems easy', created_at: 1.week.ago, ends_at: nil)
8
+ course = double(:course, name: 'Rails for Begginers', description: 'Seems easy', created_at: 1.week.ago, ends_at: nil,
9
+ targets: [
10
+ double(:target, title: '1st target', description: 'Seems easy'),
11
+ double(:target, title: '2nd target', description: 'Seems not easy')
12
+ ])
9
13
  data = {
10
14
  course: { 456 => course },
11
15
  user: { 123 => john },
@@ -5,7 +5,11 @@ module PupilfirstXapi
5
5
  RSpec.describe CourseRegistered do
6
6
  it do
7
7
  john = double(:john, name: 'John Doe', email: 'john@doe.com')
8
- course = double(:course, name: 'Rails for Begginers', description: 'Seems easy', created_at: 1.week.ago, ends_at: nil)
8
+ course = double(:course, name: 'Rails for Begginers', description: 'Seems easy', created_at: 1.week.ago, ends_at: nil,
9
+ targets: [
10
+ double(:target, title: '1st target', description: 'Seems easy'),
11
+ double(:target, title: '2nd target', description: 'Seems not easy')
12
+ ])
9
13
  data = {
10
14
  course: { 456 => course },
11
15
  user: { 123 => john },
@@ -25,7 +29,9 @@ module PupilfirstXapi
25
29
  expect(xapi.object.definition.type).to eq 'http://adlnet.gov/expapi/activities/product'
26
30
  expect(xapi.object.definition.name).to eq({'en-US' => 'Rails for Begginers'})
27
31
  expect(xapi.object.definition.description).to eq({'en-US' => 'Seems easy'})
28
- expect(xapi.object.definition.extensions).to eq nil
32
+ expect(xapi.object.definition.extensions).to eq ({
33
+ "http://id.tincanapi.com/extension/ending-position" => 2
34
+ })
29
35
  end
30
36
 
31
37
  it do
@@ -34,7 +40,11 @@ module PupilfirstXapi
34
40
  duration = ActiveSupport::Duration.build(ends_at - starts_at).iso8601
35
41
 
36
42
  john = double(:john, name: 'John Doe', email: 'john@doe.com')
37
- course = double(:course, name: 'Rails for Begginers', description: 'Seems easy', created_at: starts_at, ends_at: ends_at)
43
+ course = double(:course, name: 'Rails for Begginers', description: 'Seems easy', created_at: starts_at, ends_at: ends_at,
44
+ targets: [
45
+ double(:target, title: '1st target', description: 'Seems easy'),
46
+ double(:target, title: '2nd target', description: 'Seems not easy')
47
+ ])
38
48
  data = {
39
49
  course: { 456 => course },
40
50
  user: { 123 => john },
@@ -54,7 +64,10 @@ module PupilfirstXapi
54
64
  expect(xapi.object.definition.type).to eq 'http://adlnet.gov/expapi/activities/product'
55
65
  expect(xapi.object.definition.name).to eq({'en-US' => 'Rails for Begginers'})
56
66
  expect(xapi.object.definition.description).to eq({'en-US' => 'Seems easy'})
57
- expect(xapi.object.definition.extensions).to eq({"http://id.tincanapi.com/extension/planned-duration" => duration})
67
+ expect(xapi.object.definition.extensions).to eq({
68
+ "http://id.tincanapi.com/extension/planned-duration" => duration,
69
+ "http://id.tincanapi.com/extension/ending-position" => 2
70
+ })
58
71
  end
59
72
  end
60
73
  end
@@ -4,7 +4,12 @@ module PupilfirstXapi
4
4
  module Statements
5
5
  RSpec.describe TargetCompleted do
6
6
  it do
7
- target = double(:target, title: '1st target', description: 'Seems easy')
7
+ course = double(:course, id: 17, name: 'Rails for Begginers', description: 'Seems easy', created_at: 1.week.ago, ends_at: nil,
8
+ targets: [
9
+ double(:target, title: '1st target', description: 'Seems easy'),
10
+ double(:target, title: '2nd target', description: 'Seems not easy')
11
+ ])
12
+ target = double(:target, title: '1st target', course: course, description: 'Seems easy', sort_index: 5)
8
13
  submission = double(:timeline_event, target: target, passed?: true)
9
14
  john = double(:john, name: 'John Doe', email: 'john@doe.com')
10
15
  data = {
@@ -12,7 +17,7 @@ module PupilfirstXapi
12
17
  user: { 123 => john },
13
18
  }
14
19
  repository = ->(klass, resource_id) { data.dig(klass, resource_id) }
15
- uri_for = ->(obj) { obj == target ? 'target-1' : nil }
20
+ uri_for = ->(obj) { obj == target ? 'target-1' : obj == course ? 'course-1' : nil }
16
21
 
17
22
  xapi = TargetCompleted.new(repository, uri_for).call(actor_id: 123, resource_id: 456)
18
23
 
@@ -26,10 +31,11 @@ module PupilfirstXapi
26
31
  expect(xapi.object.definition.type).to eq 'http://activitystrea.ms/schema/1.0/task'
27
32
  expect(xapi.object.definition.name).to eq({'en-US' => '1st target'})
28
33
  expect(xapi.object.definition.description).to eq({'en-US' => 'Seems easy'})
34
+ expect(xapi.object.definition.extensions['http://id.tincanapi.com/extension/host']['id']).to eq 'course-1'
29
35
  end
30
36
 
31
37
  it 'no-op when submission is not passed' do
32
- target = double(:target, title: '1st target', description: 'Seems easy')
38
+ target = double(:target, title: '1st target', description: 'Seems easy', sort_index: 3)
33
39
  submission = double(:timeline_event, target: target, passed?: false)
34
40
  john = double(:john, name: 'John Doe', email: 'john@doe.com')
35
41
  data = {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pupilfirst_xapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - GrowthTribe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-02 00:00:00.000000000 Z
11
+ date: 2021-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.0.1
39
+ version: 0.0.2
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: 0.0.1
46
+ version: 0.0.2
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec-rails
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -98,6 +98,7 @@ files:
98
98
  - Rakefile
99
99
  - lib/pupilfirst_xapi.rb
100
100
  - lib/pupilfirst_xapi/actors.rb
101
+ - lib/pupilfirst_xapi/lrs.rb
101
102
  - lib/pupilfirst_xapi/objects.rb
102
103
  - lib/pupilfirst_xapi/objects/builder.rb
103
104
  - lib/pupilfirst_xapi/objects/course.rb
@@ -116,7 +117,7 @@ files:
116
117
  - spec/rails_helper.rb
117
118
  - spec/spec_helper.rb
118
119
  - spec/statements/course_completed_spec.rb
119
- - spec/statements/course_redistered_spec.rb
120
+ - spec/statements/course_registered_spec.rb
120
121
  - spec/statements/target_completed_spec.rb
121
122
  homepage: https://github.com/growthtribeacademy/pupilfirst-xapi
122
123
  licenses:
@@ -152,5 +153,5 @@ test_files:
152
153
  - spec/rails_helper.rb
153
154
  - spec/spec_helper.rb
154
155
  - spec/statements/course_completed_spec.rb
155
- - spec/statements/course_redistered_spec.rb
156
+ - spec/statements/course_registered_spec.rb
156
157
  - spec/statements/target_completed_spec.rb