daodalus 0.1.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 (49) hide show
  1. data/.gitignore +7 -0
  2. data/.travis.yml +7 -0
  3. data/Gemfile +10 -0
  4. data/Gemfile.lock +65 -0
  5. data/LICENCE.md +9 -0
  6. data/README.md +316 -0
  7. data/Rakefile +8 -0
  8. data/daodalus.gemspec +23 -0
  9. data/lib/daodalus.rb +29 -0
  10. data/lib/daodalus/connection.rb +19 -0
  11. data/lib/daodalus/dao.rb +41 -0
  12. data/lib/daodalus/dsl.rb +21 -0
  13. data/lib/daodalus/dsl/aggregation/group.rb +88 -0
  14. data/lib/daodalus/dsl/aggregation/limit.rb +23 -0
  15. data/lib/daodalus/dsl/aggregation/match.rb +35 -0
  16. data/lib/daodalus/dsl/aggregation/project.rb +79 -0
  17. data/lib/daodalus/dsl/aggregation/skip.rb +23 -0
  18. data/lib/daodalus/dsl/aggregation/sort.rb +29 -0
  19. data/lib/daodalus/dsl/aggregation/unwind.rb +23 -0
  20. data/lib/daodalus/dsl/aggregations.rb +44 -0
  21. data/lib/daodalus/dsl/clause.rb +19 -0
  22. data/lib/daodalus/dsl/matchers.rb +87 -0
  23. data/lib/daodalus/dsl/queries.rb +29 -0
  24. data/lib/daodalus/dsl/query.rb +46 -0
  25. data/lib/daodalus/dsl/select.rb +43 -0
  26. data/lib/daodalus/dsl/update.rb +86 -0
  27. data/lib/daodalus/dsl/updates.rb +71 -0
  28. data/lib/daodalus/dsl/where.rb +30 -0
  29. data/lib/daodalus/invalid_connection_error.rb +7 -0
  30. data/lib/daodalus/invalid_query_error.rb +4 -0
  31. data/spec/lib/daodalus/connection_spec.rb +22 -0
  32. data/spec/lib/daodalus/dao_spec.rb +34 -0
  33. data/spec/lib/daodalus/dsl/aggregation/group_spec.rb +92 -0
  34. data/spec/lib/daodalus/dsl/aggregation/limit_spec.rb +22 -0
  35. data/spec/lib/daodalus/dsl/aggregation/match_spec.rb +32 -0
  36. data/spec/lib/daodalus/dsl/aggregation/project_spec.rb +74 -0
  37. data/spec/lib/daodalus/dsl/aggregation/skip_spec.rb +22 -0
  38. data/spec/lib/daodalus/dsl/aggregation/sort_spec.rb +36 -0
  39. data/spec/lib/daodalus/dsl/aggregation/unwind_spec.rb +24 -0
  40. data/spec/lib/daodalus/dsl/clause_spec.rb +22 -0
  41. data/spec/lib/daodalus/dsl/query_spec.rb +35 -0
  42. data/spec/lib/daodalus/dsl/select_spec.rb +46 -0
  43. data/spec/lib/daodalus/dsl/update_spec.rb +113 -0
  44. data/spec/lib/daodalus/dsl/where_spec.rb +133 -0
  45. data/spec/lib/daodalus/dsl_spec.rb +12 -0
  46. data/spec/pointless_coverage_spec.rb +9 -0
  47. data/spec/spec_helper.rb +18 -0
  48. data/spec/support/mongo_cleaner.rb +12 -0
  49. metadata +208 -0
