mongoid-casino 0.0.1
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.
- 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
|