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.
Files changed (53) hide show
  1. data/.gitignore +20 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +93 -0
  7. data/Rakefile +9 -0
  8. data/casino.gemspec +30 -0
  9. data/lib/casino.rb +13 -0
  10. data/lib/casino/collection.rb +195 -0
  11. data/lib/casino/dimension.rb +11 -0
  12. data/lib/casino/focus.rb +26 -0
  13. data/lib/casino/intersection.rb +30 -0
  14. data/lib/casino/intersection/match/all.rb +29 -0
  15. data/lib/casino/intersection/match/base.rb +49 -0
  16. data/lib/casino/intersection/match/equivalence.rb +25 -0
  17. data/lib/casino/intersection/match/expression.rb +15 -0
  18. data/lib/casino/intersection/match/greater.rb +43 -0
  19. data/lib/casino/intersection/match/include.rb +15 -0
  20. data/lib/casino/intersection/match/lesser.rb +31 -0
  21. data/lib/casino/intersection/match/recurse.rb +19 -0
  22. data/lib/casino/lobby.rb +21 -0
  23. data/lib/casino/projection.rb +76 -0
  24. data/lib/casino/query.rb +23 -0
  25. data/lib/casino/question.rb +9 -0
  26. data/lib/casino/store.rb +49 -0
  27. data/lib/casino/version.rb +3 -0
  28. data/spec/fabricators/model_fabricator.rb +12 -0
  29. data/spec/fabricators/note_fabricator.rb +3 -0
  30. data/spec/fixtures/collections/collection.rb +3 -0
  31. data/spec/fixtures/collections/emails_by_day.rb +28 -0
  32. data/spec/fixtures/models/model.rb +8 -0
  33. data/spec/fixtures/models/note.rb +7 -0
  34. data/spec/lib/casino/collection_spec.rb +146 -0
  35. data/spec/lib/casino/dimension_spec.rb +27 -0
  36. data/spec/lib/casino/focus_spec.rb +53 -0
  37. data/spec/lib/casino/intersection/match/all_spec.rb +24 -0
  38. data/spec/lib/casino/intersection/match/base_spec.rb +159 -0
  39. data/spec/lib/casino/intersection/match/equivalence_spec.rb +26 -0
  40. data/spec/lib/casino/intersection/match/expression_spec.rb +26 -0
  41. data/spec/lib/casino/intersection/match/greater_spec.rb +72 -0
  42. data/spec/lib/casino/intersection/match/include_spec.rb +27 -0
  43. data/spec/lib/casino/intersection/match/lesser_spec.rb +74 -0
  44. data/spec/lib/casino/intersection/match/recurse_spec.rb +24 -0
  45. data/spec/lib/casino/intersection_spec.rb +33 -0
  46. data/spec/lib/casino/lobby_spec.rb +20 -0
  47. data/spec/lib/casino/projection_spec.rb +81 -0
  48. data/spec/lib/casino/query_spec.rb +42 -0
  49. data/spec/lib/casino/question_spec.rb +10 -0
  50. data/spec/lib/casino/store_spec.rb +60 -0
  51. data/spec/spec_helper.rb +26 -0
  52. data/spec/support/mongoid.yml +6 -0
  53. 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