module Mongo::Voteable::Tasks

Public Class Methods

init_stats(log = false) click to toggle source

Set counters and point to 0 for uninitialized voteable objects in order sort and query

# File lib/voteable_mongo/tasks.rb, line 7
def self.init_stats(log = false)
  VOTEABLE.each do |class_name, voteable|
    klass = class_name.constantize
    klass_voteable = voteable[class_name]
    puts "Init stats for #{class_name}" if log
    klass.where(votes: nil).set(votes: DEFAULT_VOTES)
  end
end
migrate_old_votes(log = false) click to toggle source

Convert votes from from version < 0.7.0 to new data store

# File lib/voteable_mongo/tasks.rb, line 23
def self.migrate_old_votes(log = false)
  VOTEABLE.each do |class_name, voteable|
    klass = class_name.constantize
    klass_voteable = voteable[class_name]
    puts "* Migrating old vote data for #{class_name} ..." if log
    migrate_old_votes_for(klass, klass_voteable)
  end
end
remake_stats(log = false) click to toggle source

Re-generate vote counters and vote points

# File lib/voteable_mongo/tasks.rb, line 17
def self.remake_stats(log = false)
  remake_stats_for_all_voteable_classes(log)
  update_parent_stats(log)
end

Private Class Methods

migrate_old_votes_for(klass, voteable) click to toggle source
# File lib/voteable_mongo/tasks.rb, line 32
def self.migrate_old_votes_for(klass, voteable)
  klass.all.each do |doc|
    # Version 0.6.x use very short field names (u, d, uc, dc, c, p) to minimize
    # votes storage but it's not human friendly
    # Version >= 0.7.0 use readable field names (up, down, up_count, down_count,
    # count, point)
    votes = doc['votes'] || doc['voteable'] || {}

    up_voter_ids = votes['up'] || votes['u'] ||
      votes['up_voter_ids'] || doc['up_voter_ids'] || []

    down_voter_ids = votes['down'] || votes['d'] ||
      votes['down_voter_ids'] || doc['down_voter_ids'] || []

    up_count = up_voter_ids.size
    down_count = down_voter_ids.size

    klass.collection.find({_id: doc.id}).update_many(
      '$set' => {
        'votes' => {
          'up' => up_voter_ids,
          'down' => down_voter_ids,
          'up_count' => up_count,
          'down_count' => down_count,
          'count' => up_count + down_count,
          'point' => voteable[:up].to_i*up_count + voteable[:down].to_i*down_count
        }
      },
      '$unset' => {
        'up_voter_ids' => true,
        'down_voter_ids' => true,
        'votes_count' => true,
        'votes_point' => true,
        'voteable' => true
      }
    )
  end
end
remake_stats_for(doc, voteable) click to toggle source
# File lib/voteable_mongo/tasks.rb, line 84
def self.remake_stats_for(doc, voteable)
  up_count = doc.up_voter_ids.length
  down_count = doc.down_voter_ids.length
  doc.update_attributes(
    'votes' => {
      'up' => doc.up_voter_ids,
      'down' => doc.down_voter_ids,
      'up_count' => up_count,
      'down_count' => down_count,
      'count' => up_count + down_count,
      'point' => voteable[:up].to_i*up_count + voteable[:down].to_i*down_count
    }
  )
end
remake_stats_for_all_voteable_classes(log) click to toggle source
# File lib/voteable_mongo/tasks.rb, line 72
def self.remake_stats_for_all_voteable_classes(log)
  VOTEABLE.each do |class_name, voteable|
    klass = class_name.constantize
    klass_voteable = voteable[class_name]
    puts "Generating stats for #{class_name}" if log
    klass.all.each{ |doc|
      remake_stats_for(doc, klass_voteable)
    }
  end
end
update_parent_stats(log) click to toggle source
# File lib/voteable_mongo/tasks.rb, line 100
def self.update_parent_stats(log)
  VOTEABLE.each do |class_name, voteable|
    klass = class_name.constantize
    voteable.each do |parent_class_name, parent_voteable|
      metadata = klass.voteable_relation(parent_class_name)
      if metadata
        parent_class = parent_class_name.constantize
        foreign_key = klass.voteable_foreign_key(metadata)
        puts "Updating stats for #{class_name} > #{parent_class_name}" if log
        klass.all.each{ |doc|
          update_parent_stats_for(doc, parent_class, foreign_key, parent_voteable)
        }
      end
    end
  end
end
update_parent_stats_for(doc, parent_class, foreign_key, voteable) click to toggle source
# File lib/voteable_mongo/tasks.rb, line 118
def self.update_parent_stats_for(doc, parent_class, foreign_key, voteable)
  parent_id = doc.read_attribute(foreign_key.to_sym)
  if parent_id
    up_count = doc.up_voter_ids.length
    down_count = doc.down_voter_ids.length

    return if up_count == 0 && down_count == 0

    inc_options = {
      'votes.point' => voteable[:up].to_i*up_count + voteable[:down].to_i*down_count
    }

    unless voteable[:update_counters] == false
      inc_options.merge!(
        'votes.count' => up_count + down_count,
        'votes.up_count' => up_count,
        'votes.down_count' => down_count
      )
    end

    parent_ids = parent_id.is_a?(Array) ? parent_id : [ parent_id ]

    parent_class.collection.find({'_id' => {'$in' => parent_ids}}).update_many({ '$inc' =>  inc_options })
  end
end