diff --git a/Gemfile b/Gemfile index 6db22ce..0291a3c 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,8 @@ source 'https://rubygems.org' group :development, :test do gem 'combustion', github: 'pat/combustion', ref: '7d0d24c3f36ce0eb336177fc493be0721bc26665' + gem 'activerecord-postgres-hstore', require: false + gem 'simple_hstore_accessor', '~> 0.2', require: false end gem 'rack', '< 2' if RUBY_VERSION < '2.2.0' diff --git a/lib/redis_counters/dumpers/engine.rb b/lib/redis_counters/dumpers/engine.rb index ccc5024..67f79db 100644 --- a/lib/redis_counters/dumpers/engine.rb +++ b/lib/redis_counters/dumpers/engine.rb @@ -266,12 +266,8 @@ def columns_definition 'character varying(4000)' when :integer, :serial, :number 'integer' - when :date - 'date' - when :timestamp - 'timestamp' - when :boolean - 'boolean' + when :date, :timestamp, :boolean, :hstore + type.to_s else if type.is_a?(Array) && type.first == :enum type.last.fetch(:name) diff --git a/spec/internal/app/models/stats_by_day.rb b/spec/internal/app/models/stats_by_day.rb index f0a71c1..6d8659a 100644 --- a/spec/internal/app/models/stats_by_day.rb +++ b/spec/internal/app/models/stats_by_day.rb @@ -1,2 +1,3 @@ class StatsByDay < ActiveRecord::Base + store_accessor :params end diff --git a/spec/internal/app/models/stats_total.rb b/spec/internal/app/models/stats_total.rb index 2ada32c..13ed31c 100644 --- a/spec/internal/app/models/stats_total.rb +++ b/spec/internal/app/models/stats_total.rb @@ -1,2 +1,3 @@ class StatsTotal < ActiveRecord::Base + store_accessor :params end diff --git a/spec/internal/db/schema.rb b/spec/internal/db/schema.rb index 47a7b55..6549291 100644 --- a/spec/internal/db/schema.rb +++ b/spec/internal/db/schema.rb @@ -3,12 +3,21 @@ CREATE TYPE subject_types AS ENUM (''); SQL + if ::ActiveRecord::VERSION::MAJOR < 4 + execute <<-SQL + CREATE EXTENSION IF NOT EXISTS hstore; + SQL + else + enable_extension :hstore + end + create_table :stats_by_days do |t| t.integer :record_id, null: false t.integer :column_id, null: false t.date :date, null: false t.integer :hits, null: false, default: 0 t.column :subject, :subject_types + t.hstore :params end add_index :stats_by_days, [:record_id, :column_id, :date], unique: true @@ -18,6 +27,7 @@ t.integer :column_id, null: false t.integer :hits, null: false, default: 0 t.column :subject, :subject_types + t.hstore :params end add_index :stats_totals, [:record_id, :column_id], unique: true diff --git a/spec/lib/redis_counters/dumpers/engine_spec.rb b/spec/lib/redis_counters/dumpers/engine_spec.rb index 044a93d..d3c791d 100644 --- a/spec/lib/redis_counters/dumpers/engine_spec.rb +++ b/spec/lib/redis_counters/dumpers/engine_spec.rb @@ -8,12 +8,13 @@ column_id: :integer, value: :integer, date: :date, - subject: [:enum, {name: :subject_types}] + subject: [:enum, {name: :subject_types}], + params: :hstore destination do model StatsByDay - take :record_id, :column_id, :hits, :date - key_fields :record_id, :column_id, :date + take :record_id, :column_id, :hits, :date, :params + key_fields :record_id, :column_id, :date, :params increment_fields :hits map :hits, to: :value condition 'target.date = :date' @@ -21,8 +22,8 @@ destination do model StatsTotal - take :record_id, :column_id, :hits - key_fields :record_id, :column_id + take :record_id, :column_id, :hits, :params + key_fields :record_id, :column_id, :params increment_fields :hits map :hits, to: :value end @@ -52,7 +53,7 @@ RedisCounters.create_counter(Redis.current, counter_class: RedisCounters::HashCounter, counter_name: :record_hits_by_day, - group_keys: [:record_id, :column_id, :subject], + group_keys: [:record_id, :column_id, :subject, :params], partition_keys: [:date] ) end @@ -63,35 +64,39 @@ describe '#process!' do before do - counter.increment(date: prev_date_s, record_id: 1, column_id: 100, subject: '') - counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '') - counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '') - counter.increment(date: prev_date_s, record_id: 2, column_id: 100, subject: nil) + counter.increment(date: prev_date_s, record_id: 1, column_id: 100, subject: '', params: '') + counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '', params: '') + counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '', params: '') + counter.increment(date: prev_date_s, record_id: 2, column_id: 100, subject: nil, params: '') + + params = {a: 1}.stringify_keys.to_s[1..-2] + counter.increment(date: prev_date_s, record_id: 3, column_id: 300, subject: nil, params: params) dumper.process!(counter, date: prev_date) - counter.increment(date: date_s, record_id: 1, column_id: 100, subject: '') - counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '') - counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '') - counter.increment(date: date_s, record_id: 2, column_id: 100, subject: nil) + counter.increment(date: date_s, record_id: 1, column_id: 100, subject: '', params: '') + counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '', params: '') + counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '', params: '') + counter.increment(date: date_s, record_id: 2, column_id: 100, subject: nil, params: '') dumper.process!(counter, date: date) end - Then { expect(StatsByDay.count).to eq 6 } + Then { expect(StatsByDay.count).to eq 7 } And { expect(StatsByDay.where(record_id: 1, column_id: 100, date: prev_date).first.hits).to eq 1 } And { expect(StatsByDay.where(record_id: 1, column_id: 200, date: prev_date).first.hits).to eq 2 } And { expect(StatsByDay.where(record_id: 2, column_id: 100, date: prev_date).first.hits).to eq 1 } + And { expect(StatsByDay.where(record_id: 3, column_id: 300, date: prev_date).first.params).to eq("a" => "1") } And { expect(StatsByDay.where(record_id: 1, column_id: 100, date: date).first.hits).to eq 1 } And { expect(StatsByDay.where(record_id: 1, column_id: 200, date: date).first.hits).to eq 2 } And { expect(StatsByDay.where(record_id: 2, column_id: 100, date: date).first.hits).to eq 1 } - And { expect(StatsTotal.count).to eq 3 } + And { expect(StatsTotal.count).to eq 4 } And { expect(StatsTotal.where(record_id: 1, column_id: 100).first.hits).to eq 2 } And { expect(StatsTotal.where(record_id: 1, column_id: 200).first.hits).to eq 4 } And { expect(StatsTotal.where(record_id: 2, column_id: 100).first.hits).to eq 2 } - And { expect(StatsAggTotal.count).to eq 2 } + And { expect(StatsAggTotal.count).to eq 3 } And { expect(StatsAggTotal.where(record_id: 1).first.hits).to eq 6 } And { expect(StatsAggTotal.where(record_id: 2).first.hits).to eq 2 } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9ab4c25..984d32c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,6 +2,11 @@ require 'bundler/setup' require 'redis_counters/dumpers' +if ::ActiveRecord::VERSION::MAJOR < 4 + require 'activerecord-postgres-hstore' + require 'simple_hstore_accessor' +end + require 'combustion' Combustion.initialize! :active_record