activerecord-reputation-system 2.0.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 357cba79dc17693f888aa559b94301e9cc6a0c39
4
+ data.tar.gz: 86542de25746208e733f163c661ec9b7be90ba2c
5
+ SHA512:
6
+ metadata.gz: 9656e9ca24b2a70661ef53336b6c96af676c1aa5d2d556267d223caf57aae0ff49fd79aa5e9feacda5ec0f16a1f2d80d7f1fc20d3c3e167023263e385c33d0c5
7
+ data.tar.gz: acc3482e4ea8e3d485d605fd711eecd7f7a70920049cb638472f4a532acb11f183dce97e374e32ec8e4e3c3c24e08c311c113648eb7f112543209ec210a00234
data/README.md CHANGED
@@ -91,6 +91,38 @@ You can get target records that have been evaluated by a given source record:
91
91
  Question.evaluated_by(:votes, @user) #=> [@question]
92
92
  ```
93
93
 
94
+ You can use a custom aggregation function, which is a feature available on this fork, but not on the original implementation.
95
+ You just need to provide the name of the method on the :aggregated_by option, and implement this method on the model.
96
+ On the example below, our aggregation function sums all values and multiply by ten:
97
+ ```ruby
98
+ class Answer < ActiveRecord::Base
99
+ belongs_to :author, :class_name => 'User'
100
+ belongs_to :question
101
+
102
+ has_reputation :custom_rating,
103
+ :source => :user,
104
+ :aggregated_by => :custom_aggregation
105
+
106
+ def custom_aggregation(*args)
107
+ rep, source, weight = args[0..2]
108
+
109
+ # Ruby doesn't support method overloading, so let's handle parameters on a condition
110
+
111
+ # For a new source, these are the input parameters:
112
+ # rep, source, weight
113
+ if args.length === 3
114
+ rep.value + weight * source.value * 10
115
+
116
+ # For an updated source, these are the input parameters:
117
+ # rep, source, weight, oldValue, newSize
118
+ elsif args.length === 5
119
+ oldValue, newSize = args[3..4]
120
+ rep.value + (source.value - oldValue) * 10
121
+ end
122
+ end
123
+ end
124
+ ```
125
+
94
126
  ## Documentation
95
127
 
96
128
  Please refer [Wiki](https://github.com/twitter/activerecord-reputation-system/wiki) for available APIs and more information.
@@ -106,6 +138,7 @@ Katsuya Noguchi
106
138
  1. [NARKOZ (Nihad Abbasov)](https://github.com/NARKOZ) - 4 commits
107
139
  2. [elitheeli (Eli Fox-Epstein)](https://github.com/elitheeli) - 1 commit
108
140
  3. [amrnt (Amr Tamimi)](https://github.com/amrnt) - 1 commit
141
+ 4. [caiosba (Caio Almeida)](https://github.com/caiosba) - 1 commit
109
142
 
110
143
  ## Related Links
111
144
 
@@ -37,6 +37,8 @@ class ReputationSystemGenerator < Rails::Generators::Base
37
37
  create_migration_file_if_not_exist 'change_evaluations_index_to_unique'
38
38
  create_migration_file_if_not_exist 'change_reputation_messages_index_to_unique'
39
39
  create_migration_file_if_not_exist 'change_reputations_index_to_unique'
40
+ create_migration_file_if_not_exist 'add_data_to_reputations'
41
+ create_migration_file_if_not_exist 'add_data_to_evaluations'
40
42
  end
41
43
 
42
44
  private
@@ -0,0 +1,9 @@
1
+ class AddDataToEvaluations < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rs_evaluations, :data, :text
4
+ end
5
+
6
+ def self.down
7
+ remove_column :rs_evaluations, :data
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class AddDataToReputations < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rs_reputations, :data, :text
4
+ end
5
+
6
+ def self.down
7
+ remove_column :rs_reputations, :data
8
+ end
9
+ end
@@ -14,6 +14,7 @@
14
14
  # limitations under the License.
15
15
  ##
16
16
 
17
+ require 'protected_attributes'
17
18
  require 'reputation_system/base'
18
19
  require 'reputation_system/query_methods'
19
20
  require 'reputation_system/finder_methods'
@@ -22,7 +22,8 @@ module ReputationSystem
22
22
 
23
23
  def get_attributes_of(reputation)
24
24
  of = reputation[:of]
25
- attrs = reputation[:of] == :self ? self : self.instance_eval(of.to_s) if of.is_a?(String) || of.is_a?(Symbol)
25
+ attrs = (of == :self) ? self : self.instance_eval(of.to_s) if of.is_a?(String) || of.is_a?(Symbol)
26
+ attrs = attrs.to_a if attrs.is_a?(ActiveRecord::Associations::CollectionProxy)
26
27
  attrs = self.instance_exec(self, &of) if of.is_a?(Proc)
27
28
  attrs = [attrs] unless attrs.is_a? Array
28
29
  attrs.compact
@@ -25,7 +25,7 @@ module ReputationSystem
25
25
  options[:select] ||= sanitize_sql_array(["%s.*", self.table_name])
26
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
27
  options[:joins] = sanitize_sql_array([options[:joins], self.table_name])
28
- find(:all, options)
28
+ joins(options[:joins]).select(options[:select])
29
29
  end
30
30
  end
31
31
 
@@ -27,7 +27,7 @@ module FinderMethods
27
27
  options[:select] = build_select_statement(table_name, reputation_name, options[:select])
28
28
  options[:joins] = build_join_statement(table_name, name, srn, options[:joins])
29
29
  options[:conditions] = build_condition_statement(reputation_name, options[:conditions])
30
- find(find_scope, options)
30
+ joins(options[:joins]).select(options[:select]).where(options[:conditions]).send(find_scope)
31
31
  end
32
32
 
33
33
  def count_with_reputation(*args)
@@ -35,7 +35,7 @@ module FinderMethods
35
35
  options[:joins] = build_join_statement(table_name, name, srn, options[:joins])
36
36
  options[:conditions] = build_condition_statement(reputation_name, options[:conditions])
37
37
  options[:conditions][0].gsub!(reputation_name.to_s, "COALESCE(rs_reputations.value, 0)")
38
- count(find_scope, options)
38
+ joins(options[:joins]).select(options[:select]).where(options[:conditions]).send(find_scope).count
39
39
  end
40
40
 
41
41
  def find_with_normalized_reputation(*args)
@@ -43,7 +43,7 @@ module FinderMethods
43
43
  options[:select] = build_select_statement(table_name, reputation_name, options[:select], srn, true)
44
44
  options[:joins] = build_join_statement(table_name, name, srn, options[:joins])
45
45
  options[:conditions] = build_condition_statement(reputation_name, options[:conditions], srn, true)
46
- find(find_scope, options)
46
+ joins(options[:joins]).select(options[:select]).where(options[:conditions]).send(find_scope)
47
47
  end
48
48
 
49
49
  def find_with_reputation_sql(*args)
@@ -53,8 +53,10 @@ module FinderMethods
53
53
  options[:conditions] = build_condition_statement(reputation_name, options[:conditions])
54
54
  if respond_to?(:construct_finder_sql, true)
55
55
  construct_finder_sql(options)
56
- else
56
+ elsif respond_to?(:construct_finder_arel, true)
57
57
  construct_finder_arel(options).to_sql
58
+ else
59
+ joins(options[:joins]).select(options[:select]).where(options[:conditions]).send(find_scope).to_sql
58
60
  end
59
61
  end
60
62
 
@@ -31,15 +31,17 @@ module ReputationSystem
31
31
  validates_uniqueness_of :source_id, :scope => [:reputation_name, :source_type, :target_id, :target_type]
32
32
  validate :source_must_be_defined_for_reputation_in_network
33
33
 
34
+ serialize :data, Hash
35
+
34
36
  def self.find_by_reputation_name_and_source_and_target(reputation_name, source, target)
35
37
  source_type = get_source_type_for_sti(source.class.name, target.class.name, reputation_name)
36
- ReputationSystem::Evaluation.find(:first,
37
- :conditions => {:reputation_name => reputation_name.to_s,
38
- :source_id => source.id,
39
- :source_type => source_type,
40
- :target_id => target.id,
41
- :target_type => target.class.name
42
- })
38
+ ReputationSystem::Evaluation.where(
39
+ :reputation_name => reputation_name.to_s,
40
+ :source_id => source.id,
41
+ :source_type => source_type,
42
+ :target_id => target.id,
43
+ :target_type => target.class.name
44
+ ).first
43
45
  end
44
46
 
45
47
  def self.create_evaluation(reputation_name, value, source, target)
@@ -31,10 +31,10 @@ module ReputationSystem
31
31
  before_validation :set_target_type_for_sti
32
32
  before_save :change_zero_value_in_case_of_product_process
33
33
 
34
- VALID_PROCESSES = ['sum', 'average', 'product']
35
- validates_inclusion_of :aggregated_by, :in => VALID_PROCESSES, :message => "Value chosen for aggregated_by is not valid process"
36
34
  validates_uniqueness_of :reputation_name, :scope => [:target_id, :target_type]
37
35
 
36
+ serialize :data, Hash
37
+
38
38
  def self.find_by_reputation_name_and_target(reputation_name, target)
39
39
  target_type = get_target_type_for_sti(target, reputation_name)
40
40
  ReputationSystem::Reputation.find_by_reputation_name_and_target_id_and_target_type(reputation_name.to_s, target.id, target_type)
@@ -66,7 +66,11 @@ module ReputationSystem
66
66
  when :product
67
67
  rep.value *= (newValue * weight)
68
68
  else
69
- raise ArgumentError, "#{process} process is not supported yet"
69
+ if source.target.respond_to?(process)
70
+ rep.value = source.target.send(process, rep, source, weight)
71
+ else
72
+ raise ArgumentError, "#{process} process is not supported yet"
73
+ end
70
74
  end
71
75
  save_succeeded = rep.save
72
76
  ReputationSystem::ReputationMessage.add_reputation_message_if_not_exist(source, rep)
@@ -90,7 +94,11 @@ module ReputationSystem
90
94
  when :product
91
95
  rep.value = (rep.value * newValue) / oldValue
92
96
  else
93
- raise ArgumentError, "#{process} process is not supported yet"
97
+ if source.target.respond_to?(process)
98
+ rep.value = source.target.send(process, rep, source, weight, oldValue, newSize)
99
+ else
100
+ raise ArgumentError, "#{process} process is not supported yet"
101
+ end
94
102
  end
95
103
  end
96
104
  save_succeeded = rep.save
@@ -175,13 +183,11 @@ module ReputationSystem
175
183
  end
176
184
 
177
185
  def self.max(reputation_name, target_type)
178
- ReputationSystem::Reputation.maximum(:value,
179
- :conditions => {:reputation_name => reputation_name.to_s, :target_type => target_type, :active => true})
186
+ ReputationSystem::Reputation.where(:reputation_name => reputation_name.to_s, :target_type => target_type, :active => true).maximum(:value)
180
187
  end
181
188
 
182
189
  def self.min(reputation_name, target_type)
183
- ReputationSystem::Reputation.minimum(:value,
184
- :conditions => {:reputation_name => reputation_name.to_s, :target_type => target_type, :active => true})
190
+ ReputationSystem::Reputation.where(:reputation_name => reputation_name.to_s, :target_type => target_type, :active => true).minimum(:value)
185
191
  end
186
192
 
187
193
  def self.get_target_type_for_sti(target, reputation_name)
@@ -44,6 +44,6 @@ module ReputationSystem
44
44
  errors.add(:sender, "must be an evaluation or a reputation")
45
45
  end
46
46
  end
47
-
47
+
48
48
  end
49
49
  end
@@ -25,21 +25,21 @@ module ReputationSystem
25
25
  end
26
26
 
27
27
  def activate_all_reputations
28
- ReputationSystem::Reputation.find(:all, :conditions => {:target_id => self.id, :target_type => self.class.name, :active => false}).each do |r|
28
+ ReputationSystem::Reputation.where(:target_id => self.id, :target_type => self.class.name, :active => false).each do |r|
29
29
  r.active = true
30
30
  r.save!
31
31
  end
32
32
  end
33
33
 
34
34
  def deactivate_all_reputations
35
- ReputationSystem::Reputation.find(:all, :conditions => {:target_id => self.id, :target_type => self.class.name, :active => true}).each do |r|
35
+ ReputationSystem::Reputation.where(:target_id => self.id, :target_type => self.class.name, :active => true).each do |r|
36
36
  r.active = false
37
37
  r.save!
38
38
  end
39
39
  end
40
40
 
41
41
  def reputations_activated?(reputation_name)
42
- r = ReputationSystem::Reputation.find(:first, :conditions => {:reputation_name => reputation_name.to_s, :target_id => self.id, :target_type => self.class.name})
42
+ r = ReputationSystem::Reputation.where(:reputation_name => reputation_name.to_s, :target_id => self.id, :target_type => self.class.name).first
43
43
  r ? r.active : false
44
44
  end
45
45
 
@@ -15,5 +15,5 @@
15
15
  ##
16
16
 
17
17
  module ReputationSystem
18
- VERSION = "2.0.2"
18
+ VERSION = "3.0.0"
19
19
  end
@@ -30,20 +30,20 @@ describe ReputationSystem::EvaluationMethods do
30
30
  it "should return false if it has not already been evaluated by a given source" do
31
31
  user = User.create! :name => 'katsuya'
32
32
  @question.add_evaluation(:total_votes, 3, user)
33
- @question.has_evaluation?(:total_votes, @user).should be_false
33
+ @question.has_evaluation?(:total_votes, @user).should be false
34
34
  end
35
35
  it "should return true if it has been evaluated by a given source" do
36
36
  @question.add_evaluation(:total_votes, 3, @user)
37
- @question.has_evaluation?(:total_votes, @user).should be_true
37
+ @question.has_evaluation?(:total_votes, @user).should be true
38
38
  end
39
39
  context "With Scopes" do
40
40
  it "should return false if it has not already been evaluated by a given source" do
41
41
  @phrase.add_evaluation(:difficulty_with_scope, 3, @user, :s1)
42
- @phrase.has_evaluation?(:difficulty_with_scope, @user, :s2).should be_false
42
+ @phrase.has_evaluation?(:difficulty_with_scope, @user, :s2).should be false
43
43
  end
44
44
  it "should return true if it has been evaluated by a given source" do
45
45
  @phrase.add_evaluation(:difficulty_with_scope, 3, @user, :s1)
46
- @phrase.has_evaluation?(:difficulty_with_scope, @user, :s1).should be_true
46
+ @phrase.has_evaluation?(:difficulty_with_scope, @user, :s1).should be true
47
47
  end
48
48
  end
49
49
  end
@@ -57,9 +57,9 @@ describe ReputationSystem::EvaluationMethods do
57
57
  user2 = User.create!(:name => 'katsuya')
58
58
  question2 = Question.create!(:text => 'Question 2', :author_id => @user.id)
59
59
  question3 = Question.create!(:text => 'Question 3', :author_id => @user.id)
60
- @question.add_evaluation(:total_votes, 1, @user).should be_true
61
- question2.add_evaluation(:total_votes, 2, user2).should be_true
62
- question3.add_evaluation(:total_votes, 3, @user).should be_true
60
+ @question.add_evaluation(:total_votes, 1, @user).should be true
61
+ question2.add_evaluation(:total_votes, 2, user2).should be true
62
+ question3.add_evaluation(:total_votes, 3, @user).should be true
63
63
  Question.evaluated_by(:total_votes, @user).should == [@question, question3]
64
64
  Question.evaluated_by(:total_votes, user2).should == [question2]
65
65
  end
@@ -68,14 +68,14 @@ describe ReputationSystem::EvaluationMethods do
68
68
  it "should return an array of targets evaluated by a given source on appropriate scope" do
69
69
  user2 = User.create!(:name => 'katsuya')
70
70
  phrase2 = Phrase.create!(:text => "Two")
71
- @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be_true
72
- @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
73
- @phrase.add_evaluation(:difficulty_with_scope, 3, user2, :s2).should be_true
74
- @phrase.add_evaluation(:difficulty_with_scope, 4, user2, :s3).should be_true
75
- phrase2.add_evaluation(:difficulty_with_scope, 1, user2, :s1).should be_true
76
- phrase2.add_evaluation(:difficulty_with_scope, 2, user2, :s2).should be_true
77
- phrase2.add_evaluation(:difficulty_with_scope, 3, @user, :s2).should be_true
78
- phrase2.add_evaluation(:difficulty_with_scope, 4, @user, :s3).should be_true
71
+ @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be true
72
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be true
73
+ @phrase.add_evaluation(:difficulty_with_scope, 3, user2, :s2).should be true
74
+ @phrase.add_evaluation(:difficulty_with_scope, 4, user2, :s3).should be true
75
+ phrase2.add_evaluation(:difficulty_with_scope, 1, user2, :s1).should be true
76
+ phrase2.add_evaluation(:difficulty_with_scope, 2, user2, :s2).should be true
77
+ phrase2.add_evaluation(:difficulty_with_scope, 3, @user, :s2).should be true
78
+ phrase2.add_evaluation(:difficulty_with_scope, 4, @user, :s3).should be true
79
79
  Phrase.evaluated_by(:difficulty_with_scope, @user, :s1).should == [@phrase]
80
80
  Phrase.evaluated_by(:difficulty_with_scope, user2, :s1).should == [phrase2]
81
81
  Phrase.evaluated_by(:difficulty_with_scope, @user, :s2).should == [@phrase, phrase2]
@@ -94,9 +94,9 @@ describe ReputationSystem::EvaluationMethods do
94
94
  it "should return an array of sources evaluated the target" do
95
95
  user2 = User.create!(:name => 'katsuya')
96
96
  question2 = Question.create!(:text => 'Question 2', :author_id => @user.id)
97
- @question.add_evaluation(:total_votes, 1, @user).should be_true
98
- question2.add_evaluation(:total_votes, 1, @user).should be_true
99
- question2.add_evaluation(:total_votes, 2, user2).should be_true
97
+ @question.add_evaluation(:total_votes, 1, @user).should be true
98
+ question2.add_evaluation(:total_votes, 1, @user).should be true
99
+ question2.add_evaluation(:total_votes, 2, user2).should be true
100
100
  @question.evaluators_for(:total_votes).should == [@user]
101
101
  question2.evaluators_for(:total_votes).should == [@user, user2]
102
102
  end
@@ -104,10 +104,10 @@ describe ReputationSystem::EvaluationMethods do
104
104
  context "With Scopes" do
105
105
  it "should return an array of targets evaluated by a given source on appropriate scope" do
106
106
  user2 = User.create!(:name => 'katsuya')
107
- @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be_true
108
- @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
109
- @phrase.add_evaluation(:difficulty_with_scope, 3, user2, :s2).should be_true
110
- @phrase.add_evaluation(:difficulty_with_scope, 4, user2, :s3).should be_true
107
+ @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be true
108
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be true
109
+ @phrase.add_evaluation(:difficulty_with_scope, 3, user2, :s2).should be true
110
+ @phrase.add_evaluation(:difficulty_with_scope, 4, user2, :s3).should be true
111
111
  @phrase.evaluators_for(:difficulty_with_scope, :s1).should == [@user]
112
112
  @phrase.evaluators_for(:difficulty_with_scope, :s2).should == [@user, user2]
113
113
  @phrase.evaluators_for(:difficulty_with_scope, :s3).should == [user2]
@@ -117,7 +117,7 @@ describe ReputationSystem::EvaluationMethods do
117
117
 
118
118
  describe "#add_evaluation" do
119
119
  it "should create evaluation in case of valid input" do
120
- @question.add_evaluation(:total_votes, 1, @user).should be_true
120
+ @question.add_evaluation(:total_votes, 1, @user).should be true
121
121
  @question.reputation_for(:total_votes).should == 1
122
122
  end
123
123
 
@@ -142,8 +142,8 @@ describe ReputationSystem::EvaluationMethods do
142
142
 
143
143
  context "with scopes" do
144
144
  it "should add evaluation on appropriate scope" do
145
- @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be_true
146
- @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
145
+ @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be true
146
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be true
147
147
  @phrase.reputation_for(:difficulty_with_scope, :s1).should == 1
148
148
  @phrase.reputation_for(:difficulty_with_scope, :s2).should == 2
149
149
  @phrase.reputation_for(:difficulty_with_scope, :s3).should == 0
@@ -161,30 +161,30 @@ describe ReputationSystem::EvaluationMethods do
161
161
 
162
162
  describe "#add_or_update_evaluation" do
163
163
  it "should create evaluation if it does not exist" do
164
- @question.add_or_update_evaluation(:total_votes, 1, @user).should be_true
164
+ @question.add_or_update_evaluation(:total_votes, 1, @user).should be true
165
165
  @question.reputation_for(:total_votes).should == 1
166
166
  end
167
167
 
168
168
  it "should update evaluation if it exists already" do
169
169
  @question.add_evaluation(:total_votes, 1, @user)
170
- @question.add_or_update_evaluation(:total_votes, 2, @user).should be_true
170
+ @question.add_or_update_evaluation(:total_votes, 2, @user).should be true
171
171
  @question.reputation_for(:total_votes).should == 2
172
172
  end
173
173
 
174
174
  context "with scopes" do
175
175
  it "should add evaluation on appropriate scope if it does not exist" do
176
- @phrase.add_or_update_evaluation(:difficulty_with_scope, 1, @user, :s1).should be_true
177
- @phrase.add_or_update_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
176
+ @phrase.add_or_update_evaluation(:difficulty_with_scope, 1, @user, :s1).should be true
177
+ @phrase.add_or_update_evaluation(:difficulty_with_scope, 2, @user, :s2).should be true
178
178
  @phrase.reputation_for(:difficulty_with_scope, :s1).should == 1
179
179
  @phrase.reputation_for(:difficulty_with_scope, :s2).should == 2
180
180
  @phrase.reputation_for(:difficulty_with_scope, :s3).should == 0
181
181
  end
182
182
 
183
183
  it "should update evaluation on appropriate scope if it exists already" do
184
- @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be_true
185
- @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
186
- @phrase.add_or_update_evaluation(:difficulty_with_scope, 3, @user, :s1).should be_true
187
- @phrase.add_or_update_evaluation(:difficulty_with_scope, 5, @user, :s2).should be_true
184
+ @phrase.add_evaluation(:difficulty_with_scope, 1, @user, :s1).should be true
185
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be true
186
+ @phrase.add_or_update_evaluation(:difficulty_with_scope, 3, @user, :s1).should be true
187
+ @phrase.add_or_update_evaluation(:difficulty_with_scope, 5, @user, :s2).should be true
188
188
  @phrase.reputation_for(:difficulty_with_scope, :s1).should == 3
189
189
  @phrase.reputation_for(:difficulty_with_scope, :s2).should == 5
190
190
  @phrase.reputation_for(:difficulty_with_scope, :s3).should == 0
@@ -208,7 +208,7 @@ describe ReputationSystem::EvaluationMethods do
208
208
  end
209
209
 
210
210
  it "should update evaluation in case of valid input" do
211
- @question.update_evaluation(:total_votes, 2, @user).should be_true
211
+ @question.update_evaluation(:total_votes, 2, @user).should be true
212
212
  @question.reputation_for(:total_votes).should == 2
213
213
  end
214
214
 
@@ -226,11 +226,11 @@ describe ReputationSystem::EvaluationMethods do
226
226
 
227
227
  context "With Scopes" do
228
228
  before :each do
229
- @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be_true
229
+ @phrase.add_evaluation(:difficulty_with_scope, 2, @user, :s2).should be true
230
230
  end
231
231
 
232
232
  it "should update evaluation on appropriate scope" do
233
- @phrase.update_evaluation(:difficulty_with_scope, 5, @user, :s2).should be_true
233
+ @phrase.update_evaluation(:difficulty_with_scope, 5, @user, :s2).should be true
234
234
  @phrase.reputation_for(:difficulty_with_scope, :s1).should == 0
235
235
  @phrase.reputation_for(:difficulty_with_scope, :s2).should == 5
236
236
  @phrase.reputation_for(:difficulty_with_scope, :s3).should == 0
@@ -296,7 +296,7 @@ describe ReputationSystem::EvaluationMethods do
296
296
  end
297
297
 
298
298
  it "should delete evaluation in case of valid input" do
299
- @question.delete_evaluation(:total_votes, @user).should be_true
299
+ @question.delete_evaluation(:total_votes, @user).should be true
300
300
  @question.reputation_for(:total_votes).should == 0
301
301
  end
302
302
 
@@ -305,7 +305,7 @@ describe ReputationSystem::EvaluationMethods do
305
305
  end
306
306
 
307
307
  it "should return false if evaluation does not exist" do
308
- @answer.delete_evaluation(:avg_rating, @user).should be_false
308
+ @answer.delete_evaluation(:avg_rating, @user).should be false
309
309
  end
310
310
 
311
311
  context "With Scopes" do
@@ -314,7 +314,7 @@ describe ReputationSystem::EvaluationMethods do
314
314
  end
315
315
 
316
316
  it "should delete evaluation on appropriate scope" do
317
- @phrase.delete_evaluation(:difficulty_with_scope, @user, :s2).should be_true
317
+ @phrase.delete_evaluation(:difficulty_with_scope, @user, :s2).should be true
318
318
  @phrase.reputation_for(:difficulty_with_scope, :s1).should == 0
319
319
  @phrase.reputation_for(:difficulty_with_scope, :s2).should == 0
320
320
  @phrase.reputation_for(:difficulty_with_scope, :s3).should == 0
@@ -332,13 +332,13 @@ describe ReputationSystem::EvaluationMethods do
332
332
 
333
333
  describe "#increase_evaluation" do
334
334
  it "should add evaluation if it does not exist" do
335
- @question.increase_evaluation(:total_votes, 2, @user).should be_true
335
+ @question.increase_evaluation(:total_votes, 2, @user).should be true
336
336
  @question.reputation_for(:total_votes).should == 2
337
337
  end
338
338
 
339
339
  it "should increase evaluation if it exists already" do
340
340
  @question.add_evaluation(:total_votes, 1, @user)
341
- @question.increase_evaluation(:total_votes, 2, @user).should be_true
341
+ @question.increase_evaluation(:total_votes, 2, @user).should be true
342
342
  @question.reputation_for(:total_votes).should == 3
343
343
  end
344
344
 
@@ -348,7 +348,7 @@ describe ReputationSystem::EvaluationMethods do
348
348
  end
349
349
 
350
350
  it "should increase evaluation on appropriate scope" do
351
- @phrase.increase_evaluation(:difficulty_with_scope, 5, @user, :s2).should be_true
351
+ @phrase.increase_evaluation(:difficulty_with_scope, 5, @user, :s2).should be true
352
352
  @phrase.reputation_for(:difficulty_with_scope, :s1).should == 0
353
353
  @phrase.reputation_for(:difficulty_with_scope, :s2).should == 7
354
354
  @phrase.reputation_for(:difficulty_with_scope, :s3).should == 0
@@ -358,13 +358,13 @@ describe ReputationSystem::EvaluationMethods do
358
358
 
359
359
  describe "#decrease_evaluation" do
360
360
  it "should add evaluation if it does not exist" do
361
- @question.decrease_evaluation(:total_votes, 2, @user).should be_true
361
+ @question.decrease_evaluation(:total_votes, 2, @user).should be true
362
362
  @question.reputation_for(:total_votes).should == -2
363
363
  end
364
364
 
365
365
  it "should increase evaluation if it exists already" do
366
366
  @question.add_evaluation(:total_votes, 1, @user)
367
- @question.decrease_evaluation(:total_votes, 2, @user).should be_true
367
+ @question.decrease_evaluation(:total_votes, 2, @user).should be true
368
368
  @question.reputation_for(:total_votes).should == -1
369
369
  end
370
370
 
@@ -374,7 +374,7 @@ describe ReputationSystem::EvaluationMethods do
374
374
  end
375
375
 
376
376
  it "should decrease evaluation on appropriate scope" do
377
- @phrase.decrease_evaluation(:difficulty_with_scope, 5, @user, :s2).should be_true
377
+ @phrase.decrease_evaluation(:difficulty_with_scope, 5, @user, :s2).should be true
378
378
  @phrase.reputation_for(:difficulty_with_scope, :s1).should == 0
379
379
  @phrase.reputation_for(:difficulty_with_scope, :s2).should == -3
380
380
  @phrase.reputation_for(:difficulty_with_scope, :s3).should == 0
@@ -177,6 +177,7 @@ describe ReputationSystem::FinderMethods do
177
177
  "FROM \"questions\" JOIN users ON questions.author_id = users.id "\
178
178
  "LEFT JOIN rs_reputations ON questions.id = rs_reputations.target_id AND rs_reputations.target_type = 'Question' AND rs_reputations.reputation_name = 'total_votes' AND rs_reputations.active = 't' "\
179
179
  "WHERE (COALESCE(rs_reputations.value, 0) > 0.6) "\
180
+ " " if ActiveRecord::VERSION::STRING >= '4' \
180
181
  "ORDER BY total_votes"
181
182
  end
182
183
  end
@@ -59,4 +59,12 @@ describe ReputationSystem::Evaluation do
59
59
  ReputationSystem::ReputationMessage.find_by_sender_id_and_sender_type(evaluation.id, evaluation.class.name).should be_nil
60
60
  end
61
61
  end
62
+
63
+ context "Additional Data" do
64
+ it "should have data as a serialized field" do
65
+ @attributes = {:reputation_name => 'total_votes', :source => @user, :target => @question, :value => 1}
66
+ e = ReputationSystem::Evaluation.create!(@attributes)
67
+ e.data.should be_a(Hash)
68
+ end
69
+ end
62
70
  end
@@ -46,8 +46,12 @@ describe ReputationSystem::Reputation do
46
46
  ReputationSystem::Reputation.create(:reputation_name => "karma3", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'product').should be_valid
47
47
  end
48
48
 
49
- it "should not be able to create reputation with process other than 'sum', 'average' and 'product'" do
50
- ReputationSystem::Reputation.create(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'invalid').should_not be_valid
49
+ it "should be able to create reputation with custom process" do
50
+ ReputationSystem::Reputation.create(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'custom_process').should be_valid
51
+ end
52
+
53
+ it "should be able to create reputation with custom process from source" do
54
+ ReputationSystem::Reputation.create(:reputation_name => "custom_rating", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'custom_rating').should be_valid
51
55
  end
52
56
 
53
57
  it "should not be able to create reputation of the same name for the same target" do
@@ -133,4 +137,31 @@ describe ReputationSystem::Reputation do
133
137
  answer.reputation_for(:avg_rating).should be_within(DELTA).of(3)
134
138
  end
135
139
  end
140
+
141
+ describe "custom aggregation function" do
142
+ it "should calculate based on a custom function for new source" do
143
+ user1 = User.create! :name => 'dick'
144
+ user2 = User.create! :name => 'katsuya'
145
+ answer = Answer.create!
146
+ answer.add_or_update_evaluation(:custom_rating, 3, user1)
147
+ answer.add_or_update_evaluation(:custom_rating, 2, user2)
148
+ answer.reputation_for(:custom_rating).should be_within(DELTA).of(50)
149
+ end
150
+
151
+ it "should calculate based on a custom function for updated source" do
152
+ user1 = User.create! :name => 'dick'
153
+ user2 = User.create! :name => 'katsuya'
154
+ answer = Answer.create!
155
+ answer.add_or_update_evaluation(:custom_rating, 3, user1)
156
+ answer.add_or_update_evaluation(:custom_rating, 2, user1)
157
+ answer.reputation_for(:custom_rating).should be_within(DELTA).of(20)
158
+ end
159
+ end
160
+
161
+ describe "additional data" do
162
+ it "should have data as a serialized field" do
163
+ r = ReputationSystem::Reputation.create!(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum')
164
+ r.data.should be_a(Hash)
165
+ end
166
+ end
136
167
  end
@@ -153,9 +153,9 @@ describe ReputationSystem::ReputationMethods do
153
153
  @question2.add_evaluation(:total_votes, 70, @user)
154
154
  @question.add_evaluation(:total_votes, 100, @user)
155
155
  @question.deactivate_all_reputations
156
- ReputationSystem::Reputation.maximum(:value, :conditions => {:reputation_name => 'total_votes', :active => true}).should == 70
156
+ ReputationSystem::Reputation.where(:reputation_name => 'total_votes', :active => true).maximum(:value).should == 70
157
157
  @question.activate_all_reputations
158
- ReputationSystem::Reputation.maximum(:value, :conditions => {:reputation_name => 'total_votes', :active => true}).should == 100
158
+ ReputationSystem::Reputation.where(:reputation_name => 'total_votes', :active => true).maximum(:value).should == 100
159
159
  end
160
160
  end
161
161
  end
data/spec/spec_helper.rb CHANGED
@@ -43,6 +43,7 @@ ActiveRecord::Schema.define do
43
43
  t.references :source, :polymorphic => true
44
44
  t.references :target, :polymorphic => true
45
45
  t.float :value, :default => 0
46
+ t.text :data
46
47
  t.timestamps
47
48
  end
48
49
 
@@ -56,6 +57,7 @@ ActiveRecord::Schema.define do
56
57
  t.string :aggregated_by
57
58
  t.references :target, :polymorphic => true
58
59
  t.boolean :active, :default => true
60
+ t.text :data
59
61
  t.timestamps
60
62
  end
61
63
 
@@ -132,6 +134,14 @@ class User < ActiveRecord::Base
132
134
  has_reputation :answer_karma,
133
135
  :source => { :reputation => :weighted_avg_rating, :of => :answers },
134
136
  :aggregated_by => :average
137
+
138
+ has_reputation :custom_rating,
139
+ :source => { :reputation => :custom_rating, :of => :answers },
140
+ :aggregated_by => :custom_rating
141
+
142
+ def custom_process
143
+ 123
144
+ end
135
145
  end
136
146
 
137
147
  class Question < ActiveRecord::Base
@@ -161,12 +171,29 @@ class Answer < ActiveRecord::Base
161
171
  has_reputation :avg_rating,
162
172
  :source => :user,
163
173
  :aggregated_by => :average
174
+
175
+ has_reputation :custom_rating,
176
+ :source => :user,
177
+ :aggregated_by => :custom_aggregation,
178
+ :source_of => { :reputation => :custom_rating, :of => :author }
179
+
180
+ def custom_aggregation(*args)
181
+ rep, source, weight = args[0..2]
182
+ # rep, source, weight
183
+ if args.length === 3
184
+ rep.value + weight * source.value * 10
185
+ # rep, source, weight, oldValue, newSize
186
+ elsif args.length === 5
187
+ oldValue, newSize = args[3..4]
188
+ rep.value + (source.value - oldValue) * 10
189
+ end
190
+ end
164
191
  end
165
192
 
166
193
  class Phrase < ActiveRecord::Base
167
194
  has_many :translations do
168
195
  def for(locale)
169
- self.find_all_by_locale(locale.to_s)
196
+ self.where(:locale => locale.to_s).to_a
170
197
  end
171
198
  end
172
199
 
metadata CHANGED
@@ -1,52 +1,60 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-reputation-system
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
5
- prerelease:
4
+ version: 3.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Katsuya Noguchi
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-12-01 00:00:00.000000000 Z
11
+ date: 2014-10-07 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- name: activerecord
14
+ name: protected_attributes
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
- type: :development
20
+ type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
30
41
  - !ruby/object:Gem::Dependency
31
42
  name: rake
32
43
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
44
  requirements:
35
- - - ! '>='
45
+ - - '>='
36
46
  - !ruby/object:Gem::Version
37
47
  version: 0.8.7
38
48
  type: :development
39
49
  prerelease: false
40
50
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
51
  requirements:
43
- - - ! '>='
52
+ - - '>='
44
53
  - !ruby/object:Gem::Version
45
54
  version: 0.8.7
46
55
  - !ruby/object:Gem::Dependency
47
56
  name: rspec
48
57
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
58
  requirements:
51
59
  - - ~>
52
60
  - !ruby/object:Gem::Version
@@ -54,7 +62,6 @@ dependencies:
54
62
  type: :development
55
63
  prerelease: false
56
64
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
65
  requirements:
59
66
  - - ~>
60
67
  - !ruby/object:Gem::Version
@@ -62,39 +69,34 @@ dependencies:
62
69
  - !ruby/object:Gem::Dependency
63
70
  name: rdoc
64
71
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
72
  requirements:
67
- - - ! '>='
73
+ - - '>='
68
74
  - !ruby/object:Gem::Version
69
75
  version: '0'
70
76
  type: :development
71
77
  prerelease: false
72
78
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
79
  requirements:
75
- - - ! '>='
80
+ - - '>='
76
81
  - !ruby/object:Gem::Version
77
82
  version: '0'
78
83
  - !ruby/object:Gem::Dependency
79
84
  name: database_cleaner
80
85
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
86
  requirements:
83
87
  - - ~>
84
88
  - !ruby/object:Gem::Version
85
- version: 0.7.1
89
+ version: 1.2.0
86
90
  type: :development
87
91
  prerelease: false
88
92
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
93
  requirements:
91
94
  - - ~>
92
95
  - !ruby/object:Gem::Version
93
- version: 0.7.1
96
+ version: 1.2.0
94
97
  - !ruby/object:Gem::Dependency
95
98
  name: sqlite3
96
99
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
100
  requirements:
99
101
  - - ~>
100
102
  - !ruby/object:Gem::Version
@@ -102,7 +104,6 @@ dependencies:
102
104
  type: :development
103
105
  prerelease: false
104
106
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
107
  requirements:
107
108
  - - ~>
108
109
  - !ruby/object:Gem::Version
@@ -120,6 +121,8 @@ files:
120
121
  - Rakefile
121
122
  - lib/activerecord-reputation-system.rb
122
123
  - lib/generators/reputation_system/reputation_system_generator.rb
124
+ - lib/generators/reputation_system/templates/add_data_to_evaluations.rb
125
+ - lib/generators/reputation_system/templates/add_data_to_reputations.rb
123
126
  - lib/generators/reputation_system/templates/add_evaluations_index.rb
124
127
  - lib/generators/reputation_system/templates/add_reputation_messages_index.rb
125
128
  - lib/generators/reputation_system/templates/add_reputations_index.rb
@@ -127,6 +130,7 @@ files:
127
130
  - lib/generators/reputation_system/templates/change_reputation_messages_index_to_unique.rb
128
131
  - lib/generators/reputation_system/templates/change_reputations_index_to_unique.rb
129
132
  - lib/generators/reputation_system/templates/create_reputation_system.rb
133
+ - lib/reputation_system.rb
130
134
  - lib/reputation_system/base.rb
131
135
  - lib/reputation_system/evaluation_methods.rb
132
136
  - lib/reputation_system/finder_methods.rb
@@ -139,7 +143,6 @@ files:
139
143
  - lib/reputation_system/reputation_methods.rb
140
144
  - lib/reputation_system/scope_methods.rb
141
145
  - lib/reputation_system/version.rb
142
- - lib/reputation_system.rb
143
146
  - spec/reputation_system/base_spec.rb
144
147
  - spec/reputation_system/evaluation_methods_spec.rb
145
148
  - spec/reputation_system/finder_methods_spec.rb
@@ -152,27 +155,26 @@ files:
152
155
  - spec/spec_helper.rb
153
156
  homepage: https://github.com/twitter/activerecord-reputation-system
154
157
  licenses: []
158
+ metadata: {}
155
159
  post_install_message:
156
160
  rdoc_options: []
157
161
  require_paths:
158
162
  - lib
159
163
  required_ruby_version: !ruby/object:Gem::Requirement
160
- none: false
161
164
  requirements:
162
- - - ! '>='
165
+ - - '>='
163
166
  - !ruby/object:Gem::Version
164
167
  version: '0'
165
168
  required_rubygems_version: !ruby/object:Gem::Requirement
166
- none: false
167
169
  requirements:
168
- - - ! '>='
170
+ - - '>='
169
171
  - !ruby/object:Gem::Version
170
172
  version: '0'
171
173
  requirements: []
172
174
  rubyforge_project:
173
- rubygems_version: 1.8.23
175
+ rubygems_version: 2.2.2
174
176
  signing_key:
175
- specification_version: 3
177
+ specification_version: 4
176
178
  summary: ActiveRecord Reputation System gem allows rails apps to compute and publish
177
179
  reputation scores for active record models
178
180
  test_files: []