activerecord-reputation-system 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -20,10 +20,12 @@ Run:
20
20
 
21
21
  ```ruby
22
22
  bundle install
23
- rails generator reputation_system
23
+ rails generate reputation_system
24
24
  rake db:migrate
25
25
  ```
26
26
 
27
+ * Please do the installation on every upgrade as it may include new migration files.
28
+
27
29
  ## Usage Example
28
30
 
29
31
  Let's say we want to keep track of user karma in Q&A site where user karma is sum of questioning skill and answering skill. Questioning skill is sum of votes for user's questions and Answering skill is sum of average rating of user's answers. This can be defined as follow:
@@ -30,6 +30,17 @@ class ReputationSystemGenerator < Rails::Generators::Base
30
30
  end
31
31
 
32
32
  def create_migration_files
33
- migration_template 'create_reputation_system.rb', 'db/migrate/create_reputation_system.rb'
33
+ create_migration_file_if_not_exist 'create_reputation_system'
34
+ create_migration_file_if_not_exist 'add_reputations_index'
35
+ create_migration_file_if_not_exist 'add_evaluations_index'
36
+ create_migration_file_if_not_exist 'add_reputation_messages_index'
34
37
  end
35
- end
38
+
39
+ private
40
+
41
+ def create_migration_file_if_not_exist(file_name)
42
+ unless self.class.migration_exists?(File.dirname(File.expand_path("db/migrate/#{file_name}")), file_name)
43
+ migration_template "#{file_name}.rb", "db/migrate/#{file_name}.rb"
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,25 @@
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
+ class AddEvaluationsIndex < ActiveRecord::Migration
18
+ def self.up
19
+ add_index :rs_evaluations, [:reputation_name, :source_id, :source_type, :target_id, :target_type], :name => "index_rs_evaluations_on_reputation_name_and_source_and_target"
20
+ end
21
+
22
+ def self.down
23
+ remove_index :rs_evaluations, :column => [:reputation_name, :source_id, :source_type, :target_id, :target_type]
24
+ end
25
+ end
@@ -0,0 +1,25 @@
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
+ class AddReputationMessagesIndex < ActiveRecord::Migration
18
+ def self.up
19
+ add_index :rs_reputation_messages, [:receiver_id, :sender_id, :sender_type], :name => "index_rs_reputation_messages_on_receiver_id_and_sender"
20
+ end
21
+
22
+ def self.down
23
+ remove_index :rs_reputation_messages, :column => [:receiver_id, :sender_id, :sender_type]
24
+ end
25
+ end
@@ -0,0 +1,25 @@
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
+ class AddReputationsIndex < ActiveRecord::Migration
18
+ def self.up
19
+ add_index :rs_reputations, [:reputation_name, :target_id, :target_type], :name => "index_rs_reputations_on_reputation_name_and_target"
20
+ end
21
+
22
+ def self.down
23
+ remove_index :rs_reputations, :column => [:reputation_name, :target_id, :target_type]
24
+ end
25
+ end
@@ -23,20 +23,18 @@ module ReputationSystem
23
23
  end
24
24
 
25
25
  def get_reputation_defs(class_name)
26
- network[class_name.to_sym] = {} unless network[class_name.to_sym]
27
- network[class_name.to_sym]
26
+ network[class_name.to_sym] ||= {}
28
27
  end
29
28
 
30
29
  def get_reputation_def(class_name, reputation_name)
31
30
  reputation_defs = get_reputation_defs(class_name)
32
- reputation_defs[reputation_name.to_sym] = {} unless reputation_defs[reputation_name.to_sym]
33
- reputation_defs[reputation_name.to_sym]
31
+ reputation_defs[reputation_name.to_sym] ||= {}
34
32
  end
35
33
 
36
34
  def add_reputation_def(class_name, reputation_name, options)
37
35
  reputation_defs = get_reputation_defs(class_name)
38
36
  options[:source] = convert_to_array_if_hash(options[:source])
39
- options[:source_of] = [] unless options[:source_of]
37
+ options[:source_of] ||= []
40
38
  options[:source_of] = convert_to_array_if_hash(options[:source_of])
