lib/redis_counters/base_counter.rb
require 'forwardable'
require 'active_support/core_ext/class/attribute'
module RedisCounters
# Базовый класс счетчика на основе Redis.
class BaseCounter
extend Forwardable
KEY_DELIMITER = ':'.freeze
VALUE_DELIMITER = ':'.freeze
attr_reader :redis
attr_reader :options
attr_reader :params
# Public: Фабричный метод создания счетчика заданного класса.
#
# redis - Redis - экземпляр redis - клиента.
# opts - Hash - хеш опций счетчика:
# counter_name - Symbol/String - идентификатор счетчика.
# key_delimiter - String - разделитель ключа (опционально).
# value_delimiter - Array[String] или String, разделитель значений. Если это массив, то первый элемент будет
# считатся новым разделителем, а второй старым. Все данные будут записываться, используя
# новый. Старый будет использоваться только для старых данных. Так что если надо сменить
# делимитр у счётчика, например с ':' на '�', то сперва надо будет установить его на ['�',
# ':'], а после дампа старых данных в БД, на '�'.
#
# Returns RedisCounters::BaseCounter.
def self.create(redis, opts)
counter_class = opts.fetch(:counter_class).to_s.constantize
counter_class.new(redis, opts)
end
# Public: Конструктор.
#
# см. self.create.
#
# Returns RedisCounters::BaseCounter.
#
def initialize(redis, opts)
@redis = redis
@options = opts
init
end
# Public: Метод производит обработку события.
#
# params - Hash - хеш параметров события.
#
# Returns process_value result.
#
def process(params = {}, &block)
@params = params.with_indifferent_access
process_value(&block)
end
def name
options[:counter_name]
end
alias_method :id, :name
protected
def init
counter_name.present?
end
def counter_name
@counter_name ||= options.fetch(:counter_name)
end
def key_delimiter
@key_delimiter ||= options.fetch(:key_delimiter, KEY_DELIMITER)
end
def value_delimiter
@value_delimiter ||= options.fetch(:value_delimiter, VALUE_DELIMITER)
end
def_delegator :redis, :multi, :transaction
end
end