data/lib/daodalus.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'mongo'
2
+ require 'optional'
3
+
4
+ require 'daodalus/connection'
5
+ require 'daodalus/invalid_connection_error'
6
+ require 'daodalus/invalid_query_error'
7
+
8
+ require 'daodalus/dsl/query'
9
+ require 'daodalus/dsl/clause'
10
+ require 'daodalus/dsl/matchers'
11
+
12
+ require 'daodalus/dsl/queries'
13
+ require 'daodalus/dsl/updates'
14
+
15
+ require 'daodalus/dsl/where'
16
+ require 'daodalus/dsl/select'
17
+ require 'daodalus/dsl/update'
18
+
19
+ require 'daodalus/dsl/aggregations'
20
+ require 'daodalus/dsl/aggregation/match'
21
+ require 'daodalus/dsl/aggregation/group'
22
+ require 'daodalus/dsl/aggregation/project'
23
+ require 'daodalus/dsl/aggregation/limit'
24
+ require 'daodalus/dsl/aggregation/skip'
25
+ require 'daodalus/dsl/aggregation/sort'
26
+ require 'daodalus/dsl/aggregation/unwind'
27
+
28
+ require 'daodalus/dsl'
29
+ require 'daodalus/dao'
@@ -0,0 +1,19 @@
1
+ module Daodalus
2
+
3
+ module Connection
4
+ extend self
5
+
6
+ def register(connection, name='default')
7
+ connections[name.to_s] = connection
8
+ end
9
+
10
+ def fetch(name='default')
11
+ connections.fetch(name.to_s) { raise InvalidConnectionError.new(name) }
12
+ end
13
+
14
+ def connections
15
+ @connections ||= {}
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ require 'delegate'
2
+
3
+ module Daodalus
4
+ class DAO
5
+ include DSL
6
+ extend Forwardable
7
+
8
+ def initialize(db, collection, connection=:default)
9
+ @db = db
10
+ @collection = collection
11
+ @connection = connection
12
+ end
13
+
14
+ def coll
15
+ @coll ||= Daodalus::Connection.fetch(connection)[db.to_s][collection.to_s]
16
+ end
17
+
18
+ delegate [
19
+ :find,
20
+ :update,
21
+ :insert,
22
+ :save,
23
+ :remove,
24
+ :count,
25
+ :aggregate
26
+ ] => :coll
27
+
28
+ def find_one(*args)
29
+ Option[coll.find_one(*args)]
30
+ end
31
+
32
+ def find_and_modify(*args)
33
+ Option[coll.find_and_modify(*args)]
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :db, :collection, :connection
39
+
40
+ end
41
+ end
@@ -0,0 +1,21 @@
1
+ module Daodalus
2
+ module DSL
3
+ include Clause
4
+ include Queries
5
+ include Updates
6
+ include Aggregations
7
+
8
+ def query
9
+ Query.new
10
+ end
11
+
12
+ def pipeline
13
+ []
14
+ end
15
+
16
+ def dao
17
+ self
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,88 @@
1
+ module Daodalus
2
+ module DSL
3
+ module Aggregation
4
+ class Group
5
+ include Aggregations
6
+
7
+ def initialize(dao, aggregations, id, values)
8
+ @dao = dao
9
+ @aggregations = aggregations
10
+ @id = id
11
+ @values = values
12
+ end
13
+
14
+ def to_aggregation
15
+ { '$group' => values.merge('_id' => id) }
16
+ end
17
+
18
+ def sum(field)
19
+ aliased '$sum' => field
20
+ end
21
+ alias_method :total, :sum
22
+
23
+ def add_to_set(field)
24
+ aliased '$addToSet' => field
25
+ end
26
+ alias_method :distinct, :add_to_set
27
+
28
+ def push(field)
29
+ aliased '$push' => field
30
+ end
31
+ alias_method :collect, :push
32
+
33
+ def first(field)
34
+ aliased '$first' => field
35
+ end
36
+
37
+ def last(field)
38
+ aliased '$last' => field
39
+ end
40
+
41
+ def max(field)
42
+ aliased '$max' => field
43
+ end
44
+
45
+ def min(field)
46
+ aliased '$min' => field
47
+ end
48
+
49
+ def avg(field)
50
+ aliased '$avg' => field
51
+ end
52
+ alias_method :average, :avg
53
+
54
+ private
55
+
56
+ def id
57
+ case @id
58
+ when Symbol then @id.to_s
59
+ when Hash then @id.reduce({}) {|acc, (a,b)| acc.merge(a.to_s => b.to_s) }
60
+ else @id
61
+ end
62
+ end
63
+
64
+ def aliased clause
65
+ Alias.new do |aka|
66
+ Group.new(dao, aggregations, id, values.merge(aka => clause))
67
+ end
68
+ end
69
+
70
+ attr_reader :dao, :aggregations, :values
71
+
72
+ class Alias
73
+ def initialize(&block)
74
+ @block = block
75
+ end
76
+
77
+ def as(aka)
78
+ block.call(aka)
79
+ end
80
+
81
+ private
82
+
83
+ attr_reader :block
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,23 @@
1
+ module Daodalus
2
+ module DSL
3
+ module Aggregation
4
+ class Limit
5
+ include Aggregations
6
+
7
+ def initialize(dao, aggregations, limit)
8
+ @dao = dao
9
+ @aggregations = aggregations
10
+ @limit = limit
11
+ end
12
+
13
+ def to_aggregation
14
+ { '$limit' => limit }
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :dao, :aggregations, :limit
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ module Daodalus
2
+ module DSL
3
+ module Aggregation
4
+ class Match
5
+ include Matchers
6
+ include Aggregations
7
+
8
+ def initialize(dao, aggregations, query, field)
9
+ @dao = dao
10
+ @aggregations = aggregations
11
+ @query = query
12
+ @field = field
13
+ end
14
+
15
+ alias_method :and, :match
16
+
17
+ def to_aggregation
18
+ { '$match' => query.wheres }
19
+ end
20
+
21
+ private
22
+
23
+ def add_clause clause
24
+ Match.new(dao, aggregations, query.where(field.to_s => clause), field)
25
+ end
26
+
27
+ def add_logical_clause clause
28
+ Match.new(dao, aggregations, query.where(clause), field)
29
+ end
30
+
31
+ attr_reader :dao, :aggregations, :query, :field
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,79 @@
1
+ module Daodalus
2
+ module DSL
3
+ module Aggregation
4
+ class Project
5
+ include Aggregations
6
+
7
+ def initialize(dao, aggregations, projection = {}, keys)
8
+ @dao = dao
9
+ @aggregations = aggregations
10
+ @projection = projection
11
+ @keys = keys
12
+ end
13
+
14
+ def to_aggregation
15
+ { '$project' => { '_id' => 0 }.merge(projection) }
16
+ end
17
+
18
+ def project(*keys)
19
+ Project.new(dao, aggregations, projection, keys)
20
+ end
21
+ alias_method :and, :project
22
+
23
+ def as(aka)
24
+ Project.new(dao, aggregations, @projection, [aka => keys.first])
25
+ end
26
+
27
+ def eq(*others)
28
+ Project.new(dao, aggregations, @projection, ['$eq' => keys + others])
29
+ end
30
+
31
+ def add(*others)
32
+ Project.new(dao, aggregations, @projection, ['$add' => keys + others])
33
+ end
34
+ alias_method :plus, :add
35
+
36
+ def divide(other)
37
+ Project.new(dao, aggregations, @projection, ['$divide' => keys + [other]])
38
+ end
39
+ alias_method :divided_by, :divide
40
+
41
+ def multiply(other)
42
+ Project.new(dao, aggregations, @projection, ['$multiply' => keys + [other]])
43
+ end
44
+ alias_method :multiplied_by, :multiply
45
+
46
+ def subtract(other)
47
+ Project.new(dao, aggregations, @projection, ['$subtract' => keys + [other]])
48
+ end
49
+ alias_method :minus, :subtract
50
+
51
+ def mod(other)
52
+ Project.new(dao, aggregations, @projection, ['$mod' => keys + [other]])
53
+ end
54
+
55
+ protected
56
+
57
+ def projection
58
+ keys.reduce(@projection) do |acc, k|
59
+ case k
60
+ when Hash then acc.merge(hashify k)
61
+ else acc.merge(k.to_s => 1)
62
+ end
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def hashify(key)
69
+ case key
70
+ when Hash then key.reduce({}) { |acc, (k,v)| acc.merge(k => hashify(v)) }
71
+ when Project then hashify key.projection
72
+ else key
73
+ end
74
+ end
75
+ attr_reader :dao, :aggregations, :keys
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,23 @@
1
+ module Daodalus
2
+ module DSL
3
+ module Aggregation
4
+ class Skip
5
+ include Aggregations
6
+
7
+ def initialize(dao, aggregations, skip)
8
+ @dao = dao
9
+ @aggregations = aggregations
10
+ @skip = skip
11
+ end
12
+
13
+ def to_aggregation
14
+ { '$skip' => skip }
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :dao, :aggregations, :skip
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ module Daodalus
2
+ module DSL
3
+ module Aggregation
4
+ class Sort
5
+ include Aggregations
6
+
7
+ def initialize(dao, aggregations, keys)
8
+ @dao = dao
9
+ @aggregations = aggregations
10
+ @keys = keys
11
+ end
12
+
13
+ def to_aggregation
14
+ { '$sort' => keys }
15
+ end
16
+
17
+ private
18
+
19
+ def keys
20
+ @keys.reduce({}) do |acc, (k,v)|
21
+ acc.merge(k => ([-1, :desc, 'desc'].include?(v) ? -1 : 1))
22
+ end
23
+ end
24
+
25
+ attr_reader :dao, :aggregations
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ module Daodalus
2
+ module DSL
3
+ module Aggregation
4
+ class Unwind
5
+ include Aggregations
6
+
7
+ def initialize(dao, aggregations, field)
8
+ @dao = dao
9
+ @aggregations = aggregations
10
+ @field = field
11
+ end
12
+
13
+ def to_aggregation
14
+ { '$unwind' => "$#{field}" }
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :dao, :aggregations, :field
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,44 @@
1
+ module Daodalus
2
+ module DSL
3
+ module Aggregations
4
+
5
+ def aggregate
6
+ dao.aggregate(pipeline)
7
+ end
8
+
9
+ def match(field=nil)
10
+ Aggregation::Match.new(dao, pipeline, Query.new, field)
11
+ end
12
+
13
+ def group(keys)
14
+ Aggregation::Group.new(dao, pipeline, keys, {})
15
+ end
16
+ alias_method :group_by, :group
17
+
18
+ def project(*keys)
19
+ Aggregation::Project.new(dao, pipeline, keys)
20
+ end
21
+
22
+ def limit(limit)
23
+ Aggregation::Limit.new(dao, pipeline, limit)
24
+ end
25
+
26
+ def skip(skip)
27
+ Aggregation::Skip.new(dao, pipeline, skip)
28
+ end
29
+
30
+ def sort(sort)
31
+ Aggregation::Sort.new(dao, pipeline, sort)
32
+ end
33
+
34
+ def unwind(field)
35
+ Aggregation::Unwind.new(dao, pipeline, field)
36
+ end
37
+
38
+ def pipeline
39
+ aggregations + [to_aggregation]
40
+ end
41
+
42
+ end
43
+ end
44
+ end