mongoid-casino 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,29 @@
1
+ module Casino
2
+ class Intersection
3
+ module Match
4
+ class All < Equivalence
5
+
6
+ def eligible?
7
+ key == '$and'
8
+ end
9
+
10
+ def evaluate
11
+ matchers.map(&:evaluate).all?
12
+ end
13
+
14
+ private
15
+
16
+ def matchers
17
+ field.reduce(Array.new) do |list, element|
18
+ list + build_bases_with_element_keys(element)
19
+ end
20
+ end
21
+
22
+ def build_bases_with_element_keys(element)
23
+ element.keys.map { |key| Base.new(document, key, element, value) }
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ module Casino
2
+ class Intersection
3
+ module Match
4
+ class Base
5
+ attr_accessor :document, :field, :key, :selector, :value
6
+
7
+ def initialize(document, key, selector, value = nil)
8
+ self.document = document
9
+ self.field = selector[key]
10
+ self.key = key
11
+ self.selector = selector
12
+ self.value = document_value || value
13
+ end
14
+
15
+ def evaluate
16
+ matcher.evaluate
17
+ end
18
+
19
+ def match_arguments
20
+ [ key, value, document, field ]
21
+ end
22
+
23
+ def matchers
24
+ matcher_classes.map { |class_name| matcher_for class_name }
25
+ end
26
+
27
+ def matcher
28
+ matchers.find { |matcher| matcher.eligible? }
29
+ end
30
+
31
+ def matcher_for(class_name)
32
+ class_name = String(class_name).humanize
33
+ Match.const_get(class_name).new(*match_arguments)
34
+ end
35
+
36
+ private
37
+
38
+ def matcher_classes
39
+ %w(all include recurse greater lesser expression equivalence)
40
+ end
41
+
42
+ def document_value
43
+ document.send(key) if document.respond_to?(key)
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,25 @@
1
+ module Casino
2
+ class Intersection
3
+ module Match
4
+ class Equivalence
5
+ attr_accessor :document, :field, :key, :value
6
+
7
+ def initialize(key, value, document, field)
8
+ self.key = key
9
+ self.document = document
10
+ self.field = field
11
+ self.value = value
12
+ end
13
+
14
+ def eligible?
15
+ true
16
+ end
17
+
18
+ def evaluate
19
+ value == field
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ module Casino
2
+ class Intersection
3
+ module Match
4
+ class Expression < Equivalence
5
+ def eligible?
6
+ field.is_a? Regexp
7
+ end
8
+
9
+ def evaluate
10
+ !(value =~ field).nil?
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ module Casino
2
+ class Intersection
3
+ module Match
4
+ class Greater < Equivalence
5
+
6
+ def eligible?
7
+ %w($gt $gte).include? key
8
+ end
9
+
10
+ def evaluate
11
+ greater_than? ? greater_than! : greater_than_or_equal!
12
+ end
13
+
14
+ private
15
+
16
+ def greater_than?
17
+ key == '$gt'
18
+ end
19
+
20
+ def greater_than!
21
+ evolved_value > evolved_field
22
+ end
23
+
24
+ def greater_than_or_equal!
25
+ evolved_value >= evolved_field
26
+ end
27
+
28
+ def evolved_value
29
+ evolve value
30
+ end
31
+
32
+ def evolved_field
33
+ evolve field
34
+ end
35
+
36
+ def evolve(instance)
37
+ instance.class.evolve(instance)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ module Casino
2
+ class Intersection
3
+ module Match
4
+ class Include < Equivalence
5
+ def eligible?
6
+ key == "$in"
7
+ end
8
+
9
+ def evaluate
10
+ field.include?(value)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ module Casino
2
+ class Intersection
3
+ module Match
4
+ class Lesser < Greater
5
+
6
+ def eligible?
7
+ %w($lt $lte).include? key
8
+ end
9
+
10
+ def evaluate
11
+ lesser_than? ? lesser_than! : lesser_than_or_equal!
12
+ end
13
+
14
+ private
15
+
16
+ def lesser_than?
17
+ key == '$lt'
18
+ end
19
+
20
+ def lesser_than!
21
+ evolved_value < evolved_field
22
+ end
23
+
24
+ def lesser_than_or_equal!
25
+ evolved_value <= evolved_field
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module Casino
2
+ class Intersection
3
+ module Match
4
+ class Recurse < Equivalence
5
+
6
+ def eligible?
7
+ field.is_a? Hash
8
+ end
9
+
10
+ def evaluate
11
+ keys = field.keys
12
+ bases = keys.map { |key| Base.new(document, key, field, value) }
13
+ bases.map(&:evaluate).all?
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Casino
2
+ class Lobby
3
+ attr_accessor :collection
4
+
5
+ def initialize(klass)
6
+ self.collection = klass
7
+ end
8
+
9
+ def registry
10
+ @registry ||= Hash.new
11
+ end
12
+
13
+ def add_registry(object)
14
+ key = object.class.name.downcase.split("::").last.to_sym
15
+ registry[key] ||= Array.new
16
+ registry[key] << object
17
+ registry[key] = registry[key].uniq
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,76 @@
1
+ module Casino
2
+ class Projection
3
+ attr_accessor :target, :pipeline
4
+
5
+ def initialize(klass, pipeline = [])
6
+ self.target = klass
7
+ self.pipeline = pipeline
8
+ end
9
+
10
+ def results
11
+ target.collection.aggregate(pipeline)
12
+ end
13
+
14
+ def mongoize(hash)
15
+ hash.keys.map { |key| build_mongoized_hash(hash, key) }.reduce(&:merge)
16
+ end
17
+
18
+ def group(conditions)
19
+ clone_with group: conditions
20
+ end
21
+ alias :pivot :group
22
+
23
+ def project(conditions)
24
+ clone_with project: conditions
25
+ end
26
+ alias :describe :project
27
+ alias :build :project
28
+
29
+ def unwind(conditions)
30
+ clone_with unwind: conditions
31
+ end
32
+ alias :expand :unwind
33
+
34
+ def match(conditions)
35
+ clone_with match: conditions
36
+ end
37
+ alias :where :match
38
+ alias :find :match
39
+
40
+ def sort(conditions)
41
+ clone_with sort: conditions
42
+ end
43
+ alias :order :sort
44
+
45
+ def skip(conditions)
46
+ clone_with skip: conditions
47
+ end
48
+ alias :offset :skip
49
+
50
+ def limit(conditions)
51
+ clone_with limit: conditions
52
+ end
53
+
54
+ private
55
+
56
+ def clone_with(condition)
57
+ self.class.new target, pipeline + [mongoize(condition)]
58
+ end
59
+
60
+ def build_mongoized_hash(hash, key)
61
+ new_key = mongo_ready(key)
62
+ value = hash[key]
63
+ value = value.is_a?(Hash) ? mongoize(value) : mongo_ready(value)
64
+ { new_key => evolve(value) }
65
+ end
66
+
67
+ def evolve(value)
68
+ value.class.respond_to?(:evolve) ? value.class.evolve(value) : value
69
+ end
70
+
71
+ def mongo_ready(object)
72
+ object.is_a?(Symbol) ? "$#{object}" : object
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,23 @@
1
+ module Casino
2
+ class Query
3
+ attr_accessor :label, :criteria, :conditions
4
+
5
+ def initialize(label, conditions, *criteria)
6
+ self.label = label
7
+ self.conditions = conditions
8
+ self.criteria = criteria
9
+ end
10
+
11
+ def merge(dimension)
12
+ self.class.new(label, build_conditions(dimension), *criteria)
13
+ end
14
+
15
+ def build_conditions(dimension)
16
+ criteria.map do |condition|
17
+ [ dimension.approach[:operator],
18
+ { dimension.field => condition } ]
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ module Casino
2
+ class Question
3
+ attr_accessor :name, :answer
4
+ def initialize(name, answer)
5
+ self.name = name
6
+ self.answer = answer
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,49 @@
1
+ module Casino
2
+ class Store
3
+ attr_accessor :collection_name
4
+
5
+ delegate :drop, :find, :indexes, :insert, to: :collection
6
+
7
+ delegate :count, :distinct, :each, :first, :limit, :remove, :remove_all,
8
+ :select, :skip, :sort, :update, :update_all, :upsert, to: :query
9
+
10
+ delegate :where, :in, to: :criteria
11
+
12
+ def initialize(collection_name)
13
+ self.collection_name = collection_name
14
+ end
15
+
16
+ def collection
17
+ @collection ||= session[collection_name.to_sym]
18
+ end
19
+
20
+ def query
21
+ @query ||= collection.find
22
+ end
23
+
24
+ def merge(*documents)
25
+ documents.each do |document|
26
+ criteria = find _id: document['_id']
27
+ criteria.upsert document
28
+ end
29
+ end
30
+
31
+ def criteria
32
+ @criteria ||= build_criteria
33
+ end
34
+
35
+ private
36
+
37
+ def session
38
+ @session ||= Mongoid.default_session
39
+ end
40
+
41
+ def build_criteria
42
+ klass = Class.new
43
+ klass.send(:include, Mongoid::Document)
44
+ klass.store_in collection: collection_name
45
+ klass.scoped
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module Casino
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ random_number = -> { rand(3) + 1 }
2
+
3
+ Fabricator(:model) do
4
+ created_at { Date.today }
5
+ source { %w(Google Facebook Twitter).shuffle.first }
6
+ end
7
+
8
+ Fabricator(:model_with_notes, from: :model) do
9
+ after_create do |model|
10
+ random_number.call.times { model.notes << Fabricate(:note, model: model) }
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ Fabricator(:note) do
2
+ views { rand(3) + 1 }
3
+ end