Module: ActsAsRrranking::ClassMethods

Defined in:
lib/acts_as_rrranking.rb

Instance Method Summary collapse

Instance Method Details

#acts_as_rrranking(ranking_key, options = {}) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/acts_as_rrranking.rb', line 8

def acts_as_rrranking(ranking_key, options = {})
  @ranking_key = ranking_key
  @redis_ranking_key = "#{self.name.underscore}_#{@ranking_key}"
  @score_key = options[:score] || :score
  @ranking_id = options[:id] || :id

  class_eval <<-STR
    def update_#{@ranking_key}
      self.class.redis.zadd('#{@redis_ranking_key}', self.#{@score_key}, self.#{@ranking_id})
    end

    def delete_#{@ranking_key}
      self.class.redis.zrem('#{@redis_ranking_key}', self.#{@ranking_id})
    end

    def current_#{@ranking_key}
      if self.#{@score_key} && self.#{@score_key} > 0
        (self.class.redis.zrevrank('#{@redis_ranking_key}', self.#{@ranking_id}) || -1).try(:+, 1)
      else
        nil
      end
    end

    after_save :update_#{@ranking_key}
    after_destroy :delete_#{@ranking_key}
  STR

  instance_eval <<-STR
    def top_#{@ranking_key.to_s.pluralize}(limit = 10, offset = 0)
      self.redis.zrange('#{@redis_ranking_key}', -limit - offset, -1 - offset).reverse.map(&:to_i)
    end

    def top_#{@ranking_key}_#{self.name.demodulize.underscore.pluralize}(limit = 10, offset = 0)
      ids = self.top_#{@ranking_key.to_s.pluralize}(limit, offset)
      self.where(#{@ranking_id}: ids).order(self.ranking_order_by_statement(ids))
    end

    def redis_ranking_key
      '#{@redis_ranking_key}'
    end

    def remove_all_redis_ranking_data
      self.redis.zremrangebyrank('#{@redis_ranking_key}', 0, -1)
    end
  STR
end

#db_adapterObject



71
72
73
# File 'lib/acts_as_rrranking.rb', line 71

def db_adapter
  @db_name ||= ActiveRecord::Base.connection_config[:adapter]
end

#ranking_order_by_statement(ids) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/acts_as_rrranking.rb', line 55

def ranking_order_by_statement(ids)
  case self.db_adapter
  when /^mysql/
    "FIELD(id, #{ids.join(',')})"
  when /^sqlite/
    stat = "CASE id"
    ids.each_with_index do |id, index|
      stat << " WHEN #{id} THEN #{index}"
    end
    stat << " END"
    stat
  else
    raise "Database not supported"
  end
end

#redisObject



79
80
81
# File 'lib/acts_as_rrranking.rb', line 79

def redis
  @redis || Redis.current || raise("Redis connection not set")
end

#redis=(conn) ⇒ Object



75
76
77
# File 'lib/acts_as_rrranking.rb', line 75

def redis=(conn)
  @redis = conn
end