recommendify-ruby 0.3.8
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.
- data/Gemfile +9 -0
- data/README.md +154 -0
- data/Rakefile +18 -0
- data/doc/example.png +0 -0
- data/doc/example.rb +87 -0
- data/doc/example_data.csv +120048 -0
- data/ext/cc_item.h +8 -0
- data/ext/cosine.c +3 -0
- data/ext/extconf.rb +18 -0
- data/ext/iikey.c +18 -0
- data/ext/jaccard.c +19 -0
- data/ext/output.c +22 -0
- data/ext/recommendify.c +214 -0
- data/ext/sort.c +23 -0
- data/ext/version.h +17 -0
- data/lib/recommendify.rb +9 -0
- data/lib/recommendify/base.rb +86 -0
- data/lib/recommendify/cc_matrix.rb +51 -0
- data/lib/recommendify/cosine_input_matrix.rb +7 -0
- data/lib/recommendify/input_matrix.rb +52 -0
- data/lib/recommendify/jaccard_input_matrix.rb +62 -0
- data/lib/recommendify/neighbor.rb +19 -0
- data/lib/recommendify/recommendify.rb +25 -0
- data/lib/recommendify/similarity_matrix.rb +62 -0
- data/lib/recommendify/sparse_matrix.rb +53 -0
- data/recommendify.gemspec +25 -0
- data/spec/base_spec.rb +188 -0
- data/spec/cc_matrix_shared.rb +89 -0
- data/spec/cosine_input_matrix_spec.rb +18 -0
- data/spec/input_matrix_shared.rb +27 -0
- data/spec/input_matrix_spec.rb +29 -0
- data/spec/jaccard_input_matrix_spec.rb +95 -0
- data/spec/recommendify_spec.rb +28 -0
- data/spec/similarity_matrix_spec.rb +93 -0
- data/spec/sparse_matrix_spec.rb +78 -0
- data/spec/spec_helper.rb +42 -0
- metadata +128 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
share_examples_for Recommendify::CCMatrix do
|
2
|
+
|
3
|
+
it "should build a sparsematrix with the correct key" do
|
4
|
+
@matrix.ccmatrix.redis_key.should == "recommendify-test:mymatrix:ccmatrix"
|
5
|
+
end
|
6
|
+
|
7
|
+
it "should increment all item counts on set addition" do
|
8
|
+
Recommendify.redis.hset("recommendify-test:mymatrix:items", "bar", 2)
|
9
|
+
@matrix.add_set("user123", ["foo", "bar"])
|
10
|
+
Recommendify.redis.hget("recommendify-test:mymatrix:items", "bar").to_i.should == 3
|
11
|
+
Recommendify.redis.hget("recommendify-test:mymatrix:items", "foo").to_i.should == 1
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should increment all item<->item pairs on set addition" do
|
15
|
+
@matrix.ccmatrix["bar", "foo"] = 2
|
16
|
+
res = @matrix.add_set("user123", ["foo", "bar", "fnord"])
|
17
|
+
res.length.should == 3
|
18
|
+
@matrix.ccmatrix["bar", "foo"].should == 3
|
19
|
+
@matrix.ccmatrix["foo", "fnord"].should == 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should increment all item<->item paris on single item addition" do
|
23
|
+
@matrix.ccmatrix["bar", "fnord"] = 2
|
24
|
+
@matrix.add_single("user123", "fnord", ["foo", "bar"])
|
25
|
+
@matrix.ccmatrix["bar", "fnord"].should == 3
|
26
|
+
@matrix.ccmatrix["foo", "fnord"].should == 1
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should increment the item count on single item addition" do
|
30
|
+
@matrix.send(:item_count_incr, "fnordfnord")
|
31
|
+
@matrix.send(:item_count_incr, "fnordfnord")
|
32
|
+
@matrix.send(:item_count_incr, "foofnord")
|
33
|
+
@matrix.add_single("user123", "fnordfnord", ["foofnord", "barfnord"])
|
34
|
+
@matrix.send(:item_count, "foofnord").should == 1
|
35
|
+
@matrix.send(:item_count, "barfnord").should == 0
|
36
|
+
@matrix.send(:item_count, "fnordfnord").should == 3
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should calculate all item<->item pairs (3)" do
|
40
|
+
res = @matrix.send(:all_pairs, ["foo", "bar", "fnord"])
|
41
|
+
res.length.should == 3
|
42
|
+
res.should include("bar:foo")
|
43
|
+
res.should include("fnord:foo")
|
44
|
+
res.should include("bar:fnord")
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should calculate all item<->item pairs (6)" do
|
48
|
+
res = @matrix.send(:all_pairs, ["foo", "bar", "fnord", "blubb"])
|
49
|
+
res.length.should == 6
|
50
|
+
res.should include("bar:foo")
|
51
|
+
res.should include("fnord:foo")
|
52
|
+
res.should include("bar:fnord")
|
53
|
+
res.should include("blubb:foo")
|
54
|
+
res.should include("blubb:fnord")
|
55
|
+
res.should include("bar:blubb")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return all_items" do
|
59
|
+
@matrix.add_set("user42", ["fnord", "blubb"])
|
60
|
+
@matrix.add_set("user23", ["hans", "wurst"])
|
61
|
+
@matrix.all_items.length.should == 4
|
62
|
+
@matrix.all_items.should include("wurst")
|
63
|
+
@matrix.all_items.should include("fnord")
|
64
|
+
@matrix.all_items.should include("hans")
|
65
|
+
@matrix.all_items.should include("wurst")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should delete all item<->item pairs on item deletion" do
|
69
|
+
@matrix.ccmatrix["foo", "fnord"] = 2
|
70
|
+
@matrix.add_set("user123", ["foo", "bar", "fnord"])
|
71
|
+
@matrix.add_set("user456", ["fnord", "blubb"])
|
72
|
+
@matrix.ccmatrix["bar", "foo"].should == 1
|
73
|
+
@matrix.ccmatrix["foo", "fnord"].should == 3
|
74
|
+
@matrix.ccmatrix["blubb", "fnord"].should == 1
|
75
|
+
@matrix.delete_item("fnord")
|
76
|
+
@matrix.ccmatrix["bar", "foo"].should == 1
|
77
|
+
@matrix.ccmatrix["foo", "fnord"].should == 0
|
78
|
+
@matrix.ccmatrix["blubb", "fnord"].should == 0
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should delete the item count on deletion" do
|
82
|
+
@matrix.add_set("user123", ["foo", "bar", "fnord"])
|
83
|
+
@matrix.add_set("user456", ["fnord", "blubb"])
|
84
|
+
@matrix.send(:item_count, "fnord").should == 2
|
85
|
+
@matrix.delete_item("fnord")
|
86
|
+
@matrix.send(:item_count, "fnord").should == 0
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require ::File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Recommendify::CosineInputMatrix do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@matrix = Recommendify::CosineInputMatrix.new(:redis_prefix => "recommendify-test", :key => "mymatrix")
|
7
|
+
end
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
flush_redis!
|
11
|
+
end
|
12
|
+
|
13
|
+
it_should_behave_like Recommendify::InputMatrix
|
14
|
+
it_should_behave_like Recommendify::CCMatrix
|
15
|
+
|
16
|
+
it "should calculate the correct cosine similarity (here be dragons)"
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
share_examples_for Recommendify::InputMatrix do
|
2
|
+
|
3
|
+
it "should build the correct keys" do
|
4
|
+
@matrix.redis_key.should == "recommendify-test:mymatrix"
|
5
|
+
end
|
6
|
+
|
7
|
+
it "should respond to add_set" do
|
8
|
+
@matrix.respond_to?(:add_set).should == true
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should respond to add_single" do
|
12
|
+
@matrix.respond_to?(:add_single).should == true
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should respond to similarity" do
|
16
|
+
@matrix.respond_to?(:similarity).should == true
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should respond to similarities_for" do
|
20
|
+
@matrix.respond_to?(:similarities_for).should == true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should respond to all_items" do
|
24
|
+
@matrix.respond_to?(:all_items).should == true
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require ::File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Recommendify::InputMatrix do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@matrix = Recommendify::InputMatrix.new(:redis_prefix => "recommendify-test", :key => "mymatrix")
|
7
|
+
end
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
flush_redis!
|
11
|
+
end
|
12
|
+
|
13
|
+
it_should_behave_like Recommendify::InputMatrix
|
14
|
+
|
15
|
+
describe "object creation" do
|
16
|
+
|
17
|
+
it "should create an object with the correct class" do
|
18
|
+
obj = Recommendify::InputMatrix.create(:key => "fubar", :similarity_func => :jaccard)
|
19
|
+
obj.should be_a(Recommendify::JaccardInputMatrix)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should create an object with the correct class and pass opts" do
|
23
|
+
obj = Recommendify::InputMatrix.create(:key => "fubar", :similarity_func => :jaccard)
|
24
|
+
obj.instance_variable_get(:@opts)[:key].should == "fubar"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require ::File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Recommendify::JaccardInputMatrix do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@matrix = Recommendify::JaccardInputMatrix.new(:redis_prefix => "recommendify-test", :key => "mymatrix")
|
7
|
+
end
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
flush_redis!
|
11
|
+
end
|
12
|
+
|
13
|
+
it_should_behave_like Recommendify::InputMatrix
|
14
|
+
it_should_behave_like Recommendify::CCMatrix
|
15
|
+
|
16
|
+
it "should calculate the correct jaccard index" do
|
17
|
+
@matrix.send(:calculate_jaccard,
|
18
|
+
["foo", "bar", "fnord", "blubb"],
|
19
|
+
["bar", "fnord", "shmoo", "snafu"]
|
20
|
+
).should == 2.0/6.0
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should calculate the correct similarity between to items" do
|
24
|
+
add_two_item_test_data!(@matrix)
|
25
|
+
# sim(fnord,blubb) = (users(fnord) & users(blub)) / (users(fnord) + users(blubb))
|
26
|
+
# => {user42 user48} / {user42 user46 user48 user50} + {user42 user44 user48}
|
27
|
+
# => {user42 user48} / {user42 user44 user46 user48 user50}
|
28
|
+
# => 2 / 5 => 0.4
|
29
|
+
@matrix.similarity("fnord", "blubb").should == 0.4
|
30
|
+
@matrix.similarity("blubb", "fnord").should == 0.4
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should calculate all similarities for an item (1/3)" do
|
34
|
+
add_three_item_test_data!(@matrix)
|
35
|
+
res = @matrix.similarities_for("fnord")
|
36
|
+
res.length.should == 2
|
37
|
+
res.should include ["shmoo", 0.75]
|
38
|
+
res.should include ["blubb", 0.4]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should calculate all similarities for an item (2/3)" do
|
42
|
+
add_three_item_test_data!(@matrix)
|
43
|
+
res = @matrix.similarities_for("shmoo")
|
44
|
+
res.length.should == 2
|
45
|
+
res.should include ["blubb", 0.2]
|
46
|
+
res.should include ["fnord", 0.75]
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
it "should calculate all similarities for an item (3/3)" do
|
51
|
+
add_three_item_test_data!(@matrix)
|
52
|
+
res = @matrix.similarities_for("blubb")
|
53
|
+
res.length.should == 2
|
54
|
+
res.should include ["shmoo", 0.2]
|
55
|
+
res.should include ["fnord", 0.4]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should call run_native when the native option was passed" do
|
59
|
+
Recommendify::JaccardInputMatrix.class_eval do
|
60
|
+
def check_native; true; end
|
61
|
+
end
|
62
|
+
matrix = Recommendify::JaccardInputMatrix.new(
|
63
|
+
:redis_prefix => "recommendify-test",
|
64
|
+
:native => true,
|
65
|
+
:key => "mymatrix"
|
66
|
+
)
|
67
|
+
matrix.should_receive(:run_native).with("fnord").and_return(true)
|
68
|
+
matrix.similarities_for("fnord")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return the correct redis url" do
|
72
|
+
@matrix.send(:redis_url).should == "127.0.0.1:6379"
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def add_two_item_test_data!(matrix)
|
78
|
+
matrix.add_set("user42", ["fnord", "blubb"])
|
79
|
+
matrix.add_set("user44", ["blubb"])
|
80
|
+
matrix.add_set("user46", ["fnord"])
|
81
|
+
matrix.add_set("user48", ["fnord", "blubb"])
|
82
|
+
matrix.add_set("user50", ["fnord"])
|
83
|
+
end
|
84
|
+
|
85
|
+
def add_three_item_test_data!(matrix)
|
86
|
+
matrix.add_set("user42", ["fnord", "blubb", "shmoo"])
|
87
|
+
matrix.add_set("user44", ["blubb"])
|
88
|
+
matrix.add_set("user46", ["fnord", "shmoo"])
|
89
|
+
matrix.add_set("user48", ["fnord", "blubb"])
|
90
|
+
matrix.add_set("user50", ["fnord", "shmoo"])
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require ::File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Recommendify do
|
4
|
+
|
5
|
+
it "should store a redis connection" do
|
6
|
+
Recommendify.redis = "asd"
|
7
|
+
Recommendify.redis.should == "asd"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should raise an exception if unconfigured redis connection is accessed" do
|
11
|
+
Recommendify.redis = nil
|
12
|
+
lambda{ ecommendify.redis }.should raise_error
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should capitalize a string" do
|
16
|
+
Recommendify.capitalize("fuubar").should == "Fuubar"
|
17
|
+
Recommendify.capitalize("fuUBar").should == "Fuubar"
|
18
|
+
Recommendify.capitalize("FUUBAR").should == "Fuubar"
|
19
|
+
Recommendify.capitalize("Fuubar").should == "Fuubar"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should constantize a string" do
|
23
|
+
obj = Recommendify.constantize("JaccardInputMatrix")
|
24
|
+
# should_be doesn't work here...
|
25
|
+
obj.inspect.should == "Recommendify::JaccardInputMatrix"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require ::File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Recommendify::SimilarityMatrix do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
flush_redis!
|
7
|
+
@matrix = Recommendify::SimilarityMatrix.new(:redis_prefix => "recommendify-test", :key => "mymatrix")
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "sorted sets per item" do
|
11
|
+
|
12
|
+
it "should store member similarities" do
|
13
|
+
@matrix.update("item_foo", [["item_bar", 0.7], ["item_fnord", 0.3]])
|
14
|
+
@matrix.write_queue["item_foo"].length.should == 2
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should store member similarities uniquely" do
|
18
|
+
@matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
|
19
|
+
@matrix.write_queue["item_fnord"].length.should == 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should store member similarities uniquely and sum the scores" do
|
23
|
+
@matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
|
24
|
+
@matrix.write_queue["item_fnord"].should == {"item_bar" => 1.0}
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should store multiple member similarities uniquely and sum the scores" do
|
28
|
+
@matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3], ["item_foo", 0.75]])
|
29
|
+
@matrix.write_queue["item_fnord"].should == {"item_bar" => 1.0, "item_foo" => 0.75}
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should store multiple member similarities uniquely and sum the scores on multiple updates" do
|
33
|
+
@matrix.update("item_fnord", [["item_bar", 0.7], ["item_foo", 0.75]])
|
34
|
+
@matrix.update("item_fnord", [["item_fnord", 0.3], ["item_bar", 0.3], ["item_foo", 0.75]])
|
35
|
+
@matrix.write_queue["item_fnord"].should == {"item_bar" => 1.0, "item_foo" => 1.5, "item_fnord" => 0.3}
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should retrieve the members" do
|
39
|
+
@matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3], ["item_foo", 0.75]])
|
40
|
+
@matrix["item_fnord"].should == {"item_bar" => 1.0, "item_foo" => 0.75}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "serialization/loading to/from redis" do
|
46
|
+
|
47
|
+
it "should serialize a member of the write_queue correctly" do
|
48
|
+
@matrix.update("item_fnord", [["item_fnord", 0.3], ["item_bar", 0.3], ["item_foo", 0.75]])
|
49
|
+
@matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
|
50
|
+
@matrix.send(:serialize_item, "item_fnord").should == "item_bar:1.3|item_foo:0.75|item_fnord:0.3"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should write the n-most similar members and scores to redis on commit_item!" do
|
54
|
+
@matrix.update("item_fnord", [["item_fnord", 0.3], ["item_bar", 0.3], ["item_foo", 0.75]])
|
55
|
+
@matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
|
56
|
+
@matrix.commit_item!("item_fnord")
|
57
|
+
Recommendify.redis.hget("recommendify-test:mymatrix", "item_fnord").should == "item_bar:1.3|item_foo:0.75|item_fnord:0.3"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not write more than max_neighbors scores to redis on commit_item!" do
|
61
|
+
60.times{ |n| @matrix.update("item_fnord", [["item_#{n}", n.to_f/100.0]]) }
|
62
|
+
@matrix.commit_item!("item_fnord")
|
63
|
+
Recommendify.redis.hget("recommendify-test:mymatrix", "item_fnord").split("|").length.should == 50
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not write more neighbors with zero-scores to redis on commit_item!" do
|
67
|
+
@matrix.update("item_fnord", [["item_fnord", 0.0], ["item_bar", 0.3], ["item_foo", 0.75]])
|
68
|
+
@matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
|
69
|
+
@matrix.commit_item!("item_fnord")
|
70
|
+
Recommendify.redis.hget("recommendify-test:mymatrix", "item_fnord").split("|").length.should == 2
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should clear the item from the write_queue after commit_item!" do
|
74
|
+
60.times{ |n| @matrix.update("item_fnord", [["item_#{n}", n.to_f/100.0]]) }
|
75
|
+
@matrix.write_queue["item_fnord"].length.should == 60
|
76
|
+
@matrix.commit_item!("item_fnord")
|
77
|
+
@matrix.write_queue["item_fnord"].length.should == 0
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should retrieve the n-most similar neighbors after stored" do
|
81
|
+
Recommendify.redis.hset("recommendify-test:mymatrix", "item_fnord", "item_blubb:0.6|item_foo:0.4")
|
82
|
+
@matrix["item_fnord"].keys.should include("item_blubb")
|
83
|
+
@matrix["item_fnord"].keys.should include("item_foo")
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should retrieve the n-most similar neighbors after stored with scores" do
|
87
|
+
Recommendify.redis.hset("recommendify-test:mymatrix", "item_fnord", "item_blubb:0.6|item_foo:0.4")
|
88
|
+
@matrix["item_fnord"].should == {"item_blubb" => 0.6, "item_foo" => 0.4}
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require ::File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Recommendify::SparseMatrix do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@sm = Recommendify::SparseMatrix.new(:redis_prefix => "recommendify-test", :key => "mysparsematrix")
|
7
|
+
end
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
flush_redis!
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should build the correct keys" do
|
14
|
+
@sm.redis_key.should == "recommendify-test:mysparsematrix"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should retrieve a value" do
|
18
|
+
Recommendify.redis.hset("recommendify-test:mysparsematrix", "bar:foo", 43)
|
19
|
+
@sm["bar", "foo"].to_i.should == 43
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should retrieve a value regardless of parameter order" do
|
23
|
+
Recommendify.redis.hset("recommendify-test:mysparsematrix", "one:two", 14)
|
24
|
+
@sm["one", "two"].to_i.should == 14
|
25
|
+
@sm["two", "one"].to_i.should == 14
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should store a value" do
|
29
|
+
@sm["bar", "foo"] = 123
|
30
|
+
Recommendify.redis.hget("recommendify-test:mysparsematrix", "bar:foo").to_i.should == 123
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should store a value regardless of parameter order" do
|
34
|
+
@sm["foo", "bar"] = 126
|
35
|
+
Recommendify.redis.hget("recommendify-test:mysparsematrix", "bar:foo").to_i.should == 126
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return 0 if the key is not found" do
|
39
|
+
@sm["not", "set"].should == 0
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should increment a value" do
|
43
|
+
@sm["foo", "bar"] = 1000
|
44
|
+
@sm.incr("foo", "bar")
|
45
|
+
Recommendify.redis.hget("recommendify-test:mysparsematrix", "bar:foo").to_i.should == 1001
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should increment a value regardless of parameter order" do
|
49
|
+
@sm["foo", "bar"] = 2000
|
50
|
+
@sm.incr("bar", "foo")
|
51
|
+
Recommendify.redis.hget("recommendify-test:mysparsematrix", "bar:foo").to_i.should == 2001
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should not create unneseccary keys" do
|
55
|
+
@sm["foo", "bar"] = 90
|
56
|
+
@sm["5asd6", "bar"] = 260
|
57
|
+
@sm["foo", "bar"] = 45
|
58
|
+
@sm["foo", "jefs"] = 26
|
59
|
+
Recommendify.redis.hkeys("recommendify-test:mysparsematrix").length.should == 3
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should create a key if the value is not 0" do
|
63
|
+
@sm["foo", "jefs"] = 26
|
64
|
+
Recommendify.redis.hkeys("recommendify-test:mysparsematrix").length.should == 1
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should not create a key if the value is 0" do
|
68
|
+
@sm["foo", "jefs"] = 0
|
69
|
+
Recommendify.redis.hkeys("recommendify-test:mysparsematrix").length.should == 0
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should delete a key if the value is set to 0" do
|
73
|
+
Recommendify.redis.hset("recommendify-test:mysparsematrix", "bar:foo", 43)
|
74
|
+
@sm["bar", "foo"] = 0
|
75
|
+
Recommendify.redis.hkeys("recommendify-test:mysparsematrix").length.should == 0
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|