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,32 @@
1
+ module Almicube
2
+ module Selector
3
+ class Base
4
+ include Almicube::Cog
5
+
6
+ attr_reader :class_name
7
+
8
+ def initialize(options={})
9
+ @class_name = options[:class_name]
10
+ @class_name = class_name.constantize if class_name.is_a? String
11
+ @label = options[:label]
12
+ end
13
+
14
+ alias :model_class :class_name
15
+
16
+ def label
17
+ @label
18
+ end
19
+
20
+ def data_provider?
21
+ false
22
+ end
23
+
24
+ def before_aggregate
25
+ end
26
+
27
+ def interstore
28
+ nil
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+ module Almicube
2
+ module Selector
3
+ class HasManySelector < Base
4
+
5
+ attr_reader :target, :association_name
6
+
7
+ def initialize(options={})
8
+ super(options)
9
+
10
+ @target = options[:target]
11
+ @association_name = options[:association_name]
12
+ end
13
+
14
+ def records
15
+ target.send(association_name)
16
+ end
17
+
18
+ def label
19
+ "#{target.class.to_s.underscore}-#{target.to_param}"
20
+ end
21
+
22
+ def before_aggregate
23
+ records.map{ |r| r.to_param }.each do |i|
24
+ Config.config.connection.zadd(interstore_key, 0, i)
25
+ end
26
+ end
27
+
28
+ def interstore
29
+ interstore_key
30
+ end
31
+
32
+ protected
33
+
34
+ def interstore_key
35
+ _key = ranking.key
36
+ _key[:distinction] = label
37
+ _key[:suffix] = ""
38
+ _key
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,34 @@
1
+ module Almicube
2
+ module Selector
3
+ class MethodSelector < Base
4
+ attr_reader :accessor, :counter
5
+
6
+ def initialize(options={})
7
+ super(options)
8
+
9
+ @accessor = options[:accessor] || :all
10
+ @counter = options[:counter] || :count
11
+
12
+ raise "invalid options" unless valid?
13
+ end
14
+
15
+ def records
16
+ class_name.send(accessor)
17
+ end
18
+
19
+ def count
20
+ class_name.send(counter)
21
+ end
22
+
23
+ def valid?
24
+ validate_accessor
25
+ end
26
+
27
+ protected
28
+
29
+ def validate_accessor
30
+ class_name.class == Class && class_name.respond_to?(accessor)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module Almicube
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
data/lib/almicube.rb CHANGED
@@ -1,16 +1,46 @@
1
+ require 'yaml'
2
+
1
3
  module Almicube
2
- autoload :Ranking, 'almicube/ranking'
4
+ module Ranking
5
+ autoload :Base, 'almicube/ranking/base'
6
+ autoload :DataRanking, 'almicube/ranking/data_ranking'
7
+ autoload :SubRanking, 'almicube/ranking/sub_ranking'
8
+ end
9
+
3
10
  autoload :RangedRanking, 'almicube/ranged_ranking'
4
11
  autoload :Model, 'almicube/model'
5
12
  autoload :AssociationProxy, 'almicube/proxy/association_proxy'
13
+ autoload :Config, 'almicube/config'
14
+ autoload :Cog, 'almicube/cog'
15
+ autoload :Key, 'almicube/key'
6
16
 
7
17
  autoload :Builder, 'almicube/builder'
8
- module Builder
9
- autoload :CountableRankingBuilder, 'almicube/builder/countable_ranking_builder'
10
- autoload :AverageRankingBuilder, 'almicube/builder/average_ranking_builder'
18
+
19
+ module Bundler
20
+ autoload :Base, 'almicube/bundler/base'
21
+ autoload :DaysAgoBundler, 'almicube/bundler/days_ago_bundler'
22
+ autoload :TodayBundler, 'almicube/bundler/today_bundler'
23
+ autoload :YesterdayBundler, 'almicube/bundler/yesterday_bundler'
24
+ autoload :WeeklyBundler, 'almicube/bundler/weekly_bundler'
25
+ end
26
+
27
+ module Selector
28
+ autoload :Base, 'almicube/selector/base'
29
+ autoload :AllSelector, 'almicube/selector/all_selector'
30
+ autoload :MethodSelector, 'almicube/selector/method_selector'
31
+ autoload :HasManySelector, 'almicube/selector/has_many_selector'
32
+ end
33
+
34
+ module Aggregator
35
+ autoload :Base, 'almicube/aggregator/base'
36
+ autoload :SumAggregator, 'almicube/aggregator/sum_aggregator'
11
37
  end
12
38
 