41
39
  assign_self_as_default_value_for_of_attr(options[:source])
42
40
  assign_self_as_default_value_for_of_attr(options[:source_of])
@@ -67,7 +65,7 @@ module ReputationSystem
67
65
  def add_scope_for(class_name, reputation_name, scope)
68
66
  options = get_reputation_def(class_name, reputation_name)
69
67
  if has_scope?(class_name, reputation_name, scope)
70
- raise ArgumentError, "#{scope.to_s} is already defined for #{reputation_name.to_s}"
68
+ raise ArgumentError, "#{scope} is already defined for #{reputation_name}"
71
69
  else
72
70
  options[:scopes].push scope.to_sym if options[:scopes]
73
71
  create_scoped_reputation_def(class_name, reputation_name, scope, options)
@@ -87,7 +85,7 @@ module ReputationSystem
87
85
  scope = scope.to_sym if scope
88
86
  validate_scope_necessity(class_name, reputation_name, scope)
89
87
  validate_scope_existence(class_name, reputation_name, scope)
90
- "#{reputation_name.to_s}#{"_#{scope.to_s}" if scope}"
88
+ "#{reputation_name}#{"_#{scope}" if scope}"
91
89
  end
92
90
 
93
91
  def get_weight_of_source_from_reputation_name_of_target(target, source_name, reputation_name)
@@ -106,17 +104,15 @@ module ReputationSystem
106
104
  protected
107
105
 
108
106
  def network
109
- @network = {} unless @network
110
- @network
107
+ @network ||= {}
111
108
  end
112
109
 
113
110
  def data_for_derive_later
114
- @data_for_derive_later = {} unless @data_for_derive_later
115
- @data_for_derive_later
111
+ @data_for_derive_later ||= {}
116
112
  end
117
113
 
118
114
  def create_scoped_reputation_def(class_name, reputation_name, scope, options)
119
- raise ArgumentError, "#{reputation_name.to_s} does not have scope." unless has_scopes?(class_name, reputation_name)
115
+ raise ArgumentError, "#{reputation_name} does not have scope." unless has_scopes?(class_name, reputation_name)
120
116
  scope_options = {}
121
117
  reputation_def = get_reputation_def(class_name, reputation_name)
122
118
  if is_primary_reputation?(class_name, reputation_name)
@@ -198,12 +194,11 @@ module ReputationSystem
198
194
  end
199
195
 
200
196
  def convert_to_array_if_hash(tar)
201
- tar = [tar] if tar.is_a? Hash
202
- tar
197
+ tar.is_a?(Hash) ? [tar] : tar
203
198
  end
204
199
 
205
200
  def assign_self_as_default_value_for_of_attr(tar)
206
- tar = tar.each { |s| s[:of] = :self unless s[:of] } if tar.is_a? Array
201
+ tar.each { |s| s[:of] = :self unless s[:of] } if tar.is_a? Array
207
202
  end
208
203
 
209
204
  def validate_scope_necessity(class_name, reputation_name, scope)
@@ -15,5 +15,5 @@
15
15
  ##
16
16
 
17
17
  module ReputationSystem
18
- VERSION = "1.1.0"
18
+ VERSION = "1.2.0"
19
19
  end
@@ -26,7 +26,7 @@ describe RSEvaluation do
26
26
  before :each do
27
27
  @attributes = {:reputation_name => 'total_votes', :source => @user, :target => @question, :value => 1}
28
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
29
+ it "should not be able to create an evaluation from given source if it has already evaluated the same reputation of the target" do
30
30
  RSEvaluation.create!(@attributes)
31
31
  lambda {RSEvaluation.create!(@attributes)}.should raise_error
32
32
  end
@@ -24,14 +24,14 @@ describe RSReputationMessage do
24
24
  end
25
25
 
26
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
27
+ it "should not be able to create a message from given sender if it has already sent one to the same receiver" do
28
+ RSReputationMessage.create(:sender => @rep1, :receiver => @rep2).should be_valid
29
+ RSReputationMessage.create(:sender => @rep1, :receiver => @rep2).should_not be_valid
30
30
  end
31
31
 
