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