meducation_sdk 1.5.7 → 1.6.0

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,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 59cdaa5f76cdde2eb332690eda73a06fc48f7679
4
- data.tar.gz: 954e3a4ecf08267207ccea0751c0896d719bf8f6
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NGJlOWVmZDZhOTE1NDRhY2M5ODcyYzgzYTE0ZDVkNWY1NDJkYTZiYw==
5
+ data.tar.gz: !binary |-
6
+ ZjI3NzAzODg0YzExMzA5ZTczZGMwYmY0ZTZkMzViMDM5NjYyYTdlZA==
5
7
  SHA512:
6
- metadata.gz: 1e5e383e3455c0109d8399762c5dcf73deedbfa7e234a0e18913c2caeb702fe5c2a0a116a2e40116ebc022bf55a8c946f35436b4ca3b378f40a5d22cc6beca6b
7
- data.tar.gz: 6e468ec9dfe67820d6857ead5038651b2985024d5e2d9969030dd53ce00169bce7a101f40ebfca5413ba6c4c3f7317d84cf11c6c4f0d396c2048844c88059fc3
8
+ metadata.gz: !binary |-
9
+ M2ZhNTUyMjZmMzU2NDMyYTZkYWMzZjQ3MzcwN2FkYWI3NGJkOTMwODI0N2I4
10
+ ZDliZWFmMGE2MzMxMzJiNjdkZTdhNWEzNjhkZjlhODNiZDVlYzMyMjAxZWNl
11
+ ZDUwODc2NzkwMGRhMzgwNjczMDNkMTBjODBiZTY1YTIyMjM2Mzg=
12
+ data.tar.gz: !binary |-
13
+ NzNhYjJhYTNjYTFjNTMyZWY0NTMxMGM3OTI0ZDVlMGZiN2RhNDM4NjJkNjA2
14
+ M2RiMGUwYWIzYzE5NGUyNTEyZjRkZWIxZmIyOTQwOWUxZTZiNDJiMGMyNWZl
15
+ NmUyYTVlNDFlNmU5Y2QzOTRmNjgwYmM3MWZiNDcxOGJhYWYwNDE=
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
- # 1.5.7 / 2014-03-4
1
+ # 1.6.0 / 2014-03-07
2
+ * [FEATURE] Add recommender
3
+ * [FEATURE] Change routing to spi.meducation.net
4
+
5
+ # 1.5.7 / 2014-03-04
2
6
  * [FEATURE] Add authors to to collection topics
3
7
 
4
8
  # 1.5.6 / 2014-02-27
@@ -5,62 +5,9 @@ require "meducation_sdk/version"
5
5
  require "meducation_sdk/configuration"
6
6
  require "meducation_sdk/mocker"
7
7
 
8
+ require "meducation_sdk/helpers"
9
+ require "meducation_sdk/services/recommender"
8
10
  require "meducation_sdk/resource"
9
- require "meducation_sdk/resources/badges/badge"
10
-
11
- RESOURCES = %w{
12
- author
13
- badges/answerer_badge
14
- badges/befriender_badge
15
- badges/citizen_badge
16
- badges/commentator_badge
17
- badges/community_member_badge
18
- badges/contributor_badge
19
- badges/eminent_author_badge
20
- badges/enlightener_badge
21
- badges/inquisitive_mind_badge
22
- badges/photogenic_badge
23
- badges/questioner_badge
24
- badges/respected_author_badge
25
- blog_post
26
- blogger
27
- board
28
- board_follow
29
- board_item
30
- collection
31
- collection_section
32
- collection_topic
33
- comment
34
- community
35
- community_membership
36
- dashboard_item
37
- ecommerce_subscription
38
- external_resource
39
- friendship
40
- group
41
- group_discussion
42
- group_discussion_post
43
- group_invite
44
- group_membership
45
- knowledge_bank_question
46
- knowledge_bank_answer
47
- media_file
48
- mesh_heading
49
- message
50
- message_thread
51
- message_thread_contributor
52
- mnemonic
53
- notification
54
- partner
55
- syllabus_item
56
- user
57
- user_email_data
58
- user_settings
59
- vote
60
- }
61
- RESOURCES.each do |resource|
62
- require "meducation_sdk/resources/#{resource}"
63
- end
64
11
 
65
12
  module MeducationSDK
66
13
  def self.config
@@ -6,7 +6,10 @@ module MeducationSDK
6
6
 
7
7
  class Configuration
8
8
 
