activerecord-reputation-system 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ## Active Record Reputation System [![Build Status](https://secure.travis-ci.org/twitter/activerecord-reputation-system.png)](http://travis-ci.org/twitter/activerecord-reputation-system)
1
+ ## Active Record Reputation System [![Build Status](https://secure.travis-ci.org/twitter/activerecord-reputation-system.png)](http://travis-ci.org/twitter/activerecord-reputation-system) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/twitter/activerecord-reputation-system)
2
2
 
3
3
  The Active Record Reputation System helps you discover more about your application and make better decisions. The Reputation System gem makes it easy to integrate reputation systems into Rails applications, decouple the system from the main application and provide guidelines for good design of reputation systems.
4
4
 
@@ -165,12 +165,12 @@ reputations_activated?(reputation_name)
165
165
  # Includes the specified reputation value for the given name via a normal Active Record find query.
166
166
  ActiveRecord::Base.find_with_reputation(reputation_name, find_scope, options)
167
167
  # For example:
168
- ActiveRecord::Base.find_with_reputation(:maturity, :all, {:select => "id", :conditions => ["maturity > ?", 3], :order => "maturity"})
168
+ User.find_with_reputation(:karma, :all, {:select => "id", :conditions => ["karma > ?", 3], :order => "karma"})
169
169
 
170
170
  # Includes the specified normalized reputation value for the given name via a normal Active Record find query.
171
171
  ActiveRecord::Base.find_with_normalized_reputation(reputation_name, find_options)
172
172
  # For example:
173
- ActiveRecord::Base.find_with_normalized_reputation(:maturity, :all, {:select => "id", :conditions => ["maturity > ?", 3], :order => "maturity"})
173
+ User.find_with_normalized_reputation(:karma, :all, {:select => "id", :conditions => ["karma > ?", 0.5], :order => "karma"})
174
174
 
175
175
  # Includes the specified reputation value for the given name via a normal Active Record count query.
176
176
  ActiveRecord::Base.count_with_reputation(reputation_name, find_options)
@@ -179,6 +179,15 @@ ActiveRecord::Base.count_with_reputation(reputation_name, find_options)
179
179
  ActiveRecord::Base.find_with_reputation_sql(reputation_name, find_options)
180
180
  ```
181
181
 
182
+ ## Querying for Evaluated ActiveRecord
183
+ ```ruby
184
+ # Returns all active record instances evaluated by a given source for a given reputation name.
185
+ ActiveRecord::Base.evaluated_by(reputation_name, source)
186
+ # For example:
187
+ Question.evaluated_by(:votes, @user)
188
+ #
189
+ ```
190
+
182
191
  ## Advanced Topics
183
192
  ### Scope
184
193
  Reputations can have different scopes to provide additional context.
@@ -213,6 +222,10 @@ To execute an Active Record query using a scoped reputation, try this:
213
222
  ```ruby
214
223
  ActiveRecord::Base.find_with_reputation(:reputation_name, :scope, :find_options)
215
224
  ```
225
+ To find active records evaluated by a given source for a scoped reputation, try this:
226
+ ```ruby
227
+ ActiveRecord::Base.evaluated_by(:reputation_name, source, :scope)
228
+ ```
216
229
  There are a few more helper methods available for scopes:
217
230
  ```ruby
218
231
  # Allows you to add a scope dynamically.
@@ -268,6 +281,10 @@ For more information on semantic versioning, please visit http://semver.org/.
268
281
  * Katsuya Noguchi: http://github.com/katsuyan
