lib/voteable_mongoid/voteable/voting.rb in voteable_mongoid-0.7.2 vs lib/voteable_mongoid/voteable/voting.rb in voteable_mongoid-0.7.3

- old
+ new

@@ -8,56 +8,62 @@ # # @param [Hash] options a hash containings: # - :votee_id: the votee document id # - :voter_id: the voter document id # - :value: :up or :down - # - :revote: change from vote up to vote down - # - :unvote: unvote the vote value (:up or :down) + # - :revote: if true change vote vote from :up to :down and vise versa + # - :unvote: if true undo the voting + # - :return: if true always return updated voteable object + # + # @return [votes, false, nil] def vote(options) - options.symbolize_keys! - options[:votee_id] ||= options[:votee].id - options[:votee_id] = BSON::ObjectId(options[:votee_id]) if options[:votee_id].is_a?(String) - options[:voter_id] = BSON::ObjectId(options[:voter_id]) if options[:voter_id].is_a?(String) - options[:value] = options[:value].to_sym + validate_and_normalize_vote_options(options) options[:voteable] = VOTEABLE[name][name] - update_parents = options[:voteable][:update_parents] - if options[:voteable] query, update = if options[:revote] - revote(options) + revote_query_and_update(options) elsif options[:unvote] - unvote(options) + unvote_query_and_update(options) else - new_vote(options) + new_vote_query_and_update(options) end - if options[:votee] || update_parents + if options[:voteable][:update_parents] || options[:votee] || options[:return_votee] # If votee exits or need to update parent # use Collection#find_and_modify to retrieve updated votes data and parent_ids begin doc = collection.master.collection.find_and_modify( :query => query, :update => update, :new => true ) # Update new votes data options[:votee].write_attribute('votes', doc['votes']) if options[:votee] - update_parent_votes(doc, options) if update_parents + update_parent_votes(doc, options) if options[:voteable][:update_parents] + return options[:votee] || new(doc) rescue # Don't update parents if operation fail or no matching object found + return false end else # Just update and don't care the result collection.update(query, update) end end end private - def new_vote(options) + def validate_and_normalize_vote_options(options) + options.symbolize_keys! + options[:votee_id] = BSON::ObjectId(options[:votee_id]) if options[:votee_id].is_a?(String) + options[:voter_id] = BSON::ObjectId(options[:voter_id]) if options[:voter_id].is_a?(String) + options[:value] &&= options[:value].to_sym + end + + def new_vote_query_and_update(options) if options[:value] == :up positive_voter_ids = 'votes.up' positive_votes_count = 'votes.up_count' else positive_voter_ids = 'votes.down' @@ -78,11 +84,11 @@ 'votes.point' => options[:voteable][options[:value]] } } end - def revote(options) + def revote_query_and_update(options) if options[:value] == :up positive_voter_ids = 'votes.up' negative_voter_ids = 'votes.down' positive_votes_count = 'votes.up_count' negative_votes_count = 'votes.down_count' @@ -111,11 +117,11 @@ } } end - def unvote(options) + def unvote_query_and_update(options) if options[:value] == :up positive_voter_ids = 'votes.up' negative_voter_ids = 'votes.down' positive_votes_count = 'votes.up_count' else @@ -140,32 +146,40 @@ } end def update_parent_votes(doc, options) - value = options[:value] - votee ||= options[:votee] - VOTEABLE[name].each do |class_name, voteable| - # For other class in VOTEABLE options, if is parent of current class - next unless relation_metadata = relations[class_name.underscore] - # If can find current votee foreign_key value for that class - next unless foreign_key_value = doc[relation_metadata.foreign_key.to_s] + # For other class in VOTEABLE options, if has relationship with current class + relation_metadata = relations.find{ |x, r| r.class_name == class_name }.try(:last) + next unless relation_metadata.present? - class_name.constantize.collection.update( - { '_id' => foreign_key_value }, - { '$inc' => parent_inc_options(value, voteable, options) } - ) + # If cannot find current votee foreign_key value for that class + foreign_key_value = doc[relation_metadata.foreign_key.to_s] + next unless foreign_key_value.present? + + if relation_metadata.relation == Mongoid::Relations::Referenced::In + class_name.constantize.collection.update( + { '_id' => foreign_key_value }, + { '$inc' => parent_inc_options(voteable, options) } + ) + elsif relation_metadata.relation == Mongoid::Relations::Referenced::ManyToMany + class_name.constantize.collection.update( + { '_id' => { '$in' => foreign_key_value } }, + { '$inc' => parent_inc_options(voteable, options) }, + { :multi => true } + ) + end end end - def parent_inc_options(value, voteable, options) + def parent_inc_options(voteable, options) inc_options = {} if options[:revote] - if value == :up + if options[:value] == :up inc_options['votes.point'] = voteable[:up] - voteable[:down] unless voteable[:update_counters] == false inc_options['votes.up_count'] = +1 inc_options['votes.down_count'] = -1 end @@ -176,24 +190,24 @@ inc_options['votes.down_count'] = +1 end end elsif options[:unvote] - inc_options['votes.point'] = -voteable[value] + inc_options['votes.point'] = -voteable[options[:value]] unless voteable[:update_counters] == false inc_options['votes.count'] = -1 - if value == :up + if options[:value] == :up inc_options['votes.up_count'] = -1 else inc_options['votes.down_count'] = -1 end end else # new vote - inc_options['votes.point'] = voteable[value] + inc_options['votes.point'] = voteable[options[:value]] unless voteable[:update_counters] == false inc_options['votes.count'] = +1 - if value == :up + if options[:value] == :up inc_options['votes.up_count'] = +1 else inc_options['votes.down_count'] = +1 end end