9
- SETTINGS = [ :logger ]
9
+ SETTINGS = [
10
+ :logger,
11
+ :recommender_host, :recommender_port
12
+ ]
10
13
 
11
14
  attr_writer *SETTINGS
12
15
 
@@ -14,11 +17,14 @@ module MeducationSDK
14
17
  self.logger = Filum.logger
15
18
 
16
19
  Loquor.config do |config|
17
- config.endpoint = "http://www.meducation.net/system"
20
+ config.endpoint = "http://spi.meducation.net"
18
21
  config.substitute_values[true] = ":__true__"
19
22
  config.substitute_values[false] = ":__false__"
20
23
  config.retry_404s = true
21
24
  end
25
+
26
+ self.recommender_host = "recommender.meducation.net"
27
+ self.recommender_port = 4567
22
28
  end
23
29
 
24
30
  [:access_id, :secret_key, :endpoint, :cache].each do |setting|
@@ -0,0 +1,26 @@
1
+ module MeducationSDK
2
+ module Helpers
3
+ SDK_TO_SPI_MAPPINGS = {}
4
+
5
+ def sdk_class_for(spi_type)
6
+ sdk_type_for(spi_type).constantize
7
+ end
8
+
9
+ def sdk_type_for(spi_type)
10
+ if SDK_TO_SPI_MAPPINGS.has_value?(spi_type)
11
+ SDK_TO_SPI_MAPPINGS.key(spi_type)
12
+ else
13
+ "MeducationSDK::#{spi_type.gsub("::", "")}"
14
+ end
15
+ end
16
+
17
+ def spi_type_for(sdk_type)
18
+ if SDK_TO_SPI_MAPPINGS.has_key?(sdk_type)
19
+ SDK_TO_SPI_MAPPINGS[sdk_type]
20
+ else
21
+ sdk_type.gsub("MeducationSDK::", "")
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -1,5 +1,11 @@
1
1
  module MeducationSDK
2
2
  class Resource < Loquor::Resource
3
+ include Helpers
4
+
5
+ def self.spi_type=(type)
6
+ Helpers::SDK_TO_SPI_MAPPINGS[self.name] = type
7
+ end
8
+
3
9
  def created_at
4
10
  DateTime.parse(@data[:created_at])
5
11
  end
@@ -7,14 +13,61 @@ module MeducationSDK
7
13
  def updated_at
8
14
  DateTime.parse(@data[:updated_at])
9
15
  end
10
-
11
- def class_for(meducation_type)
12
- case meducation_type
13
- when "Item::Comment"
14
- Comment
15
- else
16
- "MeducationSDK::#{meducation_type.gsub("::", "")}".constantize
17
- end
18
- end
19
16
  end
20
17
  end
18
+
19
+ RESOURCES = %w{
20
+ author
21
+ badges/answerer_badge
22
+ badges/befriender_badge
23
+ badges/citizen_badge
24
+ badges/commentator_badge
25
+ badges/community_member_badge
26
+ badges/contributor_badge
27
+ badges/eminent_author_badge
28
+ badges/enlightener_badge
29
+ badges/inquisitive_mind_badge
30
+ badges/photogenic_badge
31
+ badges/questioner_badge
32
+ badges/respected_author_badge
33
+ blog_post
34
+ blogger
35
+ board
36
+ board_follow
37
+ board_item
38
+ collection
39
+ collection_section
40
+ collection_topic
41
+ comment
42
+ community
43
+ community_membership
44
+ dashboard_item
45
+ ecommerce_subscription
46
+ external_resource
47
+ friendship
48
+ group
49
+ group_discussion
50
+ group_discussion_post
51
+ group_invite
52
+ group_membership
53
+ knowledge_bank_question
54
+ knowledge_bank_answer
55
+ media_file
56
+ mesh_heading
57
+ message
58
+ message_thread
59
+ message_thread_contributor
60
+ mnemonic
61
+ notification
62
+ partner
63
+ syllabus_item
64
+ user
65
+ user_email_data
66
+ user_settings
67
+ vote
68
+ }
69
+
70
+ require "meducation_sdk/resources/badges/badge"
71
+ RESOURCES.each do |resource|
72
+ require "meducation_sdk/resources/#{resource}"
73
+ end
@@ -3,7 +3,7 @@ module MeducationSDK
3
3
  self.path = "/boards"
4
4
 
5
5
  def owner
6
- @owner ||= class_for(owner_type).find(owner_id)
6
+ @owner ||= sdk_class_for(owner_type).find(owner_id)
7
7
  end
8
8
 
9
9
  def created_by