269
282
  * Inspired by ["Building Web Reputation Systems" by Randy Farmer and Bryce Glass](http://shop.oreilly.com/product/9780596159801.do)
270
283
 
284
+ ## Related Links
285
+
286
+ * RailsCasts: http://railscasts.com/episodes/364-active-record-reputation-system
287
+
271
288
  ## License
272
289
 
273
290
  Copyright 2012 Twitter, Inc.
@@ -65,9 +65,10 @@ class RSReputation < ActiveRecord::Base
65
65
  else
66
66
  raise ArgumentError, "#{process} process is not supported yet"
67
67
  end
68
- rep.save!
68
+ save_succeeded = rep.save
69
69
  RSReputationMessage.add_reputation_message_if_not_exist(source, rep)
70
70
  propagate_updated_reputation_value(rep, valueBeforeUpdate) if rep.target
71
+ save_succeeded
71
72
  end
72
73
 
73
74
  def self.update_reputation_value_with_updated_source(rep, source, oldValue, weight, process)
@@ -85,8 +86,9 @@ class RSReputation < ActiveRecord::Base
85
86
  else
86
87
  raise ArgumentError, "#{process} process is not supported yet"
87
88
  end
88
- rep.save!
89
+ save_succeeded = rep.save
89
90
  propagate_updated_reputation_value(rep, valueBeforeUpdate) if rep.target
91
+ save_succeeded
90
92
  end
91
93
 
92
94
  def normalized_value
@@ -123,29 +125,34 @@ class RSReputation < ActiveRecord::Base
123
125
 
124
126
  # Propagates updated reputation value to the reputations whose source is the updated reputation.
125
127
  def self.propagate_updated_reputation_value(sender, oldValue)
126
- sender_name = sender.reputation_name.to_sym
127
- receiver_defs = ReputationSystem::Network.get_reputation_def(sender.target.class.name, sender_name)[:source_of]
128
- if receiver_defs
129
- receiver_defs.each do |rd|
130
- receiver_targets = sender.target.get_attributes_of(rd)
131
- receiver_targets.each do |rt|
132
- scope = sender.target.evaluate_reputation_scope(rd[:scope])
133
- srn = ReputationSystem::Network.get_scoped_reputation_name(rt.class.name, rd[:reputation], scope)
134
- process = ReputationSystem::Network.get_reputation_def(rt.class.name, srn)[:aggregated_by]
135
- rep = find_by_reputation_name_and_target(srn, rt)
136
- if rep
137
- weight = ReputationSystem::Network.get_weight_of_source_from_reputation_name_of_target(rt, sender_name, srn)
138
- unless oldValue
139
- update_reputation_value_with_new_source(rep, sender, weight, process)
140
- else
141
- update_reputation_value_with_updated_source(rep, sender, oldValue, weight, process)
142
- end
143
- # If r is new then value update will be done when it is initialized.
144
- else
145
- create_reputation(srn, rt, process)
146
- end
147
- end
128
+ receiver_defs = ReputationSystem::Network.get_reputation_def(sender.target.class.name, sender.reputation_name)[:source_of]
129
+ receiver_defs.each do |rd|
130
+ targets = sender.target.get_attributes_of(rd)
131
+ targets.each do |target|
132
+ scope = sender.target.evaluate_reputation_scope(rd[:scope])
133
+ send_reputation_message_to_receiver(rd[:reputation], sender, target, scope, oldValue)
148
134
  end
135
+ end if receiver_defs
136
+ end
137
+
138
+ def self.send_reputation_message_to_receiver(reputation_name, sender, target, scope, oldValue)
139
+ srn = ReputationSystem::Network.get_scoped_reputation_name(target.class.name, reputation_name, scope)
140
+ process = ReputationSystem::Network.get_reputation_def(target.class.name, srn)[:aggregated_by]
141
+ receiver = find_by_reputation_name_and_target(srn, target)
142
+ if receiver
143
+ weight = ReputationSystem::Network.get_weight_of_source_from_reputation_name_of_target(target, sender.reputation_name, srn)
144
+ update_reputation_value(receiver, sender, weight, process, oldValue)
145
+ # If r is new then value update will be done when it is initialized.
146
+ else
147
+ create_reputation(srn, target, process)
148
+ end
149
+ end
150
+
151
+ def self.update_reputation_value(receiver, sender, weight, process, oldValue)
152
+ unless oldValue
153
+ update_reputation_value_with_new_source(receiver, sender, weight, process)
154
+ else
155
+ update_reputation_value_with_updated_source(receiver, sender, oldValue, weight, process)
149
156
  end
150
157
  end
151
158
 
@@ -16,7 +16,6 @@
16
16
 
17
17
  require 'reputation_system/base'
18
18
  require 'reputation_system/query'
19
- require 'reputation_system/normalization'
20
19
  require 'reputation_system/evaluation'
21
20
  require 'reputation_system/network'
22
21
  require 'reputation_system/reputation'
@@ -25,4 +24,4 @@ require 'models/rs_evaluation'
25
24
  require 'models/rs_reputation'
26
25
  require 'models/rs_reputation_message'
27
26
 
28
- ActiveRecord::Base.send(:include, ReputationSystem::Base)
27
+ ActiveRecord::Base.send(:include, ReputationSystem::Base)
@@ -51,7 +51,6 @@ module ReputationSystem
51
51
  unless ancestors.include?(ReputationSystem::Reputation)
52
52
  has_many :reputations, :as => :target, :class_name => "RSReputation", :dependent => :destroy
53
53
  include ReputationSystem::Query
54
- include ReputationSystem::Normalization
55
54
  include ReputationSystem::Reputation
56
55
  include ReputationSystem::Scope
57
56
  end
@@ -16,8 +16,24 @@
16
16
 
17
17
  module ReputationSystem
18
18
  module Evaluation
19
+ module ClassMethods
20
+ def evaluated_by(reputation_name, source, *args)
21
+ scope = args.first
22
+ srn = ReputationSystem::Network.get_scoped_reputation_name(self.name, reputation_name, scope)
23
+ source_type = source.class.name
24
+ options = {}
25
+ options[:select] ||= sanitize_sql_array(["%s.*", self.table_name])
26
+ options[:joins] = sanitize_sql_array(["JOIN rs_evaluations ON %s.id = rs_evaluations.target_id AND rs_evaluations.target_type = ? AND rs_evaluations.reputation_name = ? AND rs_evaluations.source_id = ? AND rs_evaluations.source_type = ?", self.name, srn.to_s, source.id, source_type])
27
+ options[:joins] = sanitize_sql_array([options[:joins], self.table_name])
28
+ find(:all, options)
29
+ end
30
+ end
31
+
32
+ def self.included(klass)
33
+ klass.extend ClassMethods
34
+ end
35
+
19
36
  def add_evaluation(reputation_name, value, source, *args)
20
- raise ArgumentError, "#{reputation_name.to_s} is not defined for #{self.class.name}" unless ReputationSystem::Network.has_reputation_for?(self.class.name, reputation_name)
21
37
  scope = args.first
22
38
  srn = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
23
39
  process = ReputationSystem::Network.get_reputation_def(self.class.name, srn)[:aggregated_by]
@@ -27,63 +43,32 @@ module ReputationSystem
27
43
  end
28
44
 
29
45
  def update_evaluation(reputation_name, value, source, *args)
30
- raise ArgumentError, "#{reputation_name.to_s} is not defined for #{self.class.name}" unless ReputationSystem::Network.has_reputation_for?(self.class.name, reputation_name)
31
- scope = args.first
32
- srn = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
33
- evaluation = RSEvaluation.find_by_reputation_name_and_source_and_target(srn, source, self)
34
- if evaluation.nil?
35
- raise ArgumentError, "Given instance of #{source.class.name} has not evaluated #{reputation_name} of the instance of #{self.class.name} yet."
36
- else
37
- oldValue = evaluation.value
38
- evaluation.value = value
39
- evaluation.save!
40
- process = ReputationSystem::Network.get_reputation_def(self.class.name, srn)[:aggregated_by]
41
- rep = RSReputation.find_by_reputation_name_and_target(srn, self)
42
- RSReputation.update_reputation_value_with_updated_source(rep, evaluation, oldValue, 1, process)
43
- end
46
+ srn, evaluation = find_srn_and_evaluation!(reputation_name, source, args.first)
47
+ oldValue = evaluation.value
48
+ evaluation.value = value
49
+ evaluation.save!
50
+ process = ReputationSystem::Network.get_reputation_def(self.class.name, srn)[:aggregated_by]
51
+ rep = RSReputation.find_by_reputation_name_and_target(srn, self)
52
+ RSReputation.update_reputation_value_with_updated_source(rep, evaluation, oldValue, 1, process)
44
53
  end
45
54
 
46
55
  def add_or_update_evaluation(reputation_name, value, source, *args)
47
- scope = args.first
48
- srn = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
49
- evaluation = RSEvaluation.find_by_reputation_name_and_source_and_target(srn, source, self)
50
- if evaluation.nil?
51
- self.add_evaluation(reputation_name, value, source, scope)
56
+ srn, evaluation = find_srn_and_evaluation(reputation_name, source, args.first)
57
+ if RSEvaluation.exists? :reputation_name => srn, :source_id => source.id, :source_type => source.class.name, :target_id => self.id, :target_type => self.class.name
58
+ self.update_evaluation(reputation_name, value, source, *args)
52
59
  else
53
- self.update_evaluation(reputation_name, value, source, scope)
60
+ self.add_evaluation(reputation_name, value, source, *args)
54
61
  end
55
62
  end
56
63
 
57
64
  def delete_evaluation(reputation_name, source, *args)
58
- raise ArgumentError, "#{reputation_name.to_s} is not defined for #{self.class.name}" unless ReputationSystem::Network.has_reputation_for?(self.class.name, reputation_name)
59
- scope = args.first
60
- srn = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
61
- evaluation = RSEvaluation.find_by_reputation_name_and_source_and_target(srn, source, self)
62
- unless evaluation.nil?
63
- process = ReputationSystem::Network.get_reputation_def(self.class.name, srn)[:aggregated_by]
64
- oldValue = evaluation.value
65
- evaluation.value = process == :product ? 1 : 0
66
- rep = RSReputation.find_by_reputation_name_and_target(srn, self)
67
- RSReputation.update_reputation_value_with_updated_source(rep, evaluation, oldValue, 1, process)
68
- evaluation.destroy
69
- end
65
+ srn, evaluation = find_srn_and_evaluation(reputation_name, source, args.first)
66
+ delete_evaluation_without_validation(srn, evaluation) if evaluation
70
67
  end
71
68
 
72
69
  def delete_evaluation!(reputation_name, source, *args)
73
- raise ArgumentError, "#{reputation_name.to_s} is not defined for #{self.class.name}" unless ReputationSystem::Network.has_reputation_for?(self.class.name, reputation_name)
74
- scope = args.first
75
- srn = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
76
- evaluation = RSEvaluation.find_by_reputation_name_and_source_and_target(srn, source, self)
77
- if evaluation.nil?
78
- raise ArgumentError, "Given instance of #{source.class.name} has not evaluated #{reputation_name} of the instance of #{self.class.name} yet."
79
- else
80
- process = ReputationSystem::Network.get_reputation_def(self.class.name, srn)[:aggregated_by]
81
- oldValue = evaluation.value
82
- evaluation.value = process == :product ? 1 : 0
83
- rep = RSReputation.find_by_reputation_name_and_target(srn, self)
84
- RSReputation.update_reputation_value_with_updated_source(rep, evaluation, oldValue, 1, process)
85
- evaluation.destroy
86
- end
70
+ srn, evaluation = find_srn_and_evaluation!(reputation_name, source, args.first)
71
+ delete_evaluation_without_validation(srn, evaluation)
87
72
  end
88
73
 
89
74
  def increase_evaluation(reputation_name, value, source, *args)
@@ -95,6 +80,33 @@ module ReputationSystem
95
80
  end
96
81
 
97
82
  protected
83
+ def find_srn_and_evaluation(reputation_name, source, scope)
84
+ srn = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
85
+ evaluation = RSEvaluation.find_by_reputation_name_and_source_and_target(srn, source, self)
86
+ return srn, evaluation
87
+ end
88
+
89
+ def find_srn_and_evaluation!(reputation_name, source, scope)
90
+ srn = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
91
+ evaluation = find_evaluation!(reputation_name, srn, source)
92
+ return srn, evaluation
93
+ end
94
+
95
+ def find_evaluation!(reputation_name, srn, source)
96
+ evaluation = RSEvaluation.find_by_reputation_name_and_source_and_target(srn, source, self)
97
+ raise ArgumentError, "Given instance of #{source.class.name} has not evaluated #{reputation_name} of the instance of #{self.class.name} yet." unless evaluation
98
+ evaluation
99
+ end
100
+
101
+ def delete_evaluation_without_validation(srn, evaluation)
102
+ process = ReputationSystem::Network.get_reputation_def(self.class.name, srn)[:aggregated_by]
103
+ oldValue = evaluation.value
104
+ evaluation.value = process == :product ? 1 : 0
105
+ rep = RSReputation.find_by_reputation_name_and_target(srn, self)
106
+ RSReputation.update_reputation_value_with_updated_source(rep, evaluation, oldValue, 1, process)
107
+ evaluation.destroy
108
+ end
109
+
98
110
  def change_evaluation_value_by(reputation_name, value, source, *args)
99
111
  scope = args.first
100
112
  srn = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
@@ -82,6 +82,7 @@ module ReputationSystem
82
82
  end
83
83
 
84
84
  def get_scoped_reputation_name(class_name, reputation_name, scope)
85
+ raise ArgumentError, "#{reputation_name.to_s} is not defined for #{class_name}" unless has_reputation_for?(class_name, reputation_name)
85
86
  scope = scope.to_sym if scope
86
87
  validate_scope_necessity(class_name, reputation_name, scope)
87
88
  validate_scope_existence(class_name, reputation_name, scope)
@@ -92,13 +93,12 @@ module ReputationSystem
92
93
  source = get_reputation_def(target.class.name, reputation_name)[:source]
93
94
  if source.is_a?(Array)
94
95
  source.each do |s|
95
- scope = target.evaluate_reputation_scope(s[:scope]) if s[:scope]
96
- of = target.get_attributes_of(s)
97
- srn = get_scoped_reputation_name((of.is_a?(Array) ? of[0] : of ).class.name, s[:reputation], scope)
98
- source = s if srn.to_sym == source_name.to_sym
96
+ srn = get_scoped_reputation_name_from_source_def_and_target(s, target)
97
+ return s[:weight] if srn.to_sym == source_name.to_sym
99
98
  end
99
+ else
100
+ source[:weight]
100
101
  end
101
- source[:weight]
102
102
  end
103
103
 
104
104
  protected
@@ -113,34 +113,44 @@ module ReputationSystem
113
113
 
114
114
  def create_scoped_reputation_def(class_name, reputation_name, scope, options)
115
115
  raise ArgumentError, "#{reputation_name} does not have scope." unless has_scopes?(class_name, reputation_name)
116
- scope_options = {}
116
+ scope_options = options.reject { |k, v| ![:source, :aggregated_by].include? k }
117
117
  reputation_def = get_reputation_def(class_name, reputation_name)
118
- if is_primary_reputation?(class_name, reputation_name)
119
- scope_options[:source] = options[:source]
120
- else
118
+ unless is_primary_reputation?(class_name, reputation_name)
121
119
  scope_options[:source] = []
122
- reputation_def[:source].each do |s|
123
- rep = {}
124
- rep[:reputation] = s[:reputation]
125
- # Passing "this" is not pretty but in some case "instance_exec" method
126
- # does not give right context for some reason.
127
- # This could be ruby bug. Needs further investigation.
128
- rep[:of] = lambda { |this| instance_exec(this, scope.to_s, &s[:of]) } if s[:of].is_a? Proc
129
- scope_options[:source].push rep
130
- end
120
+ reputation_def[:source].each { |sd| scope_options[:source].push create_source_reputation_def(sd, scope) }
131
121
  end
132
- source_of = reputation_def[:source_of]
133
- source_of.each do |so|
134
- if so[:defined_for_scope].nil? || (so[:defined_for_scope] && so[:defined_for_scope].include?(scope.to_sym))
122
+ (reputation_def[:source_of] || []).each do |so|
123
+ if source_of_defined_for_scope?(so, scope)
135
124
  scope_options[:source_of] ||= []
136
125
  scope_options[:source_of].push so
137
126
  end
138
- end if source_of
139
- scope_options[:aggregated_by] = options[:aggregated_by]
127
+ end
140
128
  srn = get_scoped_reputation_name(class_name, reputation_name, scope)
141
129
  network[class_name.to_sym][srn.to_sym] = scope_options
142
130
  end
143
131
 
132
+ def create_source_reputation_def(source_def, scope)
133
+ rep = {}
134
+ rep[:reputation] = source_def[:reputation]
135
+ # Passing "this" is not pretty but in some case "instance_exec" method
136
+ # does not give right context for some reason.
137
+ # This could be ruby bug. Needs further investigation.
138
+ rep[:of] = lambda { |this| instance_exec(this, scope.to_s, &source_def[:of]) } if source_def[:of].is_a? Proc
139
+ rep
140
+ end
141
+
142
+ def get_scoped_reputation_name_from_source_def_and_target(source_def, target)
143
+ scope = target.evaluate_reputation_scope(source_def[:scope]) if source_def[:scope]
144
+ of = target.get_attributes_of(source_def)
145
+ class_name = (of.is_a?(Array) ? of[0] : of).class.name
146
+ get_scoped_reputation_name(class_name, source_def[:reputation], scope)
147
+ end
148
+
149
+ def source_of_defined_for_scope?(source_of_def, scope)
150
+ defined_for_scope = source_of_def[:defined_for_scope]
151
+ defined_for_scope.nil? || (defined_for_scope && defined_for_scope.include?(scope.to_sym))
152
+ end
153
+
144
154
  def construct_scoped_reputation_options(class_name, reputation_name, options)
145
155
  scopes = get_reputation_def(class_name, reputation_name)[:scopes]
146
156
  scopes.each do |scope|
@@ -149,20 +159,36 @@ module ReputationSystem
149
159
  end
150
160
 
151
161
  def derive_source_of_from_source(class_name, reputation_name, source, src_class_name)
152
- if source[:of] && source[:of].is_a?(Symbol) && source[:of] != :self
153
- klass = src_class_name.to_s.constantize
154
- of_value = class_name.tableize
155
- of_value = of_value.chomp('s') unless klass.instance_methods.include?(of_value.to_s) || klass.instance_methods.include?(of_value.to_sym)
156
- else
157
- of_value = "self"
158
- end
162
+ of_value = derive_of_value(class_name, source[:of], src_class_name)
159
163
  reputation_def = get_reputation_def(src_class_name, source[:reputation])
160
164
  reputation_def[:source_of] ||= []
161
- unless reputation_def[:source_of].any? {|elem| elem[:reputation] == reputation_name.to_sym}
165
+ unless source_of_include_reputation?(reputation_def[:source_of], reputation_name)
162
166
  reputation_def[:source_of] << {:reputation => reputation_name.to_sym, :of => of_value.to_sym}
163
167
  end
164
168
  end
165
169
 
170
+ def derive_of_value(class_name, source_of, src_class_name)
171
+ if not_source_of_self?(source_of)
172
+ attr = class_name.tableize
173
+ class_has_attribute?(src_class_name, attr) ? attr : attr.chomp('s')
174
+ else
175
+ "self"
176
+ end
177
+ end
178
+
179
+ def not_source_of_self?(source_of)
180
+ source_of && source_of.is_a?(Symbol) && source_of != :self
181
+ end
182
+
183
+ def class_has_attribute?(class_name, attribute)
184
+ klass = class_name.to_s.constantize
185
+ klass.instance_methods.include?(attribute.to_s) || klass.instance_methods.include?(attribute.to_sym)
186
+ end
187
+
188
+ def source_of_include_reputation?(source_of, reputation_name)
189
+ source_of.map { |rep| rep[:reputation] }.include?(reputation_name.to_sym)
190
+ end
191
+
166
192
  def derive_source_of_from_source_later(class_name, reputation_name, source, src_class_name)
167
193
  reputation = source[:reputation].to_sym
168
194
  src_class_name = src_class_name.to_sym
@@ -17,17 +17,32 @@
17
17
  module ReputationSystem
18
18
  module Reputation
19
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
20
+ find_reputation(reputation_name, args.first).value
21
+ end
22
+
23
+ def normalized_reputation_value_for(reputation_name, *args)
24
+ find_reputation(reputation_name, args.first).normalized_value
25
+ end
26
+
27
+ def activate_all_reputations
28
+ RSReputation.find(:all, :conditions => {:target_id => self.id, :target_type => self.class.name, :active => false}).each do |r|
29
+ r.active = true
30
+ r.save!
31
+ end
32
+ end
33
+
34
+ def deactivate_all_reputations
35
+ RSReputation.find(:all, :conditions => {:target_id => self.id, :target_type => self.class.name, :active => true}).each do |r|
36
+ r.active = false
37
+ r.save!
28
38
  end
29
39
  end
30
40
 
41
+ def reputations_activated?(reputation_name)
42
+ r = RSReputation.find(:first, :conditions => {:reputation_name => reputation_name.to_s, :target_id => self.id, :target_type => self.class.name})
43
+ r ? r.active : false
44
+ end
45
+
31
46
  def rank_for(reputation_name, *args)
32
47
  scope = args.first
33
48
  my_value = self.reputation_value_for(reputation_name, scope)
@@ -35,5 +50,13 @@ module ReputationSystem
35
50
  :conditions => ["rs_reputations.value > ?", my_value]
36
51
  ) + 1
