activerecord-reputation-system 1.0.0

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