@@ -3,7 +3,7 @@ module MeducationSDK
3
3
  self.path = "/board_items"
4
4
 
5
5
  def item
6
- @item ||= class_for(item_type).find(item_id)
6
+ @item ||= sdk_class_for(item_type).find(item_id)
7
7
  end
8
8
 
9
9
  def board
@@ -1,9 +1,10 @@
1
1
  module MeducationSDK
2
2
  class Comment < Resource
3
3
  self.path = "/comments"
4
+ self.spi_type = "Item::Comment"
4
5
 
5
6
  def item
6
- @item ||= class_for(item_type).find(item_id)
7
+ @item ||= sdk_class_for(item_type).find(item_id)
7
8
  end
8
9
 
9
10
  def user
@@ -7,7 +7,7 @@ module MeducationSDK
7
7
  end
8
8
 
9
9
  def item
10
- @item ||= class_for(item_type).find(item_id)
10
+ @item ||= sdk_class_for(item_type).find(item_id)
11
11
  end
12
12
  end
13
13
 
@@ -1,6 +1,7 @@
1
1
  module MeducationSDK
2
2
  class KnowledgeBankQuestion < Resource
3
3
  self.path = "/knowledge_bank_questions"
4
+ self.spi_type = "KnowledgeBank::Question"
4
5
 
5
6
  def user
6
7
  @user = User.find(user_id)
@@ -3,7 +3,7 @@ module MeducationSDK
3
3
  self.path = "/notifications"
4
4
 
5
5
  def item
6
- @item ||= class_for(item_type).find(item_id)
6
+ @item ||= sdk_class_for(item_type).find(item_id)
7
7
  end
8
8
 
9
9
  def user
@@ -1,9 +1,10 @@
1
1
  module MeducationSDK
2
2
  class Vote < Resource
3
3
  self.path = "/votes"
4
+ self.spi_type = "Item::Vote"
4
5
 
5
6
  def item
6
- @item ||= class_for(item_type).find(item_id)
7
+ @item ||= sdk_class_for(item_type).find(item_id)
7
8
  end
8
9
 
9
10
  def user
@@ -0,0 +1,70 @@
1
+ module MeducationSDK
2
+ class Recommender
3
+ include Helpers
4
+
5
+ def self.recommend(item, options = {})
6
+ new(item, options).recommend
7
+ end
8
+
9
+ attr_reader :item
10
+ def initialize(item, options = {})
11
+ @item = item
12
+ @options = options
13
+ end
14
+
15
+ def recommend
16
+ generate_recommendations
17
+ rescue => e
18
+ log_error("!!Recommender Error!!")
19
+ log_error(e.message)
20
+ log_error(e.backtrace)
21
+ #Item::Recommendation.where(item_type: @item.class.name).where(item_id: @item.id).includes(:recommendation).map(&:recommendation)
22
+ []
23
+ end
24
+
25
+ def generate_recommendations
26
+ groupings = {}
27
+ correct_order = recommender_results.map do |result|
28
+ groupings[result['type']] ||= []
29
+ groupings[result['type']] << result['id']
30
+ "#{result['type']}##{result['id']}"
31
+ end
32
+
33
+ output = groupings.map {|(type, ids)| sdk_class_for(type).where(id: ids) }.flatten
34
+ output.sort_by!{ |item| correct_order.index("#{item.class.name}##{item.id}") }
35
+ output
36
+ end
37
+
38
+ def recommender_results
39
+ @recommender_results ||= begin
40
+ results = JSON.parse(recommender_json)
41
+ if @options[:limit]
42
+ results[0..(@options[:limit] - 1)]
43
+ else
44
+ results
45
+ end
46
+ end
47
+ end
48
+
49
+ def recommender_json
50
+ path = "/#{spi_type_for(item.class.name)}/#{item.id}"
51
+ log "Calling #{config.recommender_host}:#{config.recommender_host}#{path}"
52
+ response = Net::HTTP.get_response(config.recommender_host, path, config.recommender_port)
53
+ body = response.body
54
+ log "Received #{body}"
55
+ body
56
+ end
57
+
58
+ def log(*args)
59
+ config.logger.info(*args)
60
+ end
61
+
62
+ def log_error(*args)
63
+ config.logger.error(*args)
64
+ end
65
+
66
+ def config
67
+ MeducationSDK.config
68
+ end
69
+ end
70
+ end
@@ -1,3 +1,3 @@
1
1
  module MeducationSDK
2
- VERSION = "1.5.7"
2
+ VERSION = "1.6.0"
3
3
  end
