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.
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