37
52
  end
53
+
54
+ protected
55
+ def find_reputation(reputation_name, scope)
56
+ raise ArgumentError, "#{reputation_name} is not valid" if !self.class.has_reputation_for?(reputation_name)
57
+ srn = ReputationSystem::Network.get_scoped_reputation_name(self.class.name, reputation_name, scope)
58
+ process = ReputationSystem::Network.get_reputation_def(self.class.name, srn)[:aggregated_by]
59
+ RSReputation.find_or_create_reputation(srn, self, process)
60
+ end
38
61
  end
39
- end
62
+ end
@@ -15,5 +15,5 @@
15
15
  ##
16
16
 
17
17
  module ReputationSystem
18
- VERSION = "1.2.1"
18
+ VERSION = "1.3.0"
19
19
  end
@@ -26,9 +26,55 @@ describe ActiveRecord::Base do
26
26
  end
27
27
 
28
28
  context "Primary Reputation" do
29
+ describe "#evaluated_by" do
30
+ it "should return an empty array if it is not evaluaated by a given source" do
31
+ Question.evaluated_by(:total_votes, @user).should == []
32
+ end
33
+
34
+ it "should return an array of targets evaluated by a given source" do
35
+ user2 = User.create!(:name => 'katsuya')
36
+ question2 = Question.create!(:text => 'Question 2', :author_id => @user.id)
37
+ question3 = Question.create!(:text => 'Question 3', :author_id => @user.id)
38
+ @question.add_evaluation(:total_votes, 1, @user).should be_true
39
+ question2.add_evaluation(:total_votes, 2, user2).should be_true
40
+ question3.add_evaluation(:total_votes, 3, @user).should be_true
41
+ Question.evaluated_by(:total_votes, @user).should == [@question, question3]
42
+ Question.evaluated_by(:total_votes, user2).should == [question2]
43
+ end
44
+
45
+ context "With Scopes" do
46
+ it "should return an array of targets evaluated by a given source on appropriate scope" do
47
+ user2 = User.create!(:name => 'katsuya')
48
+ phrase2 = Phrase.create!(:text => "Two")
49
+ @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be_true
50
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
51
+ @phrase.add_evaluation(:difficulty_with_scope, 3, user2, :s2).should be_true
52
+ @phrase.add_evaluation(:difficulty_with_scope, 4, user2, :s3).should be_true
53
+ phrase2.add_evaluation(:difficulty_with_scope, 1, user2, :s1).should be_true
54
+ phrase2.add_evaluation(:difficulty_with_scope, 2, user2, :s2).should be_true
55
+ phrase2.add_evaluation(:difficulty_with_scope, 3, @user, :s2).should be_true
56
+ phrase2.add_evaluation(:difficulty_with_scope, 4, @user, :s3).should be_true
57
+ Phrase.evaluated_by(:difficulty_with_scope, @user, :s1).should == [@phrase]
58
+ Phrase.evaluated_by(:difficulty_with_scope, user2, :s1).should == [phrase2]
59
+ Phrase.evaluated_by(:difficulty_with_scope, @user, :s2).should == [@phrase, phrase2]
60
+ Phrase.evaluated_by(:difficulty_with_scope, user2, :s2).should == [@phrase, phrase2]
61
+ Phrase.evaluated_by(:difficulty_with_scope, @user, :s3).should == [phrase2]
62
+ Phrase.evaluated_by(:difficulty_with_scope, user2, :s3).should == [@phrase]
63
+ end
64
+
65
+ it "should raise exception if invalid scope is given" do
66
+ lambda{@phrase.add_evaluation(:difficulty_with_scope, 1, :invalid_scope)}.should raise_error(ArgumentError)
67
+ end
68
+
69
+ it "should raise exception if scope is not given" do
70
+ lambda{@phrase.add_evaluation(:difficulty_with_scope, 1)}.should raise_error(ArgumentError)
71
+ end
72
+ end
73
+ end
74
+
29
75
  describe "#add_evaluation" do
