almicube 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +44 -0
  3. data/Rakefile +6 -0
  4. data/almicube.gemspec +3 -0
  5. data/lib/almicube/aggregator/base.rb +25 -0
  6. data/lib/almicube/aggregator/sum_aggregator.rb +23 -0
  7. data/lib/almicube/builder.rb +27 -30
  8. data/lib/almicube/bundler/base.rb +18 -0
  9. data/lib/almicube/bundler/days_ago_bundler.rb +22 -0
  10. data/lib/almicube/bundler/today_bundler.rb +9 -0
  11. data/lib/almicube/bundler/weekly_bundler.rb +11 -0
  12. data/lib/almicube/bundler/yesterday_bundler.rb +16 -0
  13. data/lib/almicube/cog.rb +11 -0
  14. data/lib/almicube/config.rb +40 -0
  15. data/lib/almicube/engine.rb +6 -0
  16. data/lib/almicube/key.rb +46 -0
  17. data/lib/almicube/model.rb +2 -5
  18. data/lib/almicube/proxy/association_proxy.rb +1 -1
  19. data/lib/almicube/ranking/base.rb +63 -0
  20. data/lib/almicube/ranking/data_ranking.rb +128 -0
  21. data/lib/almicube/ranking/sub_ranking.rb +51 -0
  22. data/lib/almicube/selector/all_selector.rb +18 -0
  23. data/lib/almicube/selector/base.rb +32 -0
  24. data/lib/almicube/selector/has_many_selector.rb +42 -0
  25. data/lib/almicube/selector/method_selector.rb +34 -0
  26. data/lib/almicube/version.rb +1 -1
  27. data/lib/almicube.rb +34 -4
  28. data/spec/almicube/aggregator/sum_aggregator_spec.rb +92 -0
  29. data/spec/almicube/builder_sprc.rb +22 -0
  30. data/spec/almicube/bundler/days_ago_bundler_spec.rb +20 -0
  31. data/spec/almicube/bundler/today_bundler_spec.rb +24 -0
  32. data/spec/almicube/bundler/yesterday_bundler_spec.rb +16 -0
  33. data/spec/almicube/config_spec.rb +46 -0
  34. data/spec/almicube/key_spec.rb +30 -0
  35. data/spec/almicube/ranking/base_spec.rb +9 -0
  36. data/spec/almicube/ranking/data_ranking_spec.rb +103 -0
  37. data/spec/almicube/ranking/sub_ranking_spec.rb +34 -0
  38. data/spec/almicube/selector/all_selector_spec.rb +22 -0
  39. data/spec/almicube/selector/method_selector_spec.rb +39 -0
  40. data/spec/almicube/selector/mock_spec.rb +34 -0
  41. data/spec/mocks/aggregator.rb +2 -0
  42. data/spec/mocks/bundler.rb +5 -0
  43. data/spec/mocks/model.rb +17 -0
  44. data/spec/mocks/selector.rb +9 -0
  45. data/spec/spec_helper.rb +11 -0
  46. data/spec/supports/shared_examples.rb +22 -0
  47. metadata +89 -7
  48. data/lib/almicube/builder/average_ranking_builder.rb +0 -35
  49. data/lib/almicube/builder/countable_ranking_builder.rb +0 -35
  50. data/lib/almicube/ranged_ranking.rb +0 -57
  51. data/lib/almicube/ranking.rb +0 -134
@@ -0,0 +1,17 @@
1
+ require 'active_model'
2
+
3
+ class MockModel
4
+ extend ::ActiveModel::Model
5
+
6
+ def self.all
7
+ end
8
+ end
9
+
10
+ class MockModelForSelector
11
+ def self.all
12
+ end
13
+
14
+ def self.count
15
+ end
16
+ end
17
+
@@ -0,0 +1,9 @@
1
+ class MockSelector < Almicube::Selector::Base
2
+ def initialize(options={})
3
+ @records = options[:records]
4
+ end
5
+
6
+ def records
7
+ @records
8
+ end
9
+ end
@@ -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.2
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-04-25 00:00:00.000000000 Z
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/builder/average_ranking_builder.rb
57
- - lib/almicube/builder/countable_ranking_builder.rb
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/ranged_ranking.rb
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
@@ -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