almicube 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +44 -0
- data/Rakefile +6 -0
- data/almicube.gemspec +3 -0
- data/lib/almicube/aggregator/base.rb +25 -0
- data/lib/almicube/aggregator/sum_aggregator.rb +23 -0
- data/lib/almicube/builder.rb +27 -30
- data/lib/almicube/bundler/base.rb +18 -0
- data/lib/almicube/bundler/days_ago_bundler.rb +22 -0
- data/lib/almicube/bundler/today_bundler.rb +9 -0
- data/lib/almicube/bundler/weekly_bundler.rb +11 -0
- data/lib/almicube/bundler/yesterday_bundler.rb +16 -0
- data/lib/almicube/cog.rb +11 -0
- data/lib/almicube/config.rb +40 -0
- data/lib/almicube/engine.rb +6 -0
- data/lib/almicube/key.rb +46 -0
- data/lib/almicube/model.rb +2 -5
- data/lib/almicube/proxy/association_proxy.rb +1 -1
- data/lib/almicube/ranking/base.rb +63 -0
- data/lib/almicube/ranking/data_ranking.rb +128 -0
- data/lib/almicube/ranking/sub_ranking.rb +51 -0
- data/lib/almicube/selector/all_selector.rb +18 -0
- data/lib/almicube/selector/base.rb +32 -0
- data/lib/almicube/selector/has_many_selector.rb +42 -0
- data/lib/almicube/selector/method_selector.rb +34 -0
- data/lib/almicube/version.rb +1 -1
- data/lib/almicube.rb +34 -4
- data/spec/almicube/aggregator/sum_aggregator_spec.rb +92 -0
- data/spec/almicube/builder_sprc.rb +22 -0
- data/spec/almicube/bundler/days_ago_bundler_spec.rb +20 -0
- data/spec/almicube/bundler/today_bundler_spec.rb +24 -0
- data/spec/almicube/bundler/yesterday_bundler_spec.rb +16 -0
- data/spec/almicube/config_spec.rb +46 -0
- data/spec/almicube/key_spec.rb +30 -0
- data/spec/almicube/ranking/base_spec.rb +9 -0
- data/spec/almicube/ranking/data_ranking_spec.rb +103 -0
- data/spec/almicube/ranking/sub_ranking_spec.rb +34 -0
- data/spec/almicube/selector/all_selector_spec.rb +22 -0
- data/spec/almicube/selector/method_selector_spec.rb +39 -0
- data/spec/almicube/selector/mock_spec.rb +34 -0
- data/spec/mocks/aggregator.rb +2 -0
- data/spec/mocks/bundler.rb +5 -0
- data/spec/mocks/model.rb +17 -0
- data/spec/mocks/selector.rb +9 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/supports/shared_examples.rb +22 -0
- metadata +89 -7
- data/lib/almicube/builder/average_ranking_builder.rb +0 -35
- data/lib/almicube/builder/countable_ranking_builder.rb +0 -35
- data/lib/almicube/ranged_ranking.rb +0 -57
- data/lib/almicube/ranking.rb +0 -134
data/spec/mocks/model.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
Bundler.require
|
6
|
+
|
7
|
+
Dir[File.join(File.dirname(__FILE__), "supports", "*.rb")].each {|f| require f}
|
8
|
+
Dir[File.join(File.dirname(__FILE__), "mocks", "*.rb")].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
shared_examples "ranking cog" do
|
2
|
+
let(:ranking) { Almicube::Ranking::DataRanking.new }
|
3
|
+
describe "#ranking=" do
|
4
|
+
it { expect{ target.ranking = ranking }.not_to raise_error }
|
5
|
+
end
|
6
|
+
|
7
|
+
describe "#ranking" do
|
8
|
+
before { target.ranking = ranking }
|
9
|
+
it { expect(target.ranking).to eq ranking }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#active?" do
|
13
|
+
context "setted ranking" do
|
14
|
+
before { target.ranking = ranking }
|
15
|
+
it { expect(target).to be_active }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "don't set ranking" do
|
19
|
+
it { expect(target).not_to be_active }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: almicube
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- niaeashes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -38,6 +38,34 @@ dependencies:
|
|
38
38
|
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '4.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activemodel
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.0'
|
41
69
|
description: Provide raking system for your ActiveRecord Model on Rails 4 with SortedSet
|
42
70
|
of Redis DataBase.
|
43
71
|
email:
|
@@ -48,18 +76,53 @@ extra_rdoc_files: []
|
|
48
76
|
files:
|
49
77
|
- .gitignore
|
50
78
|
- Gemfile
|
79
|
+
- Gemfile.lock
|
51
80
|
- LICENSE
|
52
81
|
- README.md
|
82
|
+
- Rakefile
|
53
83
|
- almicube.gemspec
|
54
84
|
- lib/almicube.rb
|
85
|
+
- lib/almicube/aggregator/base.rb
|
86
|
+
- lib/almicube/aggregator/sum_aggregator.rb
|
55
87
|
- lib/almicube/builder.rb
|
56
|
-
- lib/almicube/
|
57
|
-
- lib/almicube/
|
88
|
+
- lib/almicube/bundler/base.rb
|
89
|
+
- lib/almicube/bundler/days_ago_bundler.rb
|
90
|
+
- lib/almicube/bundler/today_bundler.rb
|
91
|
+
- lib/almicube/bundler/weekly_bundler.rb
|
92
|
+
- lib/almicube/bundler/yesterday_bundler.rb
|
93
|
+
- lib/almicube/cog.rb
|
94
|
+
- lib/almicube/config.rb
|
95
|
+
- lib/almicube/engine.rb
|
96
|
+
- lib/almicube/key.rb
|
58
97
|
- lib/almicube/model.rb
|
59
98
|
- lib/almicube/proxy/association_proxy.rb
|
60
|
-
- lib/almicube/
|
61
|
-
- lib/almicube/ranking.rb
|
99
|
+
- lib/almicube/ranking/base.rb
|
100
|
+
- lib/almicube/ranking/data_ranking.rb
|
101
|
+
- lib/almicube/ranking/sub_ranking.rb
|
102
|
+
- lib/almicube/selector/all_selector.rb
|
103
|
+
- lib/almicube/selector/base.rb
|
104
|
+
- lib/almicube/selector/has_many_selector.rb
|
105
|
+
- lib/almicube/selector/method_selector.rb
|
62
106
|
- lib/almicube/version.rb
|
107
|
+
- spec/almicube/aggregator/sum_aggregator_spec.rb
|
108
|
+
- spec/almicube/builder_sprc.rb
|
109
|
+
- spec/almicube/bundler/days_ago_bundler_spec.rb
|
110
|
+
- spec/almicube/bundler/today_bundler_spec.rb
|
111
|
+
- spec/almicube/bundler/yesterday_bundler_spec.rb
|
112
|
+
- spec/almicube/config_spec.rb
|
113
|
+
- spec/almicube/key_spec.rb
|
114
|
+
- spec/almicube/ranking/base_spec.rb
|
115
|
+
- spec/almicube/ranking/data_ranking_spec.rb
|
116
|
+
- spec/almicube/ranking/sub_ranking_spec.rb
|
117
|
+
- spec/almicube/selector/all_selector_spec.rb
|
118
|
+
- spec/almicube/selector/method_selector_spec.rb
|
119
|
+
- spec/almicube/selector/mock_spec.rb
|
120
|
+
- spec/mocks/aggregator.rb
|
121
|
+
- spec/mocks/bundler.rb
|
122
|
+
- spec/mocks/model.rb
|
123
|
+
- spec/mocks/selector.rb
|
124
|
+
- spec/spec_helper.rb
|
125
|
+
- spec/supports/shared_examples.rb
|
63
126
|
homepage: https://github.com/niaeashes/almicube
|
64
127
|
licenses:
|
65
128
|
- MIT
|
@@ -84,4 +147,23 @@ rubygems_version: 2.2.2
|
|
84
147
|
signing_key:
|
85
148
|
specification_version: 4
|
86
149
|
summary: Ranking extension for your model
|
87
|
-
test_files:
|
150
|
+
test_files:
|
151
|
+
- spec/almicube/aggregator/sum_aggregator_spec.rb
|
152
|
+
- spec/almicube/builder_sprc.rb
|
153
|
+
- spec/almicube/bundler/days_ago_bundler_spec.rb
|
154
|
+
- spec/almicube/bundler/today_bundler_spec.rb
|
155
|
+
- spec/almicube/bundler/yesterday_bundler_spec.rb
|
156
|
+
- spec/almicube/config_spec.rb
|
157
|
+
- spec/almicube/key_spec.rb
|
158
|
+
- spec/almicube/ranking/base_spec.rb
|
159
|
+
- spec/almicube/ranking/data_ranking_spec.rb
|
160
|
+
- spec/almicube/ranking/sub_ranking_spec.rb
|
161
|
+
- spec/almicube/selector/all_selector_spec.rb
|
162
|
+
- spec/almicube/selector/method_selector_spec.rb
|
163
|
+
- spec/almicube/selector/mock_spec.rb
|
164
|
+
- spec/mocks/aggregator.rb
|
165
|
+
- spec/mocks/bundler.rb
|
166
|
+
- spec/mocks/model.rb
|
167
|
+
- spec/mocks/selector.rb
|
168
|
+
- spec/spec_helper.rb
|
169
|
+
- spec/supports/shared_examples.rb
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Almicube
|
2
|
-
module Builder
|
3
|
-
class AverageRankingBuilder
|
4
|
-
extend Base
|
5
|
-
|
6
|
-
register :average
|
7
|
-
|
8
|
-
def initialize(options)
|
9
|
-
@options = self.default_options.merge(options)
|
10
|
-
end
|
11
|
-
|
12
|
-
def default_options
|
13
|
-
{ ranking_class: Almicube::Ranking, aggregate: :std }
|
14
|
-
end
|
15
|
-
|
16
|
-
def build(date)
|
17
|
-
ranking_class.new(ranking_options(date))
|
18
|
-
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
RANKING_OPTIONS = %i[class_name as date_format attribute_name per_page aggregate default_score]
|
23
|
-
|
24
|
-
def ranking_options(date = Date.today)
|
25
|
-
( @options.select{ |k| self.class::RANKING_OPTIONS.include? k } ).merge( date: date )
|
26
|
-
end
|
27
|
-
|
28
|
-
%i[ranking_class].each do |name|
|
29
|
-
define_method(name) do
|
30
|
-
@options[name]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Almicube
|
2
|
-
module Builder
|
3
|
-
class CountableRankingBuilder
|
4
|
-
extend Base
|
5
|
-
|
6
|
-
register :countable
|
7
|
-
|
8
|
-
def initialize(options)
|
9
|
-
@options = self.default_options.merge(options)
|
10
|
-
end
|
11
|
-
|
12
|
-
def default_options
|
13
|
-
{ ranking_class: Almicube::Ranking, aggregate: :sum }
|
14
|
-
end
|
15
|
-
|
16
|
-
def build(date)
|
17
|
-
ranking_class.new(ranking_options(date))
|
18
|
-
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
RANKING_OPTIONS = %i[class_name as date_format attribute_name per_page aggregate default_score]
|
23
|
-
|
24
|
-
def ranking_options(date = Date.today)
|
25
|
-
( @options.select{ |k| self.class::RANKING_OPTIONS.include? k } ).merge( date: date )
|
26
|
-
end
|
27
|
-
|
28
|
-
%i[ranking_class].each do |name|
|
29
|
-
define_method(name) do
|
30
|
-
@options[name]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
module Almicube
|
2
|
-
class RangedRanking < Almicube::Ranking
|
3
|
-
class << self
|
4
|
-
def overwrite_params
|
5
|
-
{ key: '%{prefix}:%{class_name}:%{range}:%{suffix}', type: :range }
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
def aggregate(options={})
|
10
|
-
keys = range_days(range).times.inject([]) do |keys, i|
|
11
|
-
key = key_format(@options[:data_key], @options.merge( date: date.to_date - i.days, type: :data ))
|
12
|
-
keys << key if connection.exists key
|
13
|
-
keys
|
14
|
-
end
|
15
|
-
if %i[sum max min].include? aggregate_method
|
16
|
-
connection.zunionstore key, keys, aggregate: aggregate_method
|
17
|
-
elsif aggregate_method == :std
|
18
|
-
weights = Array.new keys.length, (1.0/keys.length)
|
19
|
-
connection.zunionstore key, keys, aggregate: :sum, weights: weights
|
20
|
-
else
|
21
|
-
connection.zunionstore key, keys, aggregate: :sum
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def date
|
26
|
-
super - 1.days
|
27
|
-
end
|
28
|
-
|
29
|
-
def range
|
30
|
-
@options.fetch(:range, default_range)
|
31
|
-
end
|
32
|
-
|
33
|
-
def default_range
|
34
|
-
:weekly
|
35
|
-
end
|
36
|
-
|
37
|
-
def aggregate_method
|
38
|
-
aggregate = @options.fetch(:aggregate, :sum)
|
39
|
-
end
|
40
|
-
|
41
|
-
protected
|
42
|
-
|
43
|
-
def range_days(range, default = nil)
|
44
|
-
case range.to_sym
|
45
|
-
when :yesterday
|
46
|
-
1
|
47
|
-
when :weekly
|
48
|
-
7
|
49
|
-
when :monthly
|
50
|
-
30
|
51
|
-
else
|
52
|
-
return default unless default.nil?
|
53
|
-
range_days(default_range, 7)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/almicube/ranking.rb
DELETED
@@ -1,134 +0,0 @@
|
|
1
|
-
require "redis"
|
2
|
-
require "active_support/all"
|
3
|
-
|
4
|
-
module Almicube
|
5
|
-
class Ranking
|
6
|
-
class << self
|
7
|
-
def default_options
|
8
|
-
{ attribute_name: :score,
|
9
|
-
type: :data,
|
10
|
-
prefix: 'ranking:%{type}',
|
11
|
-
suffix: '%{attribute_name}',
|
12
|
-
key: '%{prefix}:%{class_name}:%{date}:%{suffix}',
|
13
|
-
date_format: '%Y%m%d',
|
14
|
-
date: Date.today,
|
15
|
-
per_page: 10,
|
16
|
-
as: Float,
|
17
|
-
default_score: 0,
|
18
|
-
class_name: nil }
|
19
|
-
end
|
20
|
-
|
21
|
-
def connection
|
22
|
-
@connection ||= Redis.new
|
23
|
-
end
|
24
|
-
|
25
|
-
def build(options={})
|
26
|
-
self.new options
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def initialize(options={})
|
31
|
-
@options = self.class.default_options.merge options.symbolize_keys
|
32
|
-
|
33
|
-
raise TypeError, ":as option is only allowed Integer or Float" unless [Integer, Float].include? @options[:as]
|
34
|
-
end
|
35
|
-
|
36
|
-
def ranged(range)
|
37
|
-
Almicube::RangedRanking.new @options.merge( range: range, data_key: @options[:key] ).merge(Almicube::RangedRanking.overwrite_params)
|
38
|
-
end
|
39
|
-
|
40
|
-
KEY_PATTERN = /%{([a-z_]+)}/ # Example) %{sample_key}
|
41
|
-
|
42
|
-
def key
|
43
|
-
key_format(@options[:key], @options)
|
44
|
-
end
|
45
|
-
|
46
|
-
def all
|
47
|
-
target_class.all
|
48
|
-
end
|
49
|
-
|
50
|
-
def page(page=1)
|
51
|
-
page = [1, page.to_i].max
|
52
|
-
revrange = connection.zrevrange(key, (page - 1) * per_page, page * per_page - 1)
|
53
|
-
records = target_class.where("id IN (?)", revrange).all
|
54
|
-
revrange.inject([]) { |l, v| l << records.detect { |r| r.to_param == v } }
|
55
|
-
end
|
56
|
-
|
57
|
-
def attribute_name
|
58
|
-
@options.fetch(:attribute_name, :score).to_s.to_sym
|
59
|
-
end
|
60
|
-
|
61
|
-
def date
|
62
|
-
@options.fetch(:date, Date.today)
|
63
|
-
end
|
64
|
-
|
65
|
-
def per_page
|
66
|
-
@options.fetch(:per_page, 0)
|
67
|
-
end
|
68
|
-
|
69
|
-
def per_page=(value)
|
70
|
-
@options[:per_page] = value
|
71
|
-
end
|
72
|
-
|
73
|
-
def aggregate!(options = {})
|
74
|
-
overwrite = !! ( options.try(:overwrite) || false )
|
75
|
-
raise "ranking is already exists. if you want to force aggregating: set { overwrite: true }" if exists? && ! overwrite
|
76
|
-
|
77
|
-
all.each do |record|
|
78
|
-
score = @options.fetch(:default_score, 0)
|
79
|
-
score = record.send attribute_name if record.respond_to? attribute_name
|
80
|
-
connection.zadd key, score.to_f, record.to_param
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def aggregate(options = {})
|
85
|
-
aggregate! options
|
86
|
-
true
|
87
|
-
rescue Exception => e
|
88
|
-
false
|
89
|
-
end
|
90
|
-
|
91
|
-
def exists?
|
92
|
-
connection.exists key
|
93
|
-
end
|
94
|
-
|
95
|
-
def score(item)
|
96
|
-
actual_score = ( connection.zscore key, item.to_param ) || @options.fetch(:default_score, 0)
|
97
|
-
case @options[:as].to_s
|
98
|
-
when "Integer"
|
99
|
-
actual_score.to_i
|
100
|
-
when "Float"
|
101
|
-
actual_score.to_f
|
102
|
-
else
|
103
|
-
actual_score
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def rank(item)
|
108
|
-
connection.zrevrank(key, item.to_param) + 1
|
109
|
-
end
|
110
|
-
|
111
|
-
def incr(item, score = 1)
|
112
|
-
connection.zincrby key, score, item.to_param
|
113
|
-
end
|
114
|
-
|
115
|
-
protected
|
116
|
-
|
117
|
-
def connection
|
118
|
-
self.class.connection
|
119
|
-
end
|
120
|
-
|
121
|
-
def target_class
|
122
|
-
@options[:class_name].to_s.constantize
|
123
|
-
end
|
124
|
-
|
125
|
-
def key_format(key_base, options)
|
126
|
-
key = key_base.to_s.clone
|
127
|
-
tmp_options = options.merge date: options.fetch(:date, Date.today).strftime(@options[:date_format])
|
128
|
-
key.match( self.class::KEY_PATTERN ) do |m|
|
129
|
-
key.gsub! m[0], tmp_options.fetch(m[1].to_sym, '').to_s
|
130
|
-
end while key =~ self.class::KEY_PATTERN
|
131
|
-
key
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|