30
76
  it "should create evaluation in case of valid input" do
31
- @question.add_evaluation(:total_votes, 1, @user)
77
+ @question.add_evaluation(:total_votes, 1, @user).should be_true
32
78
  @question.reputation_value_for(:total_votes).should == 1
33
79
  end
34
80
 
@@ -48,8 +94,8 @@ describe ActiveRecord::Base do
48
94
 
49
95
  context "With Scopes" do
50
96
  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)
97
+ @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be_true
98
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
53
99
  @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 1
54
100
  @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 2
55
101
  @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
@@ -67,30 +113,30 @@ describe ActiveRecord::Base do
67
113
 
68
114
  describe "#add_or_update_evaluation" do
69
115
  it "should create evaluation if it does not exist" do
70
- @question.add_or_update_evaluation(:total_votes, 1, @user)
116
+ @question.add_or_update_evaluation(:total_votes, 1, @user).should be_true
71
117
  @question.reputation_value_for(:total_votes).should == 1
72
118
  end
73
119
 
74
120
  it "should update evaluation if it exists already" do
75
121
  @question.add_evaluation(:total_votes, 1, @user)
76
- @question.add_or_update_evaluation(:total_votes, 2, @user)
122
+ @question.add_or_update_evaluation(:total_votes, 2, @user).should be_true
77
123
  @question.reputation_value_for(:total_votes).should == 2