13
39
  if defined? ActiveRecord
14
40
  ActiveRecord::Base.send :include, Almicube::Model
15
41
  end
42
+
43
+ if defined? Rails
44
+ require 'almicube/engine'
45
+ end
16
46
  end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Aggregator::SumAggregator do
4
+ let(:size) { 1 }
5
+ let(:size_d) { size * 10 }
6
+
7
+ before(:all) { @connection = Redis.new }
8
+ before { @connection.flushdb }
9
+
10
+ it { expect(size).to be > 0 }
11
+
12
+ shared_examples "correct aggregation" do
13
+ before { aggregator.ranking = ranking }
14
+
15
+ it "add new sorted set" do
16
+ expect{ aggregator.aggregate }.to change{ @connection.dbsize }.by 1
17
+ end
18
+ it "has correct items" do
19
+ expect(@connection.zcard(ranking.key)).to eq 0
20
+ aggregator.aggregate
21
+ expect(@connection.zcard(ranking.key)).to eq ranking.records.count
22
+ end
23
+ end
24
+
25
+ context "data ranking" do
26
+ context "target attribute is score" do
27
+ let(:ranking) { double( key: "sample:score", attribute_name: :score, data?: true ) }
28
+ let(:aggregator) { described_class.new }
29
+ before do
30
+ ranking.stub(:records) { size_d.times.map { |i| double( to_param: i, score: i*10 ) } }
31
+ end
32
+ it_behaves_like "correct aggregation"
33
+ end
34
+
35
+ context "target attribute is access" do
36
+ let(:ranking) { double( key: "sample:access", attribute_name: :access, data?: true) }
37
+ let(:aggregator) { described_class.new }
38
+ before do
39
+ ranking.stub(:records) { size_d.times.map { |i| double( to_param: i, access: 1000 ) } }
40
+ end
41
+ it_behaves_like "correct aggregation"
42
+ end
43
+ end
44
+
45
+ context "sub ranking" do
46
+ context "target attribute is score" do
47
+ let(:ranking) { double( key: "sample:score", bundled_keys: ["sample:score:1", "sample:score:2"], attribute_name: :score, data?: false ) }
48
+ let(:aggregator) { described_class.new }
49
+ before do
50
+ ranking.stub(:records) { size_d.times.map { |i| double( to_param: i, score: i*10 ) } }
51
+ 2.times.each do |i|
52
+ ranking.records.each do |record|
53
+ @connection.zadd("sample:score:#{i+1}", 20, record.to_param )
54
+ end
55
+ end
56
+ end
57
+ it_behaves_like "correct aggregation"
58
+ it "has ranking to set all score 40" do
59
+ aggregator.ranking = ranking
60
+ aggregator.aggregate
61
+ @connection.zrange("sample:score", 0, -1).each do |id|
62
+ expect(@connection.zscore("sample:score", id)).to eq 40
63
+ end
64
+ end
65
+ end
66
+
67
+ context "target attribute is access" do
68
+ let(:key) { "sample:access" }
69
+ let(:bundled_keys) { ["#{key}:1", "#{key}:2"] }
70
+ let(:ranking) { double( key: key, bundled_keys: bundled_keys, attribute_name: :access, data?: false ) }
71
+ let(:aggregator) { described_class.new }
72
+ before do
73
+ ranking.stub(:records) { size_d.times.map { |i| double( to_param: i, access: 1000 ) } }
74
+ 2.times.each do |i|
75
+ ranking.records.each { |record| @connection.zadd("#{key}:#{i+1}", 1000, record.to_param ) }
76
+ end
77
+ end
78
+ it_behaves_like "correct aggregation"
79
+ it "has ranking to set all score 2000" do
80
+ aggregator.ranking = ranking
81
+ aggregator.aggregate
82
+ @connection.zrange("sample:access", 0, -1).each do |id|
83
+ expect(@connection.zscore("sample:access", id)).to eq 2000
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ it_behaves_like "ranking cog" do
90
+ let(:target) { described_class.new }
91
+ end
92
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Builder do
4
+ let(:builder) { described_class.new }
5
+
6
+ describe "#selector" do
7
+ describe "defaults all selector" do
8
+ it { expect(builder.selector).to be_kind_of Almicube::Selector::AllSelector }
9
+ end
10
+
11
+ describe "with class name on initializer" do
12
+ before { builder.selector = "MockSelector" }
13
+ it { expect(builder.selector).to be_kind_of MockSelector }
14
+ end
15
+ end
16
+
17
+ describe "#data" do
18
+ describe "returns DataRanking instance" do
19
+ it { expect(builder.data).to be_kind_of Almicube::Ranking::DataRanking }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Bundler::DaysAgoBundler do
4
+ let(:ranking) { Almicube::Ranking::DataRanking.new }
5
+
6
+ describe "#name" do
7
+ let(:bundler) { described_class.new range: 7 }
8
+ before { bundler.ranking = ranking }
9
+ it { expect(bundler.name).to eq :"7-days-ago" }
10
+ end
11
+
12
+ describe "#keys" do
13
+ let(:bundler) { described_class.new range: 7 }
14
+ before { bundler.ranking = ranking }
15
+ it { expect(bundler.keys.length).to eq 7 }
16
+ 7.times.each do |i|
17
+ it { expect(bundler.keys[i]).to match /:#{(Date.today-(i+1).days).strftime("%Y%m%d")}:/ }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Bundler::TodayBundler do
4
+ let(:bundler) { described_class.new bundle: :bundle }
5
+
6
+ describe "#name" do
7
+ it { expect(bundler.name).to eq :bundle }
8
+ end
9
+
10
+ describe "#bundle" do
11
+ it { expect(bundler.bundle).to eq bundler.name }
12
+ end
13
+
14
+ describe "#active?" do
15
+ context "with ranking" do
16
+ before { bundler.ranking = double() }
17
+ it { expect(bundler).to be_active }
18
+ end
19
+
20
+ context "without ranking" do
21
+ it { expect(bundler).not_to be_active }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Bundler::YesterdayBundler do
4
+ describe "#name" do
5
+ let(:bundler) { described_class.new }
6
+ it { expect(bundler.name).to eq :yesterday }
7
+ end
8
+
9
+ describe "#keys" do
10
+ let(:ranking) { Almicube::Ranking::SubRanking.new(Almicube::Ranking::DataRanking.new) }
11
+ let(:bundler) { described_class.new }
12
+ before { bundler.ranking = ranking }
13
+ it { expect(bundler.keys[0]).to match /:#{(Date.today-1.days).strftime("%Y%m%d")}:/ }
14
+ it { expect(bundler.keys.length).to eq 1 }
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Config do
4
+ before do
5
+ File.stub(:exists?).and_return(true)
6
+ YAML.stub(:load_file).and_return(test_config)
7
+ described_class.reset
8
+ end
9
+
10
+ describe "#connection" do
11
+ let(:default_param) { { url: "redis://0.0.0.0:6380/1" } }
12
+ let(:development_param) { { url: "redis://0.0.0.0:6380/15" } }
13
+ let(:test_config) do
14
+ {
15
+ connection: {
16
+ default: default_param,
17
+ development: development_param
18
+ }
19
+ }
20
+ end
21
+
22
+ context "with default connection" do
23
+ before { Redis.should_receive(:new).with( default_param ) }
24
+ it { described_class.config.connection }
25
+ end
26
+
27
+ context "with actual connection" do
28
+ before { Redis.should_receive(:new).with( development_param ) }
29
+ it { described_class.config.connection :development }
30
+ end
31
+
32
+ context "with no-exists connection" do
33
+ before { Redis.stub(:new) }
34
+ it { expect{ described_class.config.connection :noexists }.to raise_error }
35
+ end
36
+
37
+ context "already setting up default connection" do
38
+ let(:redis) { double("redis") }
39
+ before do
40
+ Redis.stub(:new).and_return(redis)
41
+ described_class.config.connection
42
+ end
43
+ it { expect(described_class.config.connection).to eq redis }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Key do
4
+ describe "#options" do
5
+ context "pass options through constructor" do
6
+ let(:ranking) { Almicube::Ranking::DataRanking.new }
7
+ let(:key) { described_class.new ranking, prefix: "aaa", suffix: "bbb" }
8
+
9
+ it { expect(key[:prefix]).to eq "aaa" }
10
+ it { expect(key[:suffix]).to eq "bbb" }
11
+ end
12
+
13
+ context "pass options through ranking instance" do
14
+ let(:ranking) { Almicube::Ranking::DataRanking.new prefix: "ccc", suffix: "ddd" }
15
+ let(:key) { described_class.new ranking }
16
+
17
+ it { expect(key[:prefix]).to eq "ccc" }
18
+ it { expect(key[:suffix]).to eq "ddd" }
19
+ end
20
+ end
21
+
22
+ describe "#to_str" do
23
+ let(:ranking) { double( options: {} ) }
24
+ let(:key) { described_class.new ranking, prefix: "aaa", suffix: "bbb" }
25
+ before { key[:type] = :built }
26
+ it { expect("#{key}").to match /^aaa:/ }
27
+ it { expect("#{key}").to match /:bbb$/ }
28
+ it { expect("#{key}").to match /:built:/ }
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Ranking::Base do
4
+ describe "#bundled_keys" do
5
+ let(:bundler) { double( keys: ["1", "2"] ) }
6
+ let(:ranking) { described_class.new bundler: bundler }
7
+ it { expect(ranking.bundled_keys).to eq ["1", "2"] }
8
+ end
9
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ class MockAggregator < Almicube::Aggregator::Base
4
+ end
5
+
6
+ describe Almicube::Ranking::DataRanking do
7
+ describe "#selector" do
8
+ let(:ranking) { described_class.new selector: selector }
9
+
10
+ describe "sets the mock selector" do
11
+ let(:selector) { MockSelector.new records: records }
12
+ let(:records) { [double(), double()] }
13
+ it { expect(ranking.records).to eq records }
14
+ it { expect(ranking.selector).to eq selector }
15
+ end
16
+
17
+ describe "does not set the selector" do
18
+ let(:selector) { nil }
19
+ it { expect(ranking.selector).to be_kind_of Almicube::Selector::AllSelector }
20
+ end
21
+ end
22
+
23
+ describe "#aggregator" do
24
+ let(:ranking) { described_class.new aggregator: aggregator }
25
+
26
+ describe "set the mock aggregator" do
27
+ let(:aggregator) { MockAggregator.new }
28
+ before { aggregator.should_receive(:aggregate).with(ranking) }
29
+ it { ranking.aggregate }
30
+ end
31
+ end
32
+
33
+ describe "#per_page" do
34
+ let(:ranking) { described_class.new per_page: 10 }
35
+ it { expect(ranking.per_page).to eq 10 }
36
+ end
37
+
38
+ describe "#class_name" do
39
+ let(:ranking) { described_class.new class_name: MockModel }
40
+ it { expect(ranking.class_name).to eq MockModel }
41
+ end
42
+
43
+ describe "#data?" do
44
+ let(:ranking) { described_class.new }
45
+ it { expect(ranking).to be_data }
46
+ end
47
+
48
+ describe "#key" do
49
+ context "with prefix and suffix" do
50
+ let(:ranking) { described_class.new prefix: "aaa", suffix: "bbb" }
51
+ it { expect(ranking.key).to match /^aaa:/ }
52
+ it { expect(ranking.key).to match /:bbb$/ }
53
+ end
54
+
55
+ describe "differents between two days data" do
56
+ let(:today) { Date.today }
57
+ let(:ranking1) { described_class.new date: today }
58
+ let(:ranking2) { described_class.new date: today - 1.days }
59
+
60
+ it { expect(ranking1.key).to match /#{today.strftime("%Y%m%d")}/ }
61
+ it { expect(ranking1.key).to_not match /#{ranking2.key}/ }
62
+ end
63
+
64
+ describe "include class name" do
65
+ let(:ranking) { described_class.new class_name: MockModel }
66
+
67
+ it { expect(ranking.key).to match /#{MockModel.to_s}/ }
68
+ end
69
+
70
+ describe "include attribute name" do
71
+ let(:ranking) { described_class.new attribute_name: :score }
72
+
73
+ it { expect(ranking.key).to match /score/ }
74
+ end
75
+
76
+ describe "include data flag" do
77
+ context "without specific selector" do
78
+ let(:ranking) { described_class.new }
79
+
80
+ it { expect(ranking.key).to match /:data:/ }
81
+ end
82
+ end
83
+
84
+ describe "exclude bundler name" do
85
+ let(:ranking) { described_class.new bundler: MockBundler.new }
86
+
87
+ it { expect(ranking.key).not_to match /bundle/ }
88
+ end
89
+ end
90
+
91
+ describe "#options" do
92
+ let(:ranking) { described_class.new }
93
+ let(:options) { ranking.options }
94
+
95
+ %i[selector aggregator date per_page prefix suffix].each do |key|
96
+ it { expect(options).to have_key key }
97
+ end
98
+
99
+ %i[type].each do |key|
100
+ it { expect(options).not_to have_key key }
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Ranking::SubRanking do
4
+ let(:data_selector) { MockSelector.new }
5
+ let(:data_ranking) { Almicube::Ranking::DataRanking.new( selector: data_selector ) }
6
+
7
+ describe "#key" do
8
+ let(:ranking) { described_class.new(data_ranking, bundler: bundler) }
9
+ let(:bundler) { double( bundle: :bundled ) }
10
+
11
+ it { expect(ranking.key).not_to match /:data:/ }
12
+ it { expect(ranking.key).to match /:built:/ }
13
+ it { expect(ranking.key).to match /:bundled$/ }
14
+ end
15
+
16
+ describe "#selector" do
17
+ context "uses optional selector" do
18
+ let(:selector) { double( records: [] ) }
19
+ let(:ranking) { described_class.new(data_ranking, selector: selector) }
20
+ it { expect(ranking.selector).to eq selector }
21
+ end
22
+
23
+ context "uses selector on data ranking" do
24
+ let(:ranking) { described_class.new(data_ranking) }
25
+ it { expect(ranking.selector).to eq data_selector }
26
+ end
27
+ end
28
+
29
+ describe "#records" do
30
+ let(:selector) { double( records: ["a", "b"] ) }
31
+ let(:ranking) { described_class.new(data_ranking, selector: selector) }
32
+ it { expect(ranking.records).to eq selector.records }
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almicube::Selector::AllSelector do
4
+ let(:ranking) { double( class_name: MockModel ) }
5
+
6
+ describe "#data_probider?" do
7
+ it { expect(described_class.new).to be_data_provider }
8
+ end
9
+
10
+ describe "#records" do
11
+ let(:selector) { described_class.new }
12
+ before { selector.ranking = ranking }
13
+ it "should send :all an instance of MockModel" do
14
+ MockModel.should_receive(:all)
15
+ selector.records
16
+ end
17
+ end
18
+
19
+ it_behaves_like "ranking cog" do
20
+ let(:target) { described_class.new }
21
+ end
22
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+ require 'mocks/model'
3
+
4
+ describe Almicube::Selector::MethodSelector do
5
+ describe "#initialize" do
6
+ it { expect{ described_class.new }.to raise_error }
7
+ it { expect{ described_class.new class_name: "UnknownClassName" }.to raise_error }
8
+ it { expect{ described_class.new accessor: :invalid, class_name: MockModelForSelector }.to raise_error }
9
+ it { expect{ described_class.new accessor: :all, class_name: MockModelForSelector }.to_not raise_error }
10
+ end
11
+
12
+ describe "#records" do
13
+ context "setted accessor method is all" do
14
+ let(:selector) { described_class.new accessor: :all, class_name: MockModelForSelector }
15
+ let(:records) { [double(), double()] }
16
+ before { MockModelForSelector.should_receive(:all).and_return(records) }
17
+ it { expect(selector.records).to eq records }
18
+ end
19
+ end
20
+
21
+ describe "#count" do
22
+ context "setted counter method is count" do
23
+ let(:selector) { described_class.new counter: :count, class_name: MockModelForSelector }
24
+ let(:count) { 100 }
25
+ before { MockModelForSelector.should_receive(:count).and_return(count) }
26
+ it { expect(selector.count).to eq count }
27
+ end
28
+ end
29
+
30
+ describe "default accessor" do
31
+ let(:selector) { described_class.new class_name: MockModelForSelector }
32
+ it { expect(selector.accessor).to eq :all }
33
+ end
34
+
35
+ describe "default counter" do
36
+ let(:selector) { described_class.new class_name: MockModelForSelector }
37
+ it { expect(selector.counter).to eq :count }
38
+ end
39
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'mocks/model'
3
+
4
+ describe Almicube::Selector::Base do
5
+ describe "#records" do
6
+ let(:selector) { described_class.new }
7
+ it { expect{ selector.records }.to raise_error }
8
+ end
9
+
10
+ describe "#initialize" do
11
+ let(:selector) { described_class.new options }
12
+ describe "with class_name" do
13
+ let(:options) { { class_name: MockModelForSelector } }
14
+ it { expect(selector.class_name).to eq MockModelForSelector }
15
+ it { expect(selector.model_class).to eq MockModelForSelector }
16
+ end
17
+ end
18
+
19
+ describe "#label" do
20
+ let(:selector) { described_class.new options }
21
+ describe "with label" do
22
+ let(:options) { { label: :sample } }
23
+ it { expect(selector.label).to eq :sample }
24
+ end
25
+ end
26
+
27
+ describe "#data_provider?" do
28
+ let(:selector) { described_class.new options }
29
+ describe "is false" do
30
+ let(:options) { {} }
31
+ it { expect(selector).to_not be_data_provider }
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,2 @@
1
+ class MockAggregator < Almicube::Aggregator::Base
2
+ end
@@ -0,0 +1,5 @@
1
+ class MockBundler < Almicube::Bundler::Base
2
+ def initialize(options={})
3
+ @name = :bundle
4
+ end
5
+ end