Sha256: 9042ce9eeee74bb6dcbec98f6f22c6fe33316d7ff3c364d2cf1ccc120bf05da5

Contents?: true

Size: 1.86 KB

Versions: 1

Compression:

Stored size: 1.86 KB

Contents

require 'ohm'
require 'ohm/contrib'

module Ohm
  module Tallyable
    module Macros
      def tally(attribute, options={})
        tallies[attribute] = options
      end

      def tallies
        @tallies ||= {}
      end

      def leaderboard(attribute, by=nil)
        raise ArgumentError if !_has_tally(attribute, by)

        _load_zset(_tally_key(attribute, by))
          .map { |k, v| [k, v.to_i] }
          .sort_by { |k, v| [-v, k] }
      end

      def _has_tally(attribute, by=nil)
        tally = tallies[attribute]
        !!(tally && (!tally[:by] || (by && by.include?(tally[:by]))))
      end

      def _tally_key(attribute, by=nil)
        key = self.key[:tallies][attribute]
        if by
          key = key[by.keys.first][by.values.first]
        end
        key
      end

      if Redis::VERSION.to_i == 2
        def _load_zset(key)
          key.zrevrange(0, -1, with_scores: true).each_slice(2)
        end
      else
        def _load_zset(key)
          key.zrevrange(0, -1, with_scores: true)
        end
      end
    end

    def self.included(model)
      model.before(:delete, :_decrement_tallies)
      model.before(:save, :_decrement_tallies)
      model.after(:save, :_increment_tallies)

      model.extend(Macros)
    end

    def _decrement_tallies
      _update_tallies(-1) { |attribute| read_remote(attribute) }
    end

    def _increment_tallies
      _update_tallies(1) { |attribute| send(attribute) }
    end

    def _update_tallies(amount, &block)
      self.class.tallies.each do |attribute, options|
        value = yield(attribute)
        key = self.class.key[:tallies][attribute]
        if options[:by]
          value_by = yield(options[:by])
          key = key[options[:by]][value_by]
        end
        if value
          key.zincrby(amount, value)
          key.zrem(value) if key.zscore(value) == 0.0
        end
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
ohm-tallyable-0.1.2 lib/ohm/tallyable.rb