78
124
  end
79
125
 
80
126
  context "With Scopes" do
81
127
  it "should add evaluation on appropriate scope if it does not exist" do
82
- @phrase.add_or_update_evaluation(:difficulty_with_scope, 1, @user, :s1)
83
- @phrase.add_or_update_evaluation(:difficulty_with_scope, 2, @user, :s2)
128
+ @phrase.add_or_update_evaluation(:difficulty_with_scope, 1, @user, :s1).should be_true
129
+ @phrase.add_or_update_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
84
130
  @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 1
85
131
  @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 2
86
132
  @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
87
133
  end
88
134
 
89
135
  it "should update evaluation on appropriate scope if it exists already" do
90
- @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1)
91
- @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2)
92
- @phrase.add_or_update_evaluation(:difficulty_with_scope, 3, @user, :s1)
93
- @phrase.add_or_update_evaluation(:difficulty_with_scope, 5, @user, :s2)
136
+ @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be_true
137
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
138
+ @phrase.add_or_update_evaluation(:difficulty_with_scope, 3, @user, :s1).should be_true
139
+ @phrase.add_or_update_evaluation(:difficulty_with_scope, 5, @user, :s2).should be_true
94
140
  @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 3
95
141
  @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 5
96
142
  @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
@@ -104,7 +150,7 @@ describe ActiveRecord::Base do
104
150
  end