@@ -22,10 +22,10 @@ module MeducationSDK
22
22
 
23
23
  def test_endpoint_is_set_correctly
24
24
  Configuration.new
25
- assert_equal "http://www.meducation.net/system", Loquor.config.endpoint
25
+ assert_equal "http://spi.meducation.net", Loquor.config.endpoint
26
26
  end
27
27
 
28
- def test_endpoint_is_set_correctly
28
+ def test_retry_404s_is_set_correctly
29
29
  Configuration.new
30
30
  assert_equal true, Loquor.config.retry_404s
31
31
  end
@@ -0,0 +1,23 @@
1
+ require_relative 'test_helper'
2
+ module MeducationSDK
3
+ class HelperTestClass
4
+ include Helpers
5
+ end
6
+
7
+ class HelpersTest < Minitest::Test
8
+ {
9
+ "Item::Comment" => "MeducationSDK::Comment",
10
+ "KnowledgeBank::Question" => "MeducationSDK::KnowledgeBankQuestion"
11
+ }.each do |spi_type, sdk_type|
12
+ define_method "test_sdk_type_for_#{spi_type.underscore.gsub("/", "_")}" do
13
+ assert_equal sdk_type, HelperTestClass.new.sdk_type_for(spi_type)
14
+ end
15
+ define_method "test_sdk_class_for_#{spi_type.underscore.gsub("/", "_")}" do
16
+ assert_equal sdk_type.constantize, HelperTestClass.new.sdk_class_for(spi_type)
17
+ end
18
+ define_method "test_spi_type_for_#{spi_type.underscore.gsub("/", "_")}" do
19
+ assert_equal spi_type, HelperTestClass.new.spi_type_for(sdk_type)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -17,15 +17,8 @@ module MeducationSDK
17
17
  end
18
18
  end
19
19
  end
20
-
21
- {
22
- "Item::Comment" => Comment,
23
- "KnowledgeBank::Question" => KnowledgeBankQuestion
24
- }.each do |meducation_type, sdk_class|
25
- define_method "test_class_for_#{meducation_type.underscore.gsub("/", "_")}" do
26
- r = Resource.new({})
27
- assert_equal sdk_class, r.class_for(meducation_type)
28
- end
20
+ define_method "test_helpers_included" do
21
+ assert Resource.new({}).respond_to?(:sdk_class_for)
29
22
  end
30
23
 
31
24
  def test_created_at_is_a_datetime
@@ -0,0 +1,72 @@
1
+ require_relative '../test_helper'
2
+
3
+ module MeducationSDK
4
+ class RecommenderTest < Minitest::Test
5
+
6
+ def empty_response
7
+ mock(body: '[]')
8
+ end
9
+
10
+ def item
11
+ @item ||= MediaFile.new({id: 10})
12
+ end
13
+
14
+ def item2
15
+ @item2 ||= MediaFile.new({id: 56})
16
+ end
17
+
18
+ def test_should_call_new
19
+ Recommender.expects(:new).with(item, {}).returns(mock(recommend: nil))
20
+ Recommender.recommend(item)
21
+ end
22
+
23
+ def test_should_proxy_to_recommend
24
+ Recommender.any_instance.expects(:recommend)
25
+ Recommender.recommend(nil)
26
+ end
27
+
28
+ def test_should_call_the_recommender_service
29
+ Net::HTTP.expects(:get_response).with("recommender.meducation.net", "/MediaFile/#{item.id}", 4567).returns(empty_response)
30
+ Recommender.new(item).recommend
31
+ end
32
+
33
+ def test_should_call_parse_results_of_recommendation_service
34
+ json = [
35
+ {"type" => "MediaFile", "id" => item.id, "score" => 0.0097},
36
+ {"type" => "MediaFile", "id" => item2.id, "score" => 0.0078}
37
+ ].to_json
38
+
39
+ Net::HTTP.expects(:get_response).returns(mock(body: json))
40
+ MediaFile.expects(:where).with({id: [item.id, item2.id]}).returns([item, item2])
41
+ items = Recommender.new(item).recommend
42
+ assert_equal [item, item2], items
43
+ end
44
+
45
+ def test_should_limit_correctly
46
+ items = 6.times.map { |x| MediaFile.new({id: x}) }
47
+ json = items.map {|item| {"type" => "MediaFile", "id" => item.id, "score" => 0.0097} }.to_json
48
+
49
+ Net::HTTP.expects(:get_response).returns(mock(body: json))
50
+ MediaFile.expects(:where).with({id: items[0..2].map(&:id)}).returns(items[0..2])
51
+ results = Recommender.new(item, limit: 3).recommend
52
+ end
53
+
54
+ def test_should_log_an_exception
55
+ Net::HTTP.expects(:get_response).raises(StandardError)
56
+ MeducationSDK.config.logger.expects(:error).with("!!Recommender Error!!")
57
+ MeducationSDK.config.logger.expects(:error).with("StandardError")
58
+ Recommender.new(item).recommend
59
+ end
60
+
61
+ def test_should_catch_an_exception_and_render_backup_recommendations
62
+ skip
63
+ recommendation = Item::Recommendation.create!(
64
+ item_type: item.class.name, item_id: item.id, jaccard_similarity: 1,
65
+ recommendation_type: item2.class.name, recommendation_id: item2.id
66
+ )
67
+ Net::HTTP.expects(:get_response).raises(StandardError)
68
+ items = Recommender.new(item).recommend
69
+ assert_equal [item2], items
70
+ end
71
+ end
72
+ end
data/test/test_helper.rb CHANGED
@@ -23,7 +23,7 @@ class Minitest::Test
23
23
  config.logger = MeducationSDK.config.logger
