activerecord-reputation-system 1.0.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.
@@ -0,0 +1,39 @@
1
+ ##
2
+ # Copyright 2012 Twitter, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ##
16
+
17
+ module ReputationSystem
18
+ module Reputation
19
+ def reputation_value_for(reputation_name, *args)
20
+ scope = args.first
21
+ if !self.class.has_reputation_for?(reputation_name)
22
+ raise ArgumentError, "#{reputation_name} is not valid"
23
+ else
24
+ reputation_name = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
25
+ process = ReputationSystem::Network.get_reputation_def(self.class.name, reputation_name)[:aggregated_by]
26
+ reputation = RSReputation.find_or_create_reputation(reputation_name, self, process)
27
+ reputation.value
28
+ end
29
+ end
30
+
31
+ def rank_for(reputation_name, *args)
32
+ scope = args.first
33
+ my_value = self.reputation_value_for(reputation_name, scope)
34
+ self.class.count_with_reputation(reputation_name, scope, :all,
35
+ :conditions => ["rs_reputations.value > ?", my_value]
36
+ ) + 1
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ ##
2
+ # Copyright 2012 Twitter, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ##
16
+
17
+ module ReputationSystem
18
+ module Scope
19
+ def self.included(klass)
20
+ klass.extend ClassMethods
21
+ end
22
+
23
+ module ClassMethods
24
+ def add_scope_for(reputation_name, scope)
25
+ ReputationSystem::Network.add_scope_for(name, reputation_name, scope)
26
+ end
27
+
28
+ def has_scopes?(reputation_name)
29
+ ReputationSystem::Network.has_scopes?(name, reputation_name, scope)
30
+ end
31
+
32
+ def has_scope?(reputation_name, scope)
33
+ ReputationSystem::Network.has_scope?(name, reputation_name, scope)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ ##
2
+ # Copyright 2012 Twitter, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ##
16
+
17
+ module ReputationSystem
18
+ VERSION = "1.0.0"
19
+ end
@@ -0,0 +1,44 @@
1
+ ##
2
+ # Copyright 2012 Twitter, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ##
16
+
17
+ require 'spec_helper'
18
+
19
+ describe RSEvaluation do
20
+ before(:each) do
21
+ @user = User.create!(:name => 'jack')
22
+ @question = Question.create!(:text => 'What is Twitter?', :author_id => @user.id)
23
+ end
24
+
25
+ context "Validation" do
26
+ before :each do
27
+ @attributes = {:reputation_name => 'total_votes', :source => @user, :target => @question, :value => 1}
28
+ end
29
+ it "should not be able to create an evaluation from given source if it has alredy evaluated the same reputation of the target" do
30
+ RSEvaluation.create!(@attributes)
31
+ lambda {RSEvaluation.create!(@attributes)}.should raise_error
32
+ end
33
+ end
34
+
35
+ context "Association" do
36
+ it "should delete associated reputation message" do
37
+ @question.add_evaluation(:total_votes, 5, @user)
38
+ evaluation = RSEvaluation.find_by_reputation_name_and_source_and_target(:total_votes, @user, @question)
39
+ RSReputationMessage.find_by_sender_id_and_sender_type(evaluation.id, evaluation.class.name).should_not be_nil
40
+ @question.delete_evaluation(:total_votes, @user)
41
+ RSReputationMessage.find_by_sender_id_and_sender_type(evaluation.id, evaluation.class.name).should be_nil
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,47 @@
1
+ ##
2
+ # Copyright 2012 Twitter, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ##
16
+
17
+ require 'spec_helper'
18
+
19
+ describe RSReputationMessage do
20
+ before(:each) do
21
+ @user = User.create!(:name => 'jack')
22
+ @rep1 = RSReputation.create!(:reputation_name => "karma1", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum')
23
+ @rep2 = RSReputation.create!(:reputation_name => "karma2", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum')
24
+ end
25
+
26
+ context "Validation" do
27
+ it "should not be able to create a message from given sender if it has alredy sent one to the same receiver" do
28
+ RSReputationMessage.create(:sender => @rep1, :receiver => @rep2).valid?.should == true
29
+ RSReputationMessage.create(:sender => @rep1, :receiver => @rep2).valid?.should == false
30
+ end
31
+
32
+ it "should have raise error if sender is neither RSEvaluation and RSReputation" do
33
+ RSReputationMessage.create(:sender => @user, :receiver => @rep2).errors[:sender].should_not be_nil
34
+ end
35
+ end
36
+
37
+ context "Association" do
38
+ it "should delete associated sender if it is evaluation" do
39
+ question = Question.create!(:text => 'What is Twitter?', :author_id => @user.id)
40
+ question.add_evaluation(:total_votes, 5, @user)
41
+ evaluation = RSEvaluation.find_by_reputation_name_and_source_and_target(:total_votes, @user, question)
42
+ m = RSReputationMessage.find_by_sender_id_and_sender_type(evaluation.id, evaluation.class.name)
43
+ m.destroy
44
+ lambda { evaluation.reload }.should raise_error ActiveRecord::RecordNotFound
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,101 @@
1
+ ##
2
+ # Copyright 2012 Twitter, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ##
16
+
17
+ require 'spec_helper'
18
+
19
+ describe RSReputation do
20
+ before(:each) do
21
+ @user = User.create!(:name => 'jack')
22
+ end
23
+
24
+ context "Validation" do
25
+ it "should have value 0 by default in case of non product process" do
26
+ r = RSReputation.create!(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum')
27
+ r.value.should == 0
28
+ end
29
+
30
+ it "should be able to change value to 0 if process is not product process" do
31
+ r = RSReputation.create!(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum', :value => 10)
32
+ r.value = 0
33
+ r.save!
34
+ r.reload
35
+ r.value.should == 0
36
+ end
37
+
38
+ it "should have value 1 by default in case of product process" do
39
+ r = RSReputation.create!(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'product')
40
+ r.value.should == 1
41
+ end
42
+
43
+ it "should be able to create reputation with process 'sum', 'average' and 'product'" do
44
+ RSReputation.create(:reputation_name => "karma1", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum').valid?.should == true
45
+ RSReputation.create(:reputation_name => "karma2", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'average').valid?.should == true
46
+ RSReputation.create(:reputation_name => "karma3", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'product').valid?.should == true
47
+ end
48
+
49
+ it "should not be able to create reputation with process other than 'sum', 'average' and 'product'" do
50
+ RSReputation.create(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'invalid').valid?.should == false
51
+ end
52
+
53
+ it "should not be able to create reputation of the same name for the same target" do
54
+ RSReputation.create(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum').valid?.should == true
55
+ RSReputation.create(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum').valid?.should == false
56
+ end
57
+ end
58
+
59
+ context "Association" do
60
+ before :each do
61
+ @question = Question.create!(:text => 'What is Twitter?', :author_id => @user.id)
62
+ @question.add_evaluation(:total_votes, 5, @user)
63
+ end
64
+
65
+ it "should delete associated received messages" do
66
+ rep = RSReputation.find_by_target_id_and_target_type(@question.id, 'Question')
67
+ RSReputationMessage.find_by_receiver_id(rep.id).should_not be_nil
68
+ rep.destroy
69
+ RSReputationMessage.find_by_receiver_id(rep.id).should be_nil
70
+ end
71
+
72
+ it "should delete associated sent messages" do
73
+ rep = RSReputation.find_by_target_id_and_target_type(@user.id, 'User')
74
+ RSReputationMessage.find_by_sender_id_and_sender_type(rep.id, rep.class.name).should_not be_nil
75
+ rep.destroy
76
+ RSReputationMessage.find_by_sender_id_and_sender_type(rep.id, rep.class.name).should be_nil
77
+ end
78
+ end
79
+
80
+ describe "#normalized_value" do
81
+ before :each do
82
+ @user2 = User.create!(:name => 'dick')
83
+ @user3 = User.create!(:name => 'foo')
84
+ question = Question.new(:text => "Does this work?", :author_id => @user.id)
85
+ @r1 = RSReputation.create!(:reputation_name => "karma", :value => 2, :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum')
86
+ @r2 = RSReputation.create!(:reputation_name => "karma", :value => 6, :target_id => @user2.id, :target_type => @user2.class.to_s, :aggregated_by => 'sum')
87
+ @r3 = RSReputation.create!(:reputation_name => "karma", :value => 10, :target_id => @user3.id, :target_type => @user3.class.to_s, :aggregated_by => 'sum')
88
+ @r4 = RSReputation.create!(:reputation_name => "karma", :value => 10, :target_id => question.id, :target_type => question.class.to_s, :aggregated_by => 'sum')
89
+ end
90
+
91
+ it "should return correct normalized value" do
92
+ @r1.normalized_value.should be_within(DELTA).of(0)
93
+ @r2.normalized_value.should be_within(DELTA).of(0.5)
94
+ @r3.normalized_value.should be_within(DELTA).of(1)
95
+ end
96
+
97
+ it "should return 0 if max and min are the same" do
98
+ @r4.normalized_value.should be_within(DELTA).of(0)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,68 @@
1
+ ##
2
+ # Copyright 2012 Twitter, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ##
16
+
17
+ require 'spec_helper'
18
+
19
+ describe ActiveRecord::Base do
20
+
21
+ before(:each) do
22
+ @user = User.create!(:name => 'jack')
23
+ @question = Question.create!(:text => 'Does this work?', :author_id => @user.id)
24
+ @answer = Answer.create!(:text => 'Yes!', :author_id => @user.id, :question_id => @question.id)
25
+ @phrase = Phrase.create!(:text => "One")
26
+ end
27
+
28
+ context "Mixin" do
29
+ describe "#has_reputation" do
30
+ it "should add 'add_evaluation' method to a model with primary reputation" do
31
+ @question.respond_to?(:add_evaluation).should == true
32
+ @answer.respond_to?(:add_evaluation).should == true
33
+ end
34
+
35
+ it "should not add 'add_evaluation' method to a model without primary reputation" do
36
+ @user.respond_to?(:add_evaluation).should == false
37
+ end
38
+
39
+ it "should add 'reputation_value_for' method to a model with reputation" do
40
+ @user.respond_to?(:reputation_value_for).should == true
41
+ @question.respond_to?(:reputation_value_for).should == true
42
+ end
43
+
44
+ it "should add 'normalized_reputation_value_for' method to a model with reputation" do
45
+ @user.respond_to?(:normalized_reputation_value_for).should == true
46
+ @question.respond_to?(:normalized_reputation_value_for).should == true
47
+ end
48
+
49
+ it "should delete reputations if target is deleted" do
50
+ @question.add_evaluation(:total_votes, 5, @user)
51
+ count = RSReputation.count
52
+ count = RSReputationMessage.count
53
+ @question.destroy
54
+ RSReputation.count.should < count
55
+ RSReputationMessage.count.should < count
56
+ end
57
+
58
+ it "should have declared default value if any" do
59
+ @answer.reputation_value_for(:avg_rating).should == 1
60
+ end
61
+
62
+ it "should overwrite reputation definitions if the same reputation name is declared" do
63
+ Answer.has_reputation(:avg_rating, :source => :user, :aggregated_by => :average, :init_value => 2)
64
+ Answer.new.reputation_value_for(:avg_rating).should == 2
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,289 @@
1
+ ##
2
+ # Copyright 2012 Twitter, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ##
16
+
17
+ require 'spec_helper'
18
+
19
+ describe ActiveRecord::Base do
20
+
21
+ before(:each) do
22
+ @user = User.create!(:name => 'jack')
23
+ @question = Question.create!(:text => 'Does this work?', :author_id => @user.id)
24
+ @answer = Answer.create!(:text => 'Yes!', :author_id => @user.id, :question_id => @question.id)
25
+ @phrase = Phrase.create!(:text => "One")
26
+ end
27
+
28
+ context "Primary Reputation" do
29
+ describe "#add_evaluation" do
30
+ it "should create evaluation in case of valid input" do
31
+ @question.add_evaluation(:total_votes, 1, @user)
32
+ @question.reputation_value_for(:total_votes).should == 1
33
+ end
34
+
35
+ it "should raise exception if invalid reputation name is given" do
36
+ lambda {@question.add_evaluation(:invalid, 1, @user)}.should raise_error(ArgumentError)
37
+ end
38
+
39
+ it "should raise exception if the same source evaluates for the same target more than once" do
40
+ @question.add_evaluation(:total_votes, 1, @user)
41
+ lambda{@question.add_evaluation(:total_votes, 1, @user)}.should raise_error
42
+ end
43
+
44
+ it "should not allow the same source to add an evaluation for the same target" do
45
+ @question.add_evaluation(:total_votes, 1, @user)
46
+ lambda{@question.add_evaluation(:total_votes, 1, @user)}.should raise_error
47
+ end
48
+
49
+ context "With Scopes" do
50
+ it "should add evaluation on appropriate scope" do
51
+ @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1)
52
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2)
53
+ @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 1
54
+ @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 2
55
+ @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
56
+ end
57
+
58
+ it "should raise exception if invalid scope is given" do
59
+ lambda{@phrase.add_evaluation(:difficulty_with_scope, 1, :invalid_scope)}.should raise_error(ArgumentError)
60
+ end
61
+
62
+ it "should raise exception if scope is not given" do
63
+ lambda{@phrase.add_evaluation(:difficulty_with_scope, 1, :invalid_scope)}.should raise_error(ArgumentError)
64
+ end
65
+ end
66
+ end
67
+
68
+ describe "#update_evaluation" do
69
+ before :each do
70
+ @question.add_evaluation(:total_votes, 1, @user)
71
+ end
72
+
73
+ it "should update evaluation in case of valid input" do
74
+ @question.update_evaluation(:total_votes, 2, @user)
75
+ @question.reputation_value_for(:total_votes).should == 2
76
+ end
77
+
78
+ it "should raise exception if invalid reputation name is given" do
79
+ lambda {@question.update_evaluation(:invalid, 1, @user)}.should raise_error(ArgumentError)
80
+ end
81
+
82
+ it "should raise exception if invalid source is given" do
83
+ lambda {@question.update_evaluation(:total_votes, 1, @answer)}.should raise_error(ArgumentError)
84
+ end
85
+
86
+ it "should raise exception if evaluation does not exist" do
87
+ lambda{@answer.update_evaluation(:avg_rating, 1, @user)}.should raise_error
88
+ end
89
+
90
+ context "With Scopes" do
91
+ before :each do
92
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2)
93
+ end
94
+
95
+ it "should update evaluation on appropriate scope" do
96
+ @phrase.update_evaluation(:difficulty_with_scope, 5, @user, :s2)
97
+ @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 0
98
+ @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 5
99
+ @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
100
+ end
101
+
102
+ it "should raise exception if invalid scope is given" do
103
+ lambda{@phrase.update_evaluation(:difficulty_with_scope, 5, @user, :invalid_scope)}.should raise_error(ArgumentError)
104
+ end
105
+
106
+ it "should raise exception if scope is not given" do
107
+ lambda{@phrase.update_evaluation(:difficulty_with_scope, 5, @user)}.should raise_error(ArgumentError)
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "#delete_evaluation!" do
113
+ before :each do
114
+ @question.add_evaluation(:total_votes, 1, @user)
115
+ end
116
+
117
+ it "should delete evaluation in case of valid input" do
118
+ @question.delete_evaluation!(:total_votes, @user)
119
+ @question.reputation_value_for(:total_votes).should == 0
120
+ end
121
+
122
+ it "should raise exception if invalid reputation name is given" do
123
+ lambda {@question.delete_evaluation!(:invalid, @user)}.should raise_error(ArgumentError)
124
+ end
125
+
126
+ it "should raise exception if invalid source is given" do
127
+ lambda {@question.delete_evaluation!(:total_votes, @answer)}.should raise_error(ArgumentError)
128
+ end
129
+
130
+ it "should raise exception if evaluation does not exist" do
131
+ lambda{@answer.delete_evaluation!(:avg_rating, @user)}.should raise_error
132
+ end
133
+
134
+ context "With Scopes" do
135
+ before :each do
136
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2)
137
+ end
138
+
139
+ it "should delete evaluation on appropriate scope" do
140
+ @phrase.delete_evaluation!(:difficulty_with_scope, @user, :s2)
141
+ @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 0
142
+ @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 0
143
+ @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
144
+ end
145
+
146
+ it "should raise exception if invalid scope is given" do
147
+ lambda{@phrase.delete_evaluation!(:difficulty_with_scope, @user, :invalid_scope)}.should raise_error(ArgumentError)
148
+ end
149
+
150
+ it "should raise exception if scope is not given" do
151
+ lambda{@phrase.delete_evaluation!(:difficulty_with_scope, @user)}.should raise_error(ArgumentError)
152
+ end
153
+ end
154
+ end
155
+
156
+ describe "#delete_evaluation" do
157
+ before :each do
158
+ @question.add_evaluation(:total_votes, 1, @user)
159
+ end
160
+
161
+ it "should delete evaluation in case of valid input" do
162
+ @question.delete_evaluation(:total_votes, @user)
163
+ @question.reputation_value_for(:total_votes).should == 0
164
+ end
165
+
166
+ it "should raise exception if invalid reputation name is given" do
167
+ lambda {@question.delete_evaluation(:invalid, @user)}.should raise_error(ArgumentError)
168
+ end
169
+
170
+ it "should return nil if evaluation does not exist" do
171
+ @answer.delete_evaluation(:avg_rating, @user).should be_nil
172
+ end
173
+
174
+ context "With Scopes" do
175
+ before :each do
176
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2)
177
+ end
178
+
179
+ it "should delete evaluation on appropriate scope" do
180
+ @phrase.delete_evaluation(:difficulty_with_scope, @user, :s2)
181
+ @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 0
182
+ @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 0
183
+ @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
184
+ end
185
+
186
+ it "should raise exception if invalid scope is given" do
187
+ lambda{@phrase.delete_evaluation(:difficulty_with_scope, @user, :invalid_scope)}.should raise_error(ArgumentError)
188
+ end
189
+
190
+ it "should raise exception if scope is not given" do
191
+ lambda{@phrase.delete_evaluation(:difficulty_with_scope, @user)}.should raise_error(ArgumentError)
192
+ end
193
+ end
194
+ end
195
+ end
196
+
197
+ context "Non-Primary Reputation with Gathering Aggregation" do
198
+ context "With Scopes" do
199
+ before :each do
200
+ @trans_ja = Translation.create!(:text => "Ichi", :user => @user, :locale => "ja", :phrase => @phrase)
201
+ @trans_fr = Translation.create!(:text => "Homme", :user => @user, :locale => "fr", :phrase => @phrase)
202
+ end
203
+
204
+ describe "#add_evaluation" do
205
+ it "should affect only reputations with relevant scope" do
206
+ @trans_ja.add_evaluation(:votes, 1, @user)
207
+ @trans_fr.add_evaluation(:votes, 2, @user)
208
+ @phrase.reputation_value_for(:maturity, :ja).should == 1
209
+ @phrase.reputation_value_for(:maturity, :fr).should == 2
210
+ end
211
+ end
212
+
213
+ describe "#update_eavluation" do
214
+ before :each do
215
+ @trans_ja.add_evaluation(:votes, 1, @user)
216
+ end
217
+
218
+ it "should affect only reputations with relevant scope" do
219
+ @trans_ja.update_evaluation(:votes, 3, @user)
220
+ @phrase.reputation_value_for(:maturity, :ja).should == 3
221
+ @phrase.reputation_value_for(:maturity, :fr).should == 0
222
+ end
223
+ end
224
+
225
+ describe "#delete_eavluation" do
226
+ before :each do
227
+ @trans_ja.add_evaluation(:votes, 1, @user)
228
+ end
229
+
230
+ it "should affect only reputations with relevant scope" do
231
+ @trans_ja.delete_evaluation!(:votes, @user)
232
+ @phrase.reputation_value_for(:maturity, :ja).should == 0
233
+ @phrase.reputation_value_for(:maturity, :fr).should == 0
234
+ end
235
+ end
236
+ end
237
+ end
238
+
239
+ context "Non-Primary Reputation with Mixing Aggregation" do
240
+ context "With Scopes" do
241
+ before :each do
242
+ @trans_ja = Translation.create!(:text => "Ichi", :user => @user, :locale => "ja", :phrase => @phrase)
243
+ @trans_fr = Translation.create!(:text => "Homme", :user => @user, :locale => "fr", :phrase => @phrase)
244
+ @trans_de = Translation.create!(:text => "Ein", :user => @user, :locale => "de", :phrase => @phrase)
245
+ end
246
+
247
+ describe "#add_evaluation" do
248
+ it "should affect only reputations with relevant scope" do
249
+ @trans_ja.add_evaluation(:votes, 1, @user)
250
+ @phrase.reputation_value_for(:maturity_all).should == 1
251
+ @trans_fr.add_evaluation(:votes, 2, @user)
252
+ @phrase.reputation_value_for(:maturity_all).should == 3
253
+ @trans_de.add_evaluation(:votes, 3, @user)
254
+ @phrase.reputation_value_for(:maturity_all).should == 3
255
+ @phrase.reputation_value_for(:maturity, :ja).should == 1
256
+ @phrase.reputation_value_for(:maturity, :fr).should == 2
257
+ @phrase.reputation_value_for(:maturity, :de).should == 3
258
+ end
259
+ end
260
+
261
+ describe "#update_eavluation" do
262
+ before :each do
263
+ @trans_ja.add_evaluation(:votes, 1, @user)
264
+ @trans_de.add_evaluation(:votes, 3, @user)
265
+ end
266
+
267
+ it "should affect only reputations with relevant scope" do
268
+ @trans_ja.update_evaluation(:votes, 3, @user)
269
+ @trans_de.update_evaluation(:votes, 2, @user)
270
+ @phrase.reputation_value_for(:maturity_all).should == 3
271
+ end
272
+ end
273
+
274
+ describe "#delete_eavluation" do
275
+ before :each do
276
+ @trans_ja.add_evaluation(:votes, 1, @user)
277
+ @trans_de.add_evaluation(:votes, 3, @user)
278
+ end
279
+
280
+ it "should affect only reputations with relevant scope" do
281
+ @trans_de.delete_evaluation!(:votes, @user)
282
+ @phrase.reputation_value_for(:maturity_all).should == 1
283
+ @trans_ja.delete_evaluation!(:votes, @user)
284
+ @phrase.reputation_value_for(:maturity_all).should == 0
285
+ end
286
+ end
287
+ end
288
+ end
289
+ end