105
151
 
106
152
  it "should update evaluation in case of valid input" do
107
- @question.update_evaluation(:total_votes, 2, @user)
153
+ @question.update_evaluation(:total_votes, 2, @user).should be_true
108
154
  @question.reputation_value_for(:total_votes).should == 2
109
155
  end
110
156
 
@@ -122,11 +168,11 @@ describe ActiveRecord::Base do
122
168
 
123
169
  context "With Scopes" do
124
170
  before :each do
125
- @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2)
171
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
126
172
  end
127
173
 
128
174
  it "should update evaluation on appropriate scope" do
129
- @phrase.update_evaluation(:difficulty_with_scope, 5, @user, :s2)
175
+ @phrase.update_evaluation(:difficulty_with_scope, 5, @user, :s2).should be_true
130
176
  @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 0
131
177
  @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 5
132
178
  @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
@@ -192,7 +238,7 @@ describe ActiveRecord::Base do
192
238
  end
193
239
 
194
240
  it "should delete evaluation in case of valid input" do
195
- @question.delete_evaluation(:total_votes, @user)
241
+ @question.delete_evaluation(:total_votes, @user).should be_true
196
242
  @question.reputation_value_for(:total_votes).should == 0
197
243
  end
198
244
 
@@ -210,7 +256,7 @@ describe ActiveRecord::Base do
210
256
  end
211
257
 
212
258
  it "should delete evaluation on appropriate scope" do