24
24
  config.access_id = "Sermo"
25
25
  config.secret_key = "foobar"
26
- config.endpoint = "http://localhost:3000/system"
26
+ config.endpoint = "http://localhost:3000/spi"
27
27
  end
28
28
  end
29
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meducation_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.7
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-04 00:00:00.000000000 Z
11
+ date: 2014-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -70,14 +70,14 @@ dependencies:
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ! '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ! '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
@@ -98,14 +98,14 @@ dependencies:
98
98
  name: mocha
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ! '>='
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ! '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  description: Meducation's SDK
@@ -125,6 +125,7 @@ files:
125
125
  - Rakefile
126
126
  - lib/meducation_sdk.rb
127
127
  - lib/meducation_sdk/configuration.rb
128
+ - lib/meducation_sdk/helpers.rb
128
129
  - lib/meducation_sdk/mocker.rb
129
130
  - lib/meducation_sdk/resource.rb
130
131
  - lib/meducation_sdk/resources/author.rb
@@ -176,10 +177,12 @@ files:
176
177
  - lib/meducation_sdk/resources/user_email_data.rb
177
178
  - lib/meducation_sdk/resources/user_settings.rb
178
179
  - lib/meducation_sdk/resources/vote.rb
180
+ - lib/meducation_sdk/services/recommender.rb
179
181
  - lib/meducation_sdk/version.rb
180
182
  - meducation_sdk.gemspec
181
183
  - test/arbitary_test.rb
182
184
  - test/configuration_test.rb
185
+ - test/helpers_test.rb
183
186
  - test/mocker_test.rb
184
187
  - test/resource_test.rb
185
188
  - test/resources/author_test.rb
@@ -231,6 +234,7 @@ files:
231
234
  - test/resources/user_settings_test.rb
232
235
  - test/resources/user_test.rb
233
236
  - test/resources/vote_test.rb
237
+ - test/services/recommender_test.rb
234
238
  - test/test_helper.rb
235
239
  homepage: http://github.com/meducation/meducation_sdk
236
240
  licenses:
@@ -242,23 +246,24 @@ require_paths:
242
246
  - lib
243
247
  required_ruby_version: !ruby/object:Gem::Requirement
244
248
  requirements:
245
- - - '>='
249
+ - - ! '>='
246
250
  - !ruby/object:Gem::Version
247
251
  version: '0'
248
252
  required_rubygems_version: !ruby/object:Gem::Requirement
249
253
  requirements:
250
- - - '>='
254
+ - - ! '>='
251
255
  - !ruby/object:Gem::Version
252
256
  version: '0'
253
257
  requirements: []
254
258
  rubyforge_project:
255
- rubygems_version: 2.2.1
259
+ rubygems_version: 2.1.9
256
260
  signing_key:
257
261
  specification_version: 4
258
262
  summary: The SDK for Meducation
259
263
  test_files:
260
264
  - test/arbitary_test.rb
261
265
  - test/configuration_test.rb
266
+ - test/helpers_test.rb
262
267
  - test/mocker_test.rb
263
268
  - test/resource_test.rb
264
269
  - test/resources/author_test.rb
@@ -310,4 +315,5 @@ test_files:
310
315
  - test/resources/user_settings_test.rb
311
316
  - test/resources/user_test.rb
312
317
  - test/resources/vote_test.rb
318
+ - test/services/recommender_test.rb
313
319
  - test/test_helper.rb