32
32
  it "should have raise error if sender is neither RSEvaluation and RSReputation" do
33
33
  RSReputationMessage.create(:sender => @user, :receiver => @rep2).errors[:sender].should_not be_nil
34
- end
34
+ end
35
35
  end
36
36
 
37
37
  context "Association" do
@@ -41,18 +41,18 @@ describe RSReputation do
41
41
  end
42
42
 
43
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
44
+ RSReputation.create(:reputation_name => "karma1", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum').should be_valid
45
+ RSReputation.create(:reputation_name => "karma2", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'average').should be_valid
46
+ RSReputation.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
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
50
+ RSReputation.create(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'invalid').should_not be_valid
51
51
  end
52
52
 
53
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
54
+ RSReputation.create(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum').should be_valid
55
+ RSReputation.create(:reputation_name => "karma", :target_id => @user.id, :target_type => @user.class.to_s, :aggregated_by => 'sum').should_not be_valid
56
56
  end
57
57
  end
58
58
 
@@ -48,11 +48,11 @@ describe ActiveRecord::Base do
48
48
 
49
49
  it "should delete reputations if target is deleted" do
50
50
  @question.add_evaluation(:total_votes, 5, @user)
51
- count = RSReputation.count
52
- count = RSReputationMessage.count
51
+ reputation_count = RSReputation.count
52
+ message_count = RSReputationMessage.count
53
53
  @question.destroy
54
- RSReputation.count.should < count
55
- RSReputationMessage.count.should < count
54
+ RSReputation.count.should < reputation_count
55
+ RSReputationMessage.count.should < message_count
56
56
  end
57
57
 
58
58
  it "should have declared default value if any" do
@@ -60,7 +60,7 @@ describe ActiveRecord::Base do
60
60
  end
61
61
 
62
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)
63
+ lambda{@phrase.add_evaluation(:difficulty_with_scope, 1)}.should raise_error(ArgumentError)
64
64
  end
65
65
  end
66
66
  end
@@ -295,7 +295,7 @@ describe ActiveRecord::Base do
295
295
  end
296
296
  end
297
297
 
298
- describe "#update_eavluation" do
298
+ describe "#update_evaluation" do
299
299
  before :each do
300
300
  @trans_ja.add_evaluation(:votes, 1, @user)
301
301
  end
@@ -307,7 +307,7 @@ describe ActiveRecord::Base do
307
307
  end
308
308
  end
309
309
 
310
- describe "#delete_eavluation" do
310
+ describe "#delete_evaluation" do
311
311
  before :each do
312
312
  @trans_ja.add_evaluation(:votes, 1, @user)
313
313
  end
@@ -343,7 +343,7 @@ describe ActiveRecord::Base do
343
343
  end
344
344
  end
345
345
 
346
- describe "#update_eavluation" do
346
+ describe "#update_evaluation" do
347
347
  before :each do
348
348
  @trans_ja.add_evaluation(:votes, 1, @user)
349
349
  @trans_de.add_evaluation(:votes, 3, @user)
@@ -356,7 +356,7 @@ describe ActiveRecord::Base do
356
356
  end
357
357
  end
358
358
 
359
- describe "#delete_eavluation" do
359
+ describe "#delete_evaluation" do
360
360
  before :each do
361
361
  @trans_ja.add_evaluation(:votes, 1, @user)
362
362
  @trans_de.add_evaluation(:votes, 3, @user)
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 1.1.0
9
+ version: 1.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Katsuya Noguchi
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2012-05-22 00:00:00 -07:00
17
+ date: 2012-06-12 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -110,6 +110,9 @@ files:
110
110
  - README.md
111
111
  - Rakefile
112
112
  - lib/generators/reputation_system/reputation_system_generator.rb
113
+ - lib/generators/reputation_system/templates/add_evaluations_index.rb
114
+ - lib/generators/reputation_system/templates/add_reputation_messages_index.rb
115
+ - lib/generators/reputation_system/templates/add_reputations_index.rb
113
116
  - lib/generators/reputation_system/templates/create_reputation_system.rb
114
117
  - lib/models/rs_evaluation.rb
115
118
  - lib/models/rs_reputation.rb