213
- @phrase.delete_evaluation(:difficulty_with_scope, @user, :s2)
259
+ @phrase.delete_evaluation(:difficulty_with_scope, @user, :s2).should be_true
214
260
  @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 0
215
261
  @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 0
216
262
  @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
@@ -228,13 +274,13 @@ describe ActiveRecord::Base do
228
274
 
229
275
  describe "#increase_evaluation" do
230
276
  it "should add evaluation if it does not exist" do
231
- @question.increase_evaluation(:total_votes, 2, @user)
277
+ @question.increase_evaluation(:total_votes, 2, @user).should be_true
232
278
  @question.reputation_value_for(:total_votes).should == 2
233
279
  end
234
280
 
235
281
  it "should increase evaluation if it exists already" do
236
282
  @question.add_evaluation(:total_votes, 1, @user)
237
- @question.increase_evaluation(:total_votes, 2, @user)
283
+ @question.increase_evaluation(:total_votes, 2, @user).should be_true
238
284
  @question.reputation_value_for(:total_votes).should == 3
239
285
  end
240
286
 
@@ -244,7 +290,7 @@ describe ActiveRecord::Base do
244
290
  end
245
291
 
246
292
  it "should increase evaluation on appropriate scope" do
247
- @phrase.increase_evaluation(:difficulty_with_scope, 5, @user, :s2)
293
+ @phrase.increase_evaluation(:difficulty_with_scope, 5, @user, :s2).should be_true
248
294
  @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 0
249
295
  @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == 7
250
296
  @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
@@ -254,13 +300,13 @@ describe ActiveRecord::Base do
254
300
 
255
301
  describe "#decrease_evaluation" do
256
302
  it "should add evaluation if it does not exist" do
257
- @question.decrease_evaluation(:total_votes, 2, @user)
303
+ @question.decrease_evaluation(:total_votes, 2, @user).should be_true
258
304
  @question.reputation_value_for(:total_votes).should == -2
259
305
  end
260
306
 
261
307
  it "should increase evaluation if it exists already" do
262
308
  @question.add_evaluation(:total_votes, 1, @user)
263
- @question.decrease_evaluation(:total_votes, 2, @user)
309
+ @question.decrease_evaluation(:total_votes, 2, @user).should be_true
264
310
  @question.reputation_value_for(:total_votes).should == -1
265
311
  end
266
312
 
@@ -269,8 +315,8 @@ describe ActiveRecord::Base do
269
315
  @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2)
270
316
  end
271
317
 
272
- it "should increase evaluation on appropriate scope" do
273
- @phrase.decrease_evaluation(:difficulty_with_scope, 5, @user, :s2)
318
+ it "should decrease evaluation on appropriate scope" do
319
+ @phrase.decrease_evaluation(:difficulty_with_scope, 5, @user, :s2).should be_true
274
320
  @phrase.reputation_value_for(:difficulty_with_scope, :s1).should == 0
275
321
  @phrase.reputation_value_for(:difficulty_with_scope, :s2).should == -3
276
322
  @phrase.reputation_value_for(:difficulty_with_scope, :s3).should == 0
@@ -116,4 +116,47 @@ describe ActiveRecord::Base do
116
116
  end
117
117
  end
118
118
  end
119
+
120
+ context "Normalization" do
121
+ describe "#normalized_reputation_value_for" do
122
+ it "should return 0 as if there is no data" do
123
+ @question.normalized_reputation_value_for(:total_votes).should == 0
124
+ end
125
+
126
+ it "should return appropriate value in case of valid input" do
127
+ question2 = Question.create!(:text => 'Does this work too?', :author_id => @user.id)
128
+ question3 = Question.create!(:text => 'Does this work too?', :author_id => @user.id)
129
+ @question.add_evaluation(:total_votes, 1, @user)
130
+ question2.add_evaluation(:total_votes, 2, @user)
131
+ question3.add_evaluation(:total_votes, 3, @user)
132
+ @question.normalized_reputation_value_for(:total_votes).should == 0
133
+ question2.normalized_reputation_value_for(:total_votes).should == 0.5
134
+ question3.normalized_reputation_value_for(:total_votes).should == 1
135
+ end
136
+
137
+ it "should raise exception if invalid reputation name is given" do
138
+ lambda {@question.normalized_reputation_value_for(:invalid)}.should raise_error(ArgumentError)
139
+ end
140
+
141
+ it "should raise exception if scope is given for reputation with no scopes" do
142
+ lambda {@question.normalized_reputation_value_for(:difficulty, :s1)}.should raise_error(ArgumentError)
143
+ end
144
+
145
+ it "should raise exception if scope is not given for reputation with scopes" do
146
+ lambda {@phrase.normalized_reputation_value_for(:difficulty_with_scope)}.should raise_error(ArgumentError)
147
+ end
148
+ end
149
+
150
+ describe "#exclude_all_reputations_for_normalization" do
151
+ it "should activate all reputation" do
152
+ @question2 = Question.create!(:text => 'Does this work??', :author_id => @user.id)
153
+ @question2.add_evaluation(:total_votes, 70, @user)
154
+ @question.add_evaluation(:total_votes, 100, @user)
155
+ @question.deactivate_all_reputations
156
+ RSReputation.maximum(:value, :conditions => {:reputation_name => 'total_votes', :active => true}).should == 70
157
+ @question.activate_all_reputations
158
+ RSReputation.maximum(:value, :conditions => {:reputation_name => 'total_votes', :active => true}).should == 100
159
+ end
160
+ end
161
+ end
119
162
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-reputation-system
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-14 00:00:00.000000000 Z
12
+ date: 2012-08-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
- requirement: &70099784737000 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70099784737000
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rake
27
- requirement: &70099784736120 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: 0.8.7
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70099784736120
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.8.7
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: rspec
38
- requirement: &70099784735280 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ~>
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '2.8'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70099784735280
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.8'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rdoc
49
- requirement: &70099784734240 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70099784734240
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: database_cleaner
60
- requirement: &70099790085800 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ~>
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: 0.7.1
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *70099790085800
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.7.1
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: sqlite3
71
- requirement: &70099790085300 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ~>
@@ -76,7 +101,12 @@ dependencies:
76
101
  version: 1.3.5
