mongoid-casino 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +93 -0
- data/Rakefile +9 -0
- data/casino.gemspec +30 -0
- data/lib/casino.rb +13 -0
- data/lib/casino/collection.rb +195 -0
- data/lib/casino/dimension.rb +11 -0
- data/lib/casino/focus.rb +26 -0
- data/lib/casino/intersection.rb +30 -0
- data/lib/casino/intersection/match/all.rb +29 -0
- data/lib/casino/intersection/match/base.rb +49 -0
- data/lib/casino/intersection/match/equivalence.rb +25 -0
- data/lib/casino/intersection/match/expression.rb +15 -0
- data/lib/casino/intersection/match/greater.rb +43 -0
- data/lib/casino/intersection/match/include.rb +15 -0
- data/lib/casino/intersection/match/lesser.rb +31 -0
- data/lib/casino/intersection/match/recurse.rb +19 -0
- data/lib/casino/lobby.rb +21 -0
- data/lib/casino/projection.rb +76 -0
- data/lib/casino/query.rb +23 -0
- data/lib/casino/question.rb +9 -0
- data/lib/casino/store.rb +49 -0
- data/lib/casino/version.rb +3 -0
- data/spec/fabricators/model_fabricator.rb +12 -0
- data/spec/fabricators/note_fabricator.rb +3 -0
- data/spec/fixtures/collections/collection.rb +3 -0
- data/spec/fixtures/collections/emails_by_day.rb +28 -0
- data/spec/fixtures/models/model.rb +8 -0
- data/spec/fixtures/models/note.rb +7 -0
- data/spec/lib/casino/collection_spec.rb +146 -0
- data/spec/lib/casino/dimension_spec.rb +27 -0
- data/spec/lib/casino/focus_spec.rb +53 -0
- data/spec/lib/casino/intersection/match/all_spec.rb +24 -0
- data/spec/lib/casino/intersection/match/base_spec.rb +159 -0
- data/spec/lib/casino/intersection/match/equivalence_spec.rb +26 -0
- data/spec/lib/casino/intersection/match/expression_spec.rb +26 -0
- data/spec/lib/casino/intersection/match/greater_spec.rb +72 -0
- data/spec/lib/casino/intersection/match/include_spec.rb +27 -0
- data/spec/lib/casino/intersection/match/lesser_spec.rb +74 -0
- data/spec/lib/casino/intersection/match/recurse_spec.rb +24 -0
- data/spec/lib/casino/intersection_spec.rb +33 -0
- data/spec/lib/casino/lobby_spec.rb +20 -0
- data/spec/lib/casino/projection_spec.rb +81 -0
- data/spec/lib/casino/query_spec.rb +42 -0
- data/spec/lib/casino/question_spec.rb +10 -0
- data/spec/lib/casino/store_spec.rb +60 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/mongoid.yml +6 -0
- metadata +234 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
describe Casino::Intersection::Match::Equivalence do
|
2
|
+
|
3
|
+
let(:klass) { Casino::Intersection::Match::Equivalence }
|
4
|
+
let(:source) { "Facebook" }
|
5
|
+
let(:document) { Model.new(source: source) }
|
6
|
+
let(:criteria) { Model.where(source: source) }
|
7
|
+
let(:selector) { criteria.selector }
|
8
|
+
let(:key) { 'source' }
|
9
|
+
let(:field) { selector[key] }
|
10
|
+
let(:value) { document.send(key) }
|
11
|
+
let(:equivalence) { klass.new(key, field, document, source) }
|
12
|
+
|
13
|
+
describe '#evaluate' do
|
14
|
+
describe 'when values match' do
|
15
|
+
subject { equivalence.evaluate }
|
16
|
+
it { subject.must_equal true }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'when values do not match' do
|
20
|
+
let(:inequivalence) { klass.new(key, field, document, "Google") }
|
21
|
+
subject { inequivalence.evaluate }
|
22
|
+
it { subject.must_equal false }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
describe Casino::Intersection::Match::Expression do
|
2
|
+
|
3
|
+
let(:klass) { Casino::Intersection::Match::Expression }
|
4
|
+
let(:source) { "Facebook" }
|
5
|
+
let(:document) { Model.new(source: source) }
|
6
|
+
let(:criteria) { Model.where(source: /facebook/i) }
|
7
|
+
let(:selector) { criteria.selector }
|
8
|
+
let(:key) { 'source' }
|
9
|
+
let(:field) { selector[key] }
|
10
|
+
let(:value) { document.send(key) }
|
11
|
+
let(:equivalence) { klass.new(key, field, document, source) }
|
12
|
+
|
13
|
+
describe '#evaluate' do
|
14
|
+
describe 'when values match' do
|
15
|
+
subject { equivalence.evaluate }
|
16
|
+
it { subject.must_equal true }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'when values do not match' do
|
20
|
+
let(:inequivalence) { klass.new(key, field, document, "Google") }
|
21
|
+
subject { inequivalence.evaluate }
|
22
|
+
it { subject.must_equal false }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
describe Casino::Intersection::Match::Greater do
|
2
|
+
|
3
|
+
let(:system) { Casino::Intersection::Match::Greater }
|
4
|
+
|
5
|
+
describe 'greater than' do
|
6
|
+
|
7
|
+
describe '#eligible?' do
|
8
|
+
describe "when the key is $gt" do
|
9
|
+
let(:matcher) { system.new '$gt', '', '', '' }
|
10
|
+
subject { matcher.eligible? }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#evaluate' do
|
15
|
+
|
16
|
+
describe 'when the value is greater than the field' do
|
17
|
+
it "returns true" do
|
18
|
+
matcher = system.new '$gt', Date.today, '', Date.yesterday
|
19
|
+
matcher.evaluate.must_equal true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'when the value is less than the field' do
|
24
|
+
it "returns false" do
|
25
|
+
matcher = system.new '$gt', Date.yesterday, '', Date.today
|
26
|
+
matcher.evaluate.must_equal false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'greater than or equal to' do
|
35
|
+
|
36
|
+
describe '#eligible?' do
|
37
|
+
describe "when the key is $gt" do
|
38
|
+
it "returns true" do
|
39
|
+
matcher = system.new '$gte', '', '', ''
|
40
|
+
matcher.eligible?.must_equal true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#evaluate' do
|
46
|
+
|
47
|
+
describe 'when the value is greater than the field' do
|
48
|
+
it "returns true" do
|
49
|
+
matcher = system.new '$gte', Date.today, '', Date.yesterday
|
50
|
+
matcher.evaluate.must_equal true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'when the value is equal to the field' do
|
55
|
+
it "returns true" do
|
56
|
+
matcher = system.new '$gte', Date.yesterday, '', Date.yesterday
|
57
|
+
matcher.evaluate.must_equal true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'when the value is less than the field' do
|
62
|
+
it "returns false" do
|
63
|
+
matcher = system.new '$gte', Date.yesterday, '', Date.today
|
64
|
+
matcher.evaluate.must_equal false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
describe Casino::Intersection::Match::Include do
|
2
|
+
|
3
|
+
let(:system) { Casino::Intersection::Match::Include }
|
4
|
+
|
5
|
+
describe '#eligible?' do
|
6
|
+
describe 'when the key is $in' do
|
7
|
+
let(:matcher) { system.new('$in', '', '', '') }
|
8
|
+
subject { matcher.eligible? }
|
9
|
+
it { subject.must_equal true }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#evaluate' do
|
14
|
+
describe 'when the value is within the field' do
|
15
|
+
let(:matcher) { system.new('$in', 1, '', [1, 2, 3, 4]) }
|
16
|
+
subject { matcher.evaluate }
|
17
|
+
it { subject.must_equal true }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'when the value is not within the field' do
|
21
|
+
let(:matcher) { system.new('$in', 1, '', [2, 3, 4]) }
|
22
|
+
subject { matcher.evaluate }
|
23
|
+
it { subject.must_equal false }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
describe Casino::Intersection::Match::Lesser do
|
2
|
+
|
3
|
+
let(:system) { Casino::Intersection::Match::Lesser }
|
4
|
+
|
5
|
+
describe 'lesser than' do
|
6
|
+
|
7
|
+
describe '#eligible?' do
|
8
|
+
describe "when the key is $lt" do
|
9
|
+
it "returns true" do
|
10
|
+
matcher = system.new '$lt', '', '', ''
|
11
|
+
matcher.eligible?.must_equal true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#evaluate' do
|
17
|
+
|
18
|
+
describe 'when the value is less than the field' do
|
19
|
+
it "returns true" do
|
20
|
+
matcher = system.new '$lt', Date.yesterday, '', Date.today
|
21
|
+
matcher.evaluate.must_equal true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'when the value is greater than the field' do
|
26
|
+
it "returns false" do
|
27
|
+
matcher = system.new '$lt', Date.today, '', Date.yesterday
|
28
|
+
matcher.evaluate.must_equal false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'lesser than or equal to' do
|
37
|
+
|
38
|
+
describe '#eligible?' do
|
39
|
+
describe "when the key is $lte" do
|
40
|
+
it "returns true" do
|
41
|
+
matcher = system.new '$lte', '', '', ''
|
42
|
+
matcher.eligible?.must_equal true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#evaluate' do
|
48
|
+
|
49
|
+
describe 'when the value is less than the field' do
|
50
|
+
it "returns true" do
|
51
|
+
matcher = system.new '$lte', Date.yesterday, '', Date.today
|
52
|
+
matcher.evaluate.must_equal true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'when the value is equal to the field' do
|
57
|
+
it "returns true" do
|
58
|
+
matcher = system.new '$lte', Date.today, '', Date.today
|
59
|
+
matcher.evaluate.must_equal true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'when the value is greater than the field' do
|
64
|
+
it "returns false" do
|
65
|
+
matcher = system.new '$lte', Date.today, '', Date.yesterday
|
66
|
+
matcher.evaluate.must_equal false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
describe Casino::Intersection::Match::Recurse do
|
2
|
+
|
3
|
+
let(:system) { Casino::Intersection::Match::Recurse }
|
4
|
+
|
5
|
+
describe '#eligible?' do
|
6
|
+
let(:matcher) { system.new('', '', '', {}) }
|
7
|
+
subject { matcher.eligible? }
|
8
|
+
it { subject.must_equal true }
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#evaluate' do
|
12
|
+
|
13
|
+
let(:matcher) { system.new('', '', '', { '$gt' => 4 }) }
|
14
|
+
let(:base) { Casino::Intersection::Match::Base }
|
15
|
+
subject { matcher.evaluate }
|
16
|
+
it 'builds base matchers to evaluate' do
|
17
|
+
base.stub(:new, OpenStruct.new(evaluate: true)) do
|
18
|
+
subject.must_equal true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
describe Casino::Intersection do
|
2
|
+
|
3
|
+
let(:label) { [ Date.today.strftime("%m/%d/%Y"), "Facebook" ] }
|
4
|
+
let(:criteria) { Model.scoped }
|
5
|
+
let(:intersection) { Casino::Intersection.new(label, criteria) }
|
6
|
+
|
7
|
+
subject { intersection }
|
8
|
+
|
9
|
+
it { subject.label.must_equal label }
|
10
|
+
it { subject.criteria.must_equal criteria }
|
11
|
+
it { subject.must_respond_to :selector }
|
12
|
+
|
13
|
+
describe '#match?' do
|
14
|
+
|
15
|
+
let(:model) { Model.new }
|
16
|
+
let(:criteria) { Model.where(created_at: Date.today) }
|
17
|
+
let(:intersection) { Casino::Intersection.new(label, criteria) }
|
18
|
+
let(:value) { model.created_at }
|
19
|
+
let(:base_class) { Casino::Intersection::Match::Base }
|
20
|
+
let(:base_mock) { MiniTest::Mock.new }
|
21
|
+
let(:base_instance) { base_class.new(*base_arguments) }
|
22
|
+
let(:base_arguments) { [model, 'created_at', intersection.selector, value] }
|
23
|
+
|
24
|
+
it "invokes a Casino::Intersection::Match::Base instance" do
|
25
|
+
base_mock.expect(:evaluate, base_instance)
|
26
|
+
base_class.stub(:new, base_mock) do
|
27
|
+
intersection.match?(model)
|
28
|
+
end
|
29
|
+
base_mock.verify
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Casino::Lobby do
|
4
|
+
|
5
|
+
let(:collection) { Collection }
|
6
|
+
let(:object_class) { Model }
|
7
|
+
let(:object_instance) { object_class.new }
|
8
|
+
let(:object_key) { object_class.name.downcase.split("::").last.to_sym }
|
9
|
+
let(:lobby) { Casino::Lobby.new(collection) }
|
10
|
+
|
11
|
+
subject { lobby }
|
12
|
+
|
13
|
+
it { subject.collection.must_equal collection }
|
14
|
+
|
15
|
+
it "stores objects instances in a registry" do
|
16
|
+
subject.add_registry(object_instance)
|
17
|
+
subject.registry[object_key].must_include object_instance
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
describe Casino::Projection do
|
2
|
+
|
3
|
+
let(:projection) { Casino::Projection.new(Model) }
|
4
|
+
|
5
|
+
describe '#results' do
|
6
|
+
it "sends the pipeline to the collection's aggregate method" do
|
7
|
+
Model.collection.stub(:aggregate, []) do
|
8
|
+
projection.results.must_equal []
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#mongoize' do
|
14
|
+
let(:hash) do
|
15
|
+
{ group: { '_id' => :email, 'count' => { sum: 1 } } }
|
16
|
+
end
|
17
|
+
let(:mongoized_hash) do
|
18
|
+
{ '$group' => { '_id' => '$email', 'count' => { '$sum' => 1 } } }
|
19
|
+
end
|
20
|
+
subject { projection.mongoize(hash) }
|
21
|
+
it { subject.must_equal mongoized_hash }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#group' do
|
25
|
+
let(:group_hash) do
|
26
|
+
{ '$group' => { '_id' => '$author' } }
|
27
|
+
end
|
28
|
+
subject { projection.group('_id' => :author) }
|
29
|
+
it { subject.pipeline.must_include group_hash }
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#project' do
|
33
|
+
let(:project_hash) do
|
34
|
+
{ '$project' => { 'person' => '$human' } }
|
35
|
+
end
|
36
|
+
subject { projection.project('person' => :human) }
|
37
|
+
it { subject.pipeline.must_include project_hash }
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#unwind' do
|
41
|
+
let(:unwind_hash) do
|
42
|
+
{ '$unwind' => '$notes' }
|
43
|
+
end
|
44
|
+
subject { projection.unwind(:notes) }
|
45
|
+
it { subject.pipeline.must_include unwind_hash }
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#match' do
|
49
|
+
let(:today) { Date.today }
|
50
|
+
let(:match_hash) do
|
51
|
+
{ '$match' => { '$created_at' => { '$gte' => today } } }
|
52
|
+
end
|
53
|
+
subject { projection.match(created_at: { gte: today }) }
|
54
|
+
it { subject.pipeline.must_include match_hash }
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#sort' do
|
58
|
+
let(:sort_hash) do
|
59
|
+
{ '$sort' => { 'count' => -1 } }
|
60
|
+
end
|
61
|
+
subject { projection.sort('count' => -1) }
|
62
|
+
it { subject.pipeline.must_include sort_hash }
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#skip' do
|
66
|
+
let(:skip_hash) do
|
67
|
+
{ '$skip' => 10 }
|
68
|
+
end
|
69
|
+
subject { projection.skip(10) }
|
70
|
+
it { subject.pipeline.must_include skip_hash }
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '#limit' do
|
74
|
+
let(:limit_hash) do
|
75
|
+
{ '$limit' => 10 }
|
76
|
+
end
|
77
|
+
subject { projection.limit(10) }
|
78
|
+
it { subject.pipeline.must_include limit_hash }
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Casino::Query do
|
4
|
+
|
5
|
+
let(:label) { "women's boots" }
|
6
|
+
let(:criteria) { [ /page_gender=f/i, /offer_cohort=boots/i ] }
|
7
|
+
let(:query) { Casino::Query.new(label, [], *criteria) }
|
8
|
+
|
9
|
+
subject { query }
|
10
|
+
|
11
|
+
it { subject.label.must_equal label }
|
12
|
+
it { subject.criteria.must_equal criteria }
|
13
|
+
it { subject.conditions.must_equal [] }
|
14
|
+
|
15
|
+
describe '#merge' do
|
16
|
+
|
17
|
+
let(:field) { :created_at }
|
18
|
+
let(:queries) { :method_name }
|
19
|
+
let(:and_approach) { { operator: :and } }
|
20
|
+
|
21
|
+
let(:dimension) do
|
22
|
+
Casino::Dimension.new("Date", field, queries, and_approach)
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:conditions) do
|
26
|
+
query.criteria.map do |condition|
|
27
|
+
[ :and, { dimension.field => condition } ]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
subject { query.merge(dimension) }
|
32
|
+
|
33
|
+
it "merges the dimension data in" do
|
34
|
+
subject.conditions.must_equal conditions
|
35
|
+
end
|
36
|
+
|
37
|
+
it "produces a different object" do
|
38
|
+
subject.wont_equal query
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Casino::Question do
|
4
|
+
let(:name) { :emails }
|
5
|
+
let(:answer) { :distinct_emails }
|
6
|
+
let(:question) { Casino::Question.new(name, answer) }
|
7
|
+
subject { question }
|
8
|
+
it { subject.name.must_equal name }
|
9
|
+
it { subject.answer.must_equal answer }
|
10
|
+
end
|