Permalink
Browse files

Bring back major changes reverted

  • Loading branch information...
1 parent 0d5bb33 commit cd95ef444c4eb658e857c5d6b4fb38819cfaaa7b Katsuya Noguchi committed Oct 4, 2012
View
@@ -1,3 +1,11 @@
+* Remove reputation_value_for and normalized_reputation_value_for methods.
+
+* Add `evaluations` association for all evaluation targets.
+
+* Set `:sum` as default for `aggregated_by` option.
+
+* Rename models - RSReputation to ReputationSystem::Reputation, RSEvaluation to ReputationSystem::Evaluation and RSReputationMessage to ReputationSystem::ReputationMessage
+
## ActiveRecordReputationSystem 1.5.1 ##
* Fix a bug that raises exception when associations related reputation propageted has not been initialized at that time.
@@ -1,69 +0,0 @@
-##
-# Copyright 2012 Twitter, Inc
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-class RSEvaluation < ActiveRecord::Base
- belongs_to :source, :polymorphic => true
- belongs_to :target, :polymorphic => true
- has_one :sent_messages, :as => :sender, :class_name => 'RSReputationMessage', :dependent => :destroy
-
- attr_accessible :reputation_name, :value, :source, :source_id, :source_type, :target, :target_id, :target_type
-
- # Sets an appropriate source type in case of Single Table Inheritance.
- before_validation :set_source_type_for_sti
-
- # the same source cannot evaluate the same target more than once.
- validates_uniqueness_of :source_id, :scope => [:reputation_name, :source_type, :target_id, :target_type]
- validate :source_must_be_defined_for_reputation_in_network
-
- def self.find_by_reputation_name_and_source_and_target(reputation_name, source, target)
- source_type = get_source_type_for_sti(source, target.class.name, reputation_name)
- RSEvaluation.find(:first,
- :conditions => {:reputation_name => reputation_name.to_s,
- :source_id => source.id,
- :source_type => source_type,
- :target_id => target.id,
- :target_type => target.class.name
- })
- end
-
- def self.create_evaluation(reputation_name, value, source, target)
- RSEvaluation.create!(:reputation_name => reputation_name.to_s, :value => value,
- :source_id => source.id, :source_type => source.class.name,
- :target_id => target.id, :target_type => target.class.name)
- end
-
- protected
-
- def self.get_source_type_for_sti(source, target_type, reputation_name)
- valid_source_type = ReputationSystem::Network.get_reputation_def(target_type, reputation_name)[:source].to_s.camelize
- temp = source.class
- while temp && valid_source_type != temp.name && temp.name != "ActiveRecord::Base"
- temp = temp.superclass
- end
- temp ? temp.name : nil
- end
-
- def set_source_type_for_sti
- temp = self.class.get_source_type_for_sti(source, target_type, reputation_name)
- self.source_type = temp if temp
- end
-
- def source_must_be_defined_for_reputation_in_network
- unless source_type == ReputationSystem::Network.get_reputation_def(target_type, reputation_name)[:source].to_s.camelize
- errors.add(:source_type, "#{source_type} is not source of #{reputation_name} reputation")
- end
- end
-end
View
@@ -1,204 +0,0 @@
-##
-# Copyright 2012 Twitter, Inc
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-class RSReputation < ActiveRecord::Base
- belongs_to :target, :polymorphic => true
- has_many :received_messages, :class_name => 'RSReputationMessage', :foreign_key => :receiver_id, :dependent => :destroy do
- def from(sender)
- self.find_by_sender_id_and_sender_type(sender.id, sender.class.to_s)
- end
- end
- has_many :sent_messages, :as => :sender, :class_name => 'RSReputationMessage', :dependent => :destroy
-
- attr_accessible :reputation_name, :value, :aggregated_by, :active, :target, :target_id, :target_type, :received_messages
-
- before_validation :set_target_type_for_sti
- before_save :change_zero_value_in_case_of_product_process
-
- VALID_PROCESSES = ['sum', 'average', 'product']
- validates_inclusion_of :aggregated_by, :in => VALID_PROCESSES, :message => "Value chosen for aggregated_by is not valid process"
- validates_uniqueness_of :reputation_name, :scope => [:target_id, :target_type]
-
- def self.find_by_reputation_name_and_target(reputation_name, target)
- target_type = get_target_type_for_sti(target, reputation_name)
- RSReputation.find_by_reputation_name_and_target_id_and_target_type(reputation_name.to_s, target.id, target_type)
- end
-
- # All external access to reputation should use this since they are created lazily.
- def self.find_or_create_reputation(reputation_name, target, process)
- rep = find_by_reputation_name_and_target(reputation_name, target)
- rep ? rep : create_reputation(reputation_name, target, process)
- end
-
- def self.create_reputation(reputation_name, target, process)
- create_options = {:reputation_name => reputation_name.to_s, :target_id => target.id,
- :target_type => target.class.name, :aggregated_by => process.to_s}
- default_value = ReputationSystem::Network.get_reputation_def(target.class.name, reputation_name)[:init_value]
- create_options.merge!(:value => default_value) if default_value
- rep = create(create_options)
- initialize_reputation_value(rep, target, process)
- end
-
- def self.update_reputation_value_with_new_source(rep, source, weight, process)
- weight ||= 1 # weight is 1 by default.
- size = rep.received_messages.size
- valueBeforeUpdate = size > 0 ? rep.value : nil
- newValue = source.value
- case process.to_sym
- when :sum
- rep.value += (newValue * weight)
- when :average
- rep.value = (rep.value * size + newValue * weight) / (size + 1)
- when :product
- rep.value *= (newValue * weight)
- else
- raise ArgumentError, "#{process} process is not supported yet"
- end
- save_succeeded = rep.save
- RSReputationMessage.add_reputation_message_if_not_exist(source, rep)
- propagate_updated_reputation_value(rep, valueBeforeUpdate) if rep.target
- save_succeeded
- end
-
- def self.update_reputation_value_with_updated_source(rep, source, oldValue, weight, process)
- weight ||= 1 # weight is 1 by default.
- size = rep.received_messages.size
- valueBeforeUpdate = size > 0 ? rep.value : nil
- newValue = source.value
- case process.to_sym
- when :sum
- rep.value += (newValue - oldValue) * weight
- when :average
- rep.value += ((newValue - oldValue) * weight) / size
- when :product
- rep.value = (rep.value * newValue) / oldValue
- else
- raise ArgumentError, "#{process} process is not supported yet"
- end
- save_succeeded = rep.save
- propagate_updated_reputation_value(rep, valueBeforeUpdate) if rep.target
- save_succeeded
- end
-
- def normalized_value
- if self.active == 1 || self.active == true
- max = RSReputation.max(self.reputation_name, self.target_type)
- min = RSReputation.min(self.reputation_name, self.target_type)
- if max && min
- range = max - min
- range == 0 ? 0 : (self.value - min) / range
- else
- 0
- end
- else
- 0
- end
- end
-
- protected
-
- # Updates reputation value for new reputation if its source already exist.
- def self.initialize_reputation_value(receiver, target, process)
- name = receiver.reputation_name
- unless ReputationSystem::Network.is_primary_reputation?(target.class.name, name)
- sender_defs = ReputationSystem::Network.get_reputation_def(target.class.name, name)[:source]
- sender_defs.each do |sd|
- sender_targets = target.get_attributes_of(sd)
- sender_targets.each do |st|
- update_reputation_if_source_exist(sd, st, receiver, process) if receiver.target
- end
- end
- end
- receiver
- end
-
- # Propagates updated reputation value to the reputations whose source is the updated reputation.
- def self.propagate_updated_reputation_value(sender, oldValue)
- receiver_defs = ReputationSystem::Network.get_reputation_def(sender.target.class.name, sender.reputation_name)[:source_of]
- receiver_defs.each do |rd|
- targets = sender.target.get_attributes_of(rd)
- targets.each do |target|
- scope = sender.target.evaluate_reputation_scope(rd[:scope])
- send_reputation_message_to_receiver(rd[:reputation], sender, target, scope, oldValue)
- end
- end if receiver_defs
- end
-
- def self.send_reputation_message_to_receiver(reputation_name, sender, target, scope, oldValue)
- srn = ReputationSystem::Network.get_scoped_reputation_name(target.class.name, reputation_name, scope)
- process = ReputationSystem::Network.get_reputation_def(target.class.name, srn)[:aggregated_by]
- receiver = find_by_reputation_name_and_target(srn, target)
- if receiver
- weight = ReputationSystem::Network.get_weight_of_source_from_reputation_name_of_target(target, sender.reputation_name, srn)
- update_reputation_value(receiver, sender, weight, process, oldValue)
- # If r is new then value update will be done when it is initialized.
- else
- create_reputation(srn, target, process)
- end
- end
-
- def self.update_reputation_value(receiver, sender, weight, process, oldValue)
- unless oldValue
- update_reputation_value_with_new_source(receiver, sender, weight, process)
- else
- update_reputation_value_with_updated_source(receiver, sender, oldValue, weight, process)
- end
- end
-
- def self.update_reputation_if_source_exist(sd, st, receiver, process)
- scope = receiver.target.evaluate_reputation_scope(sd[:scope])
- srn = ReputationSystem::Network.get_scoped_reputation_name(st.class.name, sd[:reputation], scope)
- source = find_by_reputation_name_and_target(srn, st)
- if source
- update_reputation_value_with_new_source(receiver, source, sd[:weight], process)
- RSReputationMessage.add_reputation_message_if_not_exist(source, receiver)
- end
- end
-
- def self.max(reputation_name, target_type)
- RSReputation.maximum(:value,
- :conditions => {:reputation_name => reputation_name.to_s, :target_type => target_type, :active => true})
- end
-
- def self.min(reputation_name, target_type)
- RSReputation.minimum(:value,
- :conditions => {:reputation_name => reputation_name.to_s, :target_type => target_type, :active => true})
- end
-
- def self.get_target_type_for_sti(target, reputation_name)
- temp = target.class
- defs = ReputationSystem::Network.get_reputation_defs(temp.name)[reputation_name.to_sym]
- while temp && temp.name != "ActiveRecord::Base" && defs && defs.empty?
- temp = temp.superclass
- defs = ReputationSystem::Network.get_reputation_defs(temp.name)[reputation_name.to_sym]
- end
- temp ? temp.name : nil
- end
-
- def set_target_type_for_sti
- temp = self.class.get_target_type_for_sti(target, reputation_name)
- self.target_type = temp if temp
- end
-
- def change_zero_value_in_case_of_product_process
- self.value = 1 if self.value == 0 && self.aggregated_by == "product"
- end
-
- def remove_associated_messages
- RSReputationMessage.delete_all(:sender_type => self.class.name, :sender_id => self.id)
- RSReputationMessage.delete_all(:receiver_id => self.id)
- end
-end
@@ -1,46 +0,0 @@
-##
-# Copyright 2012 Twitter, Inc
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-class RSReputationMessage < ActiveRecord::Base
- belongs_to :sender, :polymorphic => true
- belongs_to :receiver, :class_name => 'RSReputation'
-
- attr_accessible :weight, :sender, :receiver
-
- # The same sender cannot send massage to the same receiver more than once.
- validates_uniqueness_of :receiver_id, :scope => [:sender_id, :sender_type]
- validate :sender_must_be_evaluation_or_reputation
-
- after_destroy :delete_sender_if_evaluation
-
- def self.add_reputation_message_if_not_exist(sender, receiver)
- rm = create(:sender => sender, :receiver => receiver)
- receiver.received_messages.push rm if rm.valid?
- end
-
- protected
-
- def delete_sender_if_evaluation
- sender.destroy if sender.is_a?(RSEvaluation)
- end
-
- def sender_must_be_evaluation_or_reputation
- unless sender.is_a?(RSEvaluation) || sender.is_a?(RSReputation)
- errors.add(:sender, "must be an evaluation or a reputation")
- end
- end
-
-end
View
@@ -18,12 +18,12 @@
require 'reputation_system/query_methods'
require 'reputation_system/finder_methods'
require 'reputation_system/query_builder'
-require 'reputation_system/evaluation'
+require 'reputation_system/evaluation_methods'
require 'reputation_system/network'
-require 'reputation_system/reputation'
-require 'reputation_system/scope'
-require 'models/rs_evaluation'
-require 'models/rs_reputation'
-require 'models/rs_reputation_message'
+require 'reputation_system/reputation_methods'
+require 'reputation_system/scope_methods'
+require 'reputation_system/models/evaluation'
+require 'reputation_system/models/reputation'
+require 'reputation_system/models/reputation_message'
ActiveRecord::Base.send(:include, ReputationSystem::Base)
@@ -40,27 +40,37 @@ def evaluate_reputation_scope(scope)
module ClassMethods
def has_reputation(reputation_name, options)
- has_valid_input = reputation_name && options[:aggregated_by] && options[:source]
+ has_valid_input = reputation_name && options[:source]
raise ArgumentError, "has_reputation method received invalid arguments." unless has_valid_input
# Overwrites reputation if the same reputation name is declared in the same model.
# TODO: This should raise exception instead while allowing Rails app to reload in dev mode.
ReputationSystem::Network.remove_reputation_def(name, reputation_name) if has_reputation_for?(reputation_name)
# If it is first time to be called
- unless ancestors.include?(ReputationSystem::Reputation)
- has_many :reputations, :as => :target, :class_name => "RSReputation", :dependent => :destroy
+ unless ancestors.include?(ReputationSystem::ReputationMethods)
+ has_many :reputations, :as => :target, :class_name => "ReputationSystem::Reputation", :dependent => :destroy do
+ def for(reputation_name)
+ self.where(:reputation_name => reputation_name)
+ end
+ end
+ has_many :evaluations, :as => :target, :class_name => "ReputationSystem::Evaluation", :dependent => :destroy do
+ def for(reputation_name)
+ self.where(:reputation_name => reputation_name)
+ end
+ end
+
include ReputationSystem::QueryBuilder
include ReputationSystem::QueryMethods
include ReputationSystem::FinderMethods
- include ReputationSystem::Reputation
- include ReputationSystem::Scope
+ include ReputationSystem::ReputationMethods
+ include ReputationSystem::ScopeMethods
end
ReputationSystem::Network.add_reputation_def(name, reputation_name, options)
# evaluation related methods are defined only for primary reputations
- include ReputationSystem::Evaluation if ReputationSystem::Network.is_primary_reputation?(name, reputation_name) && !ancestors.include?(ReputationSystem::Evaluation)
+ include ReputationSystem::EvaluationMethods if ReputationSystem::Network.is_primary_reputation?(name, reputation_name) && !ancestors.include?(ReputationSystem::EvaluationMethods)
end
def has_reputation_for?(reputation_name)
Oops, something went wrong.

0 comments on commit cd95ef4

Please sign in to comment.