77
102
  type: :development
78
103
  prerelease: false
79
- version_requirements: *70099790085300
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 1.3.5
80
110
  description: ActiveRecord Reputation System gem allows rails apps to compute and publish
81
111
  reputation scores for active record models.
82
112
  email:
@@ -99,7 +129,6 @@ files:
99
129
  - lib/reputation_system/base.rb
100
130
  - lib/reputation_system/evaluation.rb
101
131
  - lib/reputation_system/network.rb
102
- - lib/reputation_system/normalization.rb
103
132
  - lib/reputation_system/query.rb
104
133
  - lib/reputation_system/reputation.rb
105
134
  - lib/reputation_system/scope.rb
@@ -111,7 +140,6 @@ files:
111
140
  - spec/reputation_system/base_spec.rb
112
141
  - spec/reputation_system/evaluation_spec.rb
113
142
  - spec/reputation_system/network_spec.rb
114
- - spec/reputation_system/normalization_spec.rb
115
143
  - spec/reputation_system/query_spec.rb
116
144
  - spec/reputation_system/reputation_spec.rb
117
145
  - spec/reputation_system/scope_spec.rb
@@ -128,15 +156,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
128
156
  - - ! '>='
129
157
  - !ruby/object:Gem::Version
130
158
  version: '0'
159
+ segments:
160
+ - 0
161
+ hash: 1595828597124955977
131
162
  required_rubygems_version: !ruby/object:Gem::Requirement
132
163
  none: false
133
164
  requirements:
134
165
  - - ! '>='
135
166
  - !ruby/object:Gem::Version
136
167
  version: '0'
168
+ segments:
169
+ - 0
170
+ hash: 1595828597124955977
137
171
  requirements: []
138
172
  rubyforge_project:
139
- rubygems_version: 1.8.17
173
+ rubygems_version: 1.8.24
140
174
  signing_key:
141
175
  specification_version: 3
142
176
  summary: ActiveRecord Reputation System gem allows rails apps to compute and publish
@@ -1,50 +0,0 @@
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 Normalization
19
- def normalized_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.normalized_value
28
- end
29
- end
30
-
31
- def activate_all_reputations
32
- RSReputation.find(:all, :conditions => {:target_id => self.id, :target_type => self.class.name, :active => false}).each do |r|
33
- r.active = true
34
- r.save!
35
- end
36
- end
37
-
38
- def deactivate_all_reputations
39
- RSReputation.find(:all, :conditions => {:target_id => self.id, :target_type => self.class.name, :active => true}).each do |r|
40
- r.active = false
41
- r.save!
42
- end
43
- end
44
-
45
- def reputations_activated?(reputation_name)
46
- r = RSReputation.find(:first, :conditions => {:reputation_name => reputation_name.to_s, :target_id => self.id, :target_type => self.class.name})
47
- r ? r.active : false
48
- end
49
- end
50
- end
@@ -1,68 +0,0 @@
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
- describe "#normalized_reputation_value_for" do
29
- it "should return 0 as if there is no data" do
30
- @question.normalized_reputation_value_for(:total_votes).should == 0
31
- end
32
-
33
- it "should return appropriate value in case of valid input" do
34
- question2 = Question.create!(:text => 'Does this work too?', :author_id => @user.id)
35
- question3 = Question.create!(:text => 'Does this work too?', :author_id => @user.id)
36
- @question.add_evaluation(:total_votes, 1, @user)
37
- question2.add_evaluation(:total_votes, 2, @user)
38
- question3.add_evaluation(:total_votes, 3, @user)
39
- @question.normalized_reputation_value_for(:total_votes).should == 0
40
- question2.normalized_reputation_value_for(:total_votes).should == 0.5
41
- question3.normalized_reputation_value_for(:total_votes).should == 1
42
- end
43
-
44
- it "should raise exception if invalid reputation name is given" do
45
- lambda {@question.normalized_reputation_value_for(:invalid)}.should raise_error(ArgumentError)
46
- end
47
-
48
- it "should raise exception if scope is given for reputation with no scopes" do
49
- lambda {@question.normalized_reputation_value_for(:difficulty, :s1)}.should raise_error(ArgumentError)
50
- end
51
-
52
- it "should raise exception if scope is not given for reputation with scopes" do
53
- lambda {@phrase.normalized_reputation_value_for(:difficulty_with_scope)}.should raise_error(ArgumentError)
54
- end
55
- end
56
-
57
- describe "#exclude_all_reputations_for_normalization" do
58
- it "should activate all reputation" do
59
- @question2 = Question.create!(:text => 'Does this work??', :author_id => @user.id)
60
- @question2.add_evaluation(:total_votes, 70, @user)
61
- @question.add_evaluation(:total_votes, 100, @user)
62
- @question.deactivate_all_reputations
63
- RSReputation.maximum(:value, :conditions => {:reputation_name => 'total_votes', :active => true}).should == 70
64
- @question.activate_all_reputations
65
- RSReputation.maximum(:value, :conditions => {:reputation_name => 'total_votes', :active => true}).should == 100
66
- end
67
- end
68
- end