mongo_aggregation_dsl 0.0.0.pre4

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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +61 -0
  3. data/.gitignore +54 -0
  4. data/.reek.yml +5 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +51 -0
  7. data/.ruby-version +1 -0
  8. data/Gemfile +10 -0
  9. data/Gemfile.lock +205 -0
  10. data/README.md +56 -0
  11. data/Rakefile +8 -0
  12. data/codecov.yml +3 -0
  13. data/config/pronto-circleci.yml +7 -0
  14. data/lib/aggregate/contracts/class_includes.rb +26 -0
  15. data/lib/aggregate/contracts/hash_max_length.rb +24 -0
  16. data/lib/aggregate/contracts/hash_min_length.rb +24 -0
  17. data/lib/aggregate/contracts/hash_value_type.rb +31 -0
  18. data/lib/aggregate/contracts/starts_with.rb +24 -0
  19. data/lib/aggregate/contracts.rb +8 -0
  20. data/lib/aggregate/pipeline.rb +41 -0
  21. data/lib/aggregate/stages/base.rb +20 -0
  22. data/lib/aggregate/stages/facet.rb +24 -0
  23. data/lib/aggregate/stages/group.rb +25 -0
  24. data/lib/aggregate/stages/hash_base.rb +13 -0
  25. data/lib/aggregate/stages/lookup.rb +26 -0
  26. data/lib/aggregate/stages/match.rb +25 -0
  27. data/lib/aggregate/stages/project.rb +17 -0
  28. data/lib/aggregate/stages/replace_root.rb +22 -0
  29. data/lib/aggregate/stages/unwind.rb +29 -0
  30. data/lib/aggregate/stages.rb +10 -0
  31. data/lib/aggregate/values/array.rb +20 -0
  32. data/lib/aggregate/values/base.rb +46 -0
  33. data/lib/aggregate/values/document_class.rb +27 -0
  34. data/lib/aggregate/values/hash.rb +43 -0
  35. data/lib/aggregate/values/nil.rb +25 -0
  36. data/lib/aggregate/values/object_id.rb +24 -0
  37. data/lib/aggregate/values/string.rb +22 -0
  38. data/lib/aggregate/values/symbol.rb +52 -0
  39. data/lib/aggregate/values.rb +8 -0
  40. data/lib/aggregate.rb +19 -0
  41. data/lib/mongo_aggregation_dsl.rb +3 -0
  42. data/mongo_aggregation_dsl.gemspec +42 -0
  43. metadata +385 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 939d254e03bcd1b34e04c7de797781863e8a9a53
4
+ data.tar.gz: d91bb52fd5bc15ef8a198715484f29ea1d3e887f
5
+ SHA512:
6
+ metadata.gz: ced780b0b600bcf8b069445de552314d49fbcf4b22db1502f25b30ffe29a4d196ffba9b3da6f7aa9ad19685c49969dfd5c494957874cca3199749082cba8efb3
7
+ data.tar.gz: 58c41fc7f244b76fc54d6ee77cdb0e445ad24d17fcd82f4ce54ef6a6d7e9a31235207b928b2d60e67e80d5251f9556b9747061347694c90ae78a0974cf1cd8c7
@@ -0,0 +1,61 @@
1
+ # Ruby CircleCI 2.0 configuration file
2
+ #
3
+ # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
+ #
5
+ version: 2
6
+ jobs:
7
+ build:
8
+ docker:
9
+ # specify the version you desire here
10
+ - image: circleci/ruby:2.3.4-node-browsers
11
+ environment:
12
+
13
+ working_directory: ~/repo
14
+
15
+ steps:
16
+ - checkout
17
+
18
+ # Download and cache dependencies
19
+ - restore_cache:
20
+ keys:
21
+ - v1-dependencies-{{ checksum "Gemfile.lock" }}
22
+ # fallback to using the latest cache if no exact match is found
23
+ - v1-dependencies-
24
+
25
+ - run:
26
+ name: Install system dependencies
27
+ command: |
28
+ sudo apt-get update
29
+ sudo apt-get install cmake
30
+
31
+ - run:
32
+ name: install dependencies
33
+ command: |
34
+ bundle install --jobs=4 --retry=3 --path vendor/bundle
35
+
36
+ - save_cache:
37
+ paths:
38
+ - ./venv
39
+ key: v1-dependencies-{{ checksum "Gemfile.lock" }}
40
+
41
+ - run:
42
+ name: pronto
43
+ command: echo ${PRONTO_GITHUB_ACCESS_TOKEN} && bundle exec pronto-circleci
44
+
45
+ # run tests!
46
+ - run:
47
+ name: run tests
48
+ command: |
49
+ mkdir /tmp/test-results
50
+
51
+ bundle exec rspec --format progress \
52
+ --format RspecJunitFormatter \
53
+ --out /tmp/test-results/rspec.xml \
54
+ --format progress
55
+
56
+ # collect reports
57
+ - store_test_results:
58
+ path: /tmp/test-results
59
+ - store_artifacts:
60
+ path: /tmp/test-results
61
+ destination: test-results
data/.gitignore ADDED
@@ -0,0 +1,54 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+
52
+ .idea/
53
+ .rspec_status
54
+ cornucopia_report/
data/.reek.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ detectors:
3
+ # TooManyStatements is covered by RuboCop.
4
+ TooManyStatements:
5
+ enabled: false
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,51 @@
1
+ # https://github.com/bbatsov/rubocop/blob/master/config/default.yml
2
+
3
+ Documentation:
4
+ Enabled: false
5
+
6
+ AllCops:
7
+ TargetRubyVersion: 2.3
8
+ Exclude:
9
+ - "bin/**/*"
10
+
11
+ LineLength:
12
+ Max: 150
13
+
14
+ ## Multi-line method chaining should be done with leading dots.
15
+ Layout/DotPosition:
16
+ EnforcedStyle: trailing
17
+
18
+ Layout/MultilineMethodCallIndentation:
19
+ Enabled: false
20
+
21
+ Layout/MultilineOperationIndentation:
22
+ Enabled: false
23
+
24
+ Metrics/MethodLength:
25
+ Max: 15
26
+
27
+ StringLiterals:
28
+ EnforcedStyle: double_quotes
29
+
30
+ IndentHash:
31
+ EnforcedStyle: consistent
32
+
33
+ # Indentation of `when`.
34
+ Layout/CaseIndentation:
35
+ EnforcedStyle: case
36
+ SupportedStyles:
37
+ - case
38
+ - end
39
+ IndentOneStep: true
40
+ # By default, the indentation width from Style/IndentationWidth is used
41
+ # But it can be overridden by setting this parameter
42
+ # This only matters if IndentOneStep is true
43
+ IndentationWidth: ~
44
+
45
+ Metrics/ClassLength:
46
+ Max: 150
47
+
48
+ Metrics/BlockLength:
49
+ Exclude:
50
+ - "spec/**/*"
51
+ - "*.gemspec"
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.1
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in acts-as-taggable-on-mongoid.gemspec
8
+ gemspec
9
+
10
+ gem "gem-release"
data/Gemfile.lock ADDED
@@ -0,0 +1,205 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mongo_aggregation_dsl (0.0.0.pre4)
5
+ autoloaded (~> 2)
6
+ contracts-lite
7
+ mongo (~> 2.6.2)
8
+ mongoid (~> 5.2.0)
9
+ origin (~> 2.3.1)
10
+
11
+ GEM
12
+ remote: https://rubygems.org/
13
+ specs:
14
+ activemodel (4.2.10)
15
+ activesupport (= 4.2.10)
16
+ builder (~> 3.1)
17
+ activesupport (4.2.10)
18
+ i18n (~> 0.7)
19
+ minitest (~> 5.1)
20
+ thread_safe (~> 0.3, >= 0.3.4)
21
+ tzinfo (~> 1.1)
22
+ addressable (2.5.2)
23
+ public_suffix (>= 2.0.2, < 4.0)
24
+ ast (2.4.0)
25
+ autoloaded (2.2.1)
26
+ axiom-types (0.1.1)
27
+ descendants_tracker (~> 0.0.4)
28
+ ice_nine (~> 0.11.0)
29
+ thread_safe (~> 0.3, >= 0.3.1)
30
+ brakeman (4.3.1)
31
+ bson (4.3.0)
32
+ builder (3.2.3)
33
+ code_analyzer (0.4.8)
34
+ sexp_processor
35
+ codeclimate-engine-rb (0.4.1)
36
+ virtus (~> 1.0)
37
+ codecov (0.1.10)
38
+ json
39
+ simplecov
40
+ url
41
+ coercible (1.0.0)
42
+ descendants_tracker (~> 0.0.1)
43
+ colorize (0.8.1)
44
+ concurrent-ruby (1.0.5)
45
+ contracts-lite (0.15.0)
46
+ database_cleaner (1.7.0)
47
+ descendants_tracker (0.0.4)
48
+ thread_safe (~> 0.3, >= 0.3.1)
49
+ diff-lcs (1.3)
50
+ docile (1.3.1)
51
+ equalizer (0.0.11)
52
+ erubis (2.7.0)
53
+ faraday (0.15.2)
54
+ multipart-post (>= 1.2, < 3)
55
+ fasterer (0.4.1)
56
+ colorize (~> 0.7)
57
+ ruby_parser (~> 3.11.0)
58
+ gem-release (2.0.1)
59
+ gitlab (4.5.0)
60
+ httparty (>= 0.14.0)
61
+ terminal-table (>= 1.5.1)
62
+ httparty (0.16.2)
63
+ multi_xml (>= 0.5.2)
64
+ i18n (0.9.5)
65
+ concurrent-ruby (~> 1.0)
66
+ ice_nine (0.11.2)
67
+ jaro_winkler (1.5.1)
68
+ json (2.1.0)
69
+ kwalify (0.7.2)
70
+ minitest (5.11.3)
71
+ mongo (2.6.2)
72
+ bson (>= 4.3.0, < 5.0.0)
73
+ mongoid (5.2.1)
74
+ activemodel (~> 4.0)
75
+ mongo (>= 2.4.1, < 3.0.0)
76
+ origin (~> 2.3)
77
+ tzinfo (>= 0.3.37)
78
+ multi_xml (0.6.0)
79
+ multipart-post (2.0.0)
80
+ octokit (4.11.0)
81
+ sawyer (~> 0.8.0, >= 0.5.3)
82
+ origin (2.3.1)
83
+ parallel (1.12.1)
84
+ parser (2.5.1.2)
85
+ ast (~> 2.4.0)
86
+ powerpack (0.1.2)
87
+ pronto (0.9.5)
88
+ gitlab (~> 4.0, >= 4.0.0)
89
+ httparty (>= 0.13.7)
90
+ octokit (~> 4.7, >= 4.7.0)
91
+ rainbow (~> 2.1)
92
+ rugged (~> 0.24, >= 0.23.0)
93
+ thor (~> 0.19.0)
94
+ pronto-brakeman (0.9.1)
95
+ brakeman (>= 3.2.0)
96
+ pronto (~> 0.9.0)
97
+ pronto-circleci (1.0.1)
98
+ pronto (~> 0.9)
99
+ pronto-fasterer (0.9.0)
100
+ fasterer (~> 0.3, >= 0.3.0)
101
+ pronto (~> 0.9.0)
102
+ pronto-rails_best_practices (0.9.0)
103
+ pronto (~> 0.9.0)
104
+ rails_best_practices (~> 1.16, >= 1.15.0)
105
+ pronto-reek (0.9.1)
106
+ pronto (~> 0.9.0)
107
+ reek (>= 4.2, < 6.0)
108
+ pronto-rubocop (0.9.1)
109
+ pronto (~> 0.9.0)
110
+ rubocop (~> 0.50, >= 0.49.1)
111
+ public_suffix (3.0.3)
112
+ rails_best_practices (1.19.3)
113
+ activesupport
114
+ code_analyzer (>= 0.4.8)
115
+ erubis
116
+ i18n
117
+ json
118
+ require_all (~> 2.0)
119
+ ruby-progressbar
120
+ rainbow (2.2.2)
121
+ rake
122
+ rake (10.5.0)
123
+ reek (5.0.2)
124
+ codeclimate-engine-rb (~> 0.4.0)
125
+ kwalify (~> 0.7.0)
126
+ parser (>= 2.5.0.0, < 2.6, != 2.5.1.1)
127
+ rainbow (>= 2.0, < 4.0)
128
+ require_all (2.0.0)
129
+ rspec (3.8.0)
130
+ rspec-core (~> 3.8.0)
131
+ rspec-expectations (~> 3.8.0)
132
+ rspec-mocks (~> 3.8.0)
133
+ rspec-core (3.8.0)
134
+ rspec-support (~> 3.8.0)
135
+ rspec-expectations (3.8.1)
136
+ diff-lcs (>= 1.2.0, < 2.0)
137
+ rspec-support (~> 3.8.0)
138
+ rspec-mocks (3.8.0)
139
+ diff-lcs (>= 1.2.0, < 2.0)
140
+ rspec-support (~> 3.8.0)
141
+ rspec-support (3.8.0)
142
+ rspec_junit_formatter (0.3.0)
143
+ rspec-core (>= 2, < 4, != 2.12.0)
144
+ rubocop (0.59.0)
145
+ jaro_winkler (~> 1.5.1)
146
+ parallel (~> 1.10)
147
+ parser (>= 2.5, != 2.5.1.1)
148
+ powerpack (~> 0.1)
149
+ rainbow (>= 2.2.2, < 4.0)
150
+ ruby-progressbar (~> 1.7)
151
+ unicode-display_width (~> 1.0, >= 1.0.1)
152
+ ruby-progressbar (1.10.0)
153
+ ruby_parser (3.11.0)
154
+ sexp_processor (~> 4.9)
155
+ rugged (0.27.4)
156
+ sawyer (0.8.1)
157
+ addressable (>= 2.3.5, < 2.6)
158
+ faraday (~> 0.8, < 1.0)
159
+ sexp_processor (4.11.0)
160
+ simplecov (0.16.1)
161
+ docile (~> 1.1)
162
+ json (>= 1.8, < 3)
163
+ simplecov-html (~> 0.10.0)
164
+ simplecov-html (0.10.2)
165
+ simplecov-rcov (0.2.3)
166
+ simplecov (>= 0.4.1)
167
+ terminal-table (1.8.0)
168
+ unicode-display_width (~> 1.1, >= 1.1.1)
169
+ thor (0.19.4)
170
+ thread_safe (0.3.6)
171
+ tzinfo (1.2.5)
172
+ thread_safe (~> 0.1)
173
+ unicode-display_width (1.4.0)
174
+ url (0.3.2)
175
+ virtus (1.0.5)
176
+ axiom-types (~> 0.1)
177
+ coercible (~> 1.0)
178
+ descendants_tracker (~> 0.0, >= 0.0.3)
179
+ equalizer (~> 0.0, >= 0.0.9)
180
+
181
+ PLATFORMS
182
+ ruby
183
+
184
+ DEPENDENCIES
185
+ bundler (~> 1.16)
186
+ codecov (~> 0.1.0, ~> 0.1)
187
+ database_cleaner
188
+ gem-release
189
+ mongo_aggregation_dsl!
190
+ pronto
191
+ pronto-brakeman
192
+ pronto-circleci
193
+ pronto-fasterer
194
+ pronto-rails_best_practices
195
+ pronto-reek
196
+ pronto-rubocop
197
+ rake (~> 10.0)
198
+ rspec (~> 3.0)
199
+ rspec_junit_formatter (~> 0.3.0)
200
+ rubocop
201
+ simplecov
202
+ simplecov-rcov
203
+
204
+ BUNDLED WITH
205
+ 1.16.4
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # mongo_aggregation_dsl
2
+
3
+ This gem provides a basic implementation of a mongo aggregation dsl. It is by no means complete.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mongo_aggregation_dsl'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install mongo_aggregation_dsl
20
+
21
+ ## Usage
22
+
23
+ Example returns an array containing the resulting document json
24
+ ```ruby
25
+ Aggregate::Pipeline.new(User).
26
+ match(account_id: BSON::ObjectId("111111111111111")).
27
+ project(id: 1).
28
+ lookup(
29
+ from: EndUser,
30
+ let: { user_id: :"$_id" },
31
+ as: "my_record",
32
+ pipeline: Aggregate::Pipeline.new.
33
+ match(
34
+ :expr.and => [
35
+ { eq: %w[$user_id $$user_id] },
36
+ { eq: ["$status_code", 1] }
37
+ ]
38
+ ).
39
+ project(id: 1)
40
+ ).execute
41
+ ```
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests.
46
+
47
+ To release a new version, update the version number in `mongo_aggregation_dsl.gemspec`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
48
+
49
+ ## Contributing
50
+
51
+ Bug reports and pull requests are welcome on GitHub at https://github.com/CardTapp/mongo_aggregation_dsl. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
52
+
53
+ ## License
54
+
55
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
56
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/codecov.yml ADDED
@@ -0,0 +1,3 @@
1
+ codecov:
2
+ ci:
3
+ - CircleCI
@@ -0,0 +1,7 @@
1
+ github:
2
+ org: "CardTapp"
3
+ repo: "mongo_aggregation_dsl"
4
+ pronto:
5
+ comments_on_diff: true
6
+ reviews_on_diff: true
7
+ report_status: true
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aggregate
4
+ module Contracts
5
+ # Validates that a class includes a given module
6
+ class ClassIncludes < ::Contracts::Builtin::CallableClass
7
+ def initialize(klasses)
8
+ @klasses = [klasses].flatten(1)
9
+ end
10
+
11
+ # :reek:FeatureEnvy
12
+ # :reek:ManualDispatch
13
+ def valid?(object)
14
+ @klasses.all? { |klass| object.respond_to?(:included_modules) && object.included_modules.include?(klass) }
15
+ end
16
+
17
+ def to_s
18
+ "Expected to include #{@klasses}"
19
+ end
20
+
21
+ def inspect
22
+ to_s
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aggregate
4
+ module Contracts
5
+ # Validates a hash length does not exceed the max given value
6
+ class HashMaxLength < ::Contracts::Builtin::CallableClass
7
+ def initialize(*vals)
8
+ @length = vals[0]
9
+ end
10
+
11
+ def valid?(hash)
12
+ hash.length <= @length
13
+ end
14
+
15
+ def to_s
16
+ "Hash length to be less than than or equal to #{@length}"
17
+ end
18
+
19
+ def inspect
20
+ to_s
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aggregate
4
+ module Contracts
5
+ # Validates a hash length is less than the min given value
6
+ class HashMinLength < ::Contracts::Builtin::CallableClass
7
+ def initialize(*vals)
8
+ @length = vals[0]
9
+ end
10
+
11
+ def valid?(hash)
12
+ hash.length >= @length
13
+ end
14
+
15
+ def to_s
16
+ "Hash length to be greater than or equal to #{@length}"
17
+ end
18
+
19
+ def inspect
20
+ to_s
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aggregate
4
+ module Contracts
5
+ # Validates the value types in a given range are of a given type
6
+ class HashValueType < ::Contracts::Builtin::CallableClass
7
+ def initialize(*vals)
8
+ @range = vals[0]
9
+ @type = vals[1]
10
+ @error = nil
11
+ end
12
+
13
+ def valid?(hash)
14
+ values = hash.values[@range]
15
+ if values.is_a? Array
16
+ values.all? { |value| value.is_a? @type }
17
+ else
18
+ values.is_a?(@type)
19
+ end
20
+ end
21
+
22
+ def to_s
23
+ "Hash values #{@range} to be of type #{@type}"
24
+ end
25
+
26
+ def inspect
27
+ to_s
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aggregate
4
+ module Contracts
5
+ # Validates an object in string format begins with the given value
6
+ class StartsWith < ::Contracts::Builtin::CallableClass
7
+ def initialize(*args)
8
+ @start = args[0]
9
+ end
10
+
11
+ def valid?(object)
12
+ object.to_s.start_with?(@start)
13
+ end
14
+
15
+ def to_s
16
+ "Expected to start with #{@start}"
17
+ end
18
+
19
+ def inspect
20
+ to_s
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aggregate
4
+ # Contracts are used in stages to apply validation of the options passed into a stage
5
+ module Contracts
6
+ Autoloaded.module {}
7
+ end
8
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aggregate
4
+ # Represents an aggregation pipeline and is the main entry point to the DSL
5
+ # Example: Aggregate::Pipeline.new().match().project().execute()
6
+ class Pipeline
7
+ attr_reader :stages
8
+
9
+ def initialize(klass = nil)
10
+ @klass = klass
11
+ @stages = []
12
+ end
13
+
14
+ def to_s
15
+ inspect
16
+ end
17
+
18
+ def inspect
19
+ @stages.to_s
20
+ end
21
+
22
+ # :reek:NilCheck
23
+ def execute
24
+ raise "Pipeline initializer must specify a class in order to be executable" if @klass.nil?
25
+
26
+ db = Mongoid.default_client.database
27
+ command = "function(){return db.#{@klass.collection_name}.aggregate(#{self}).toArray()}"
28
+
29
+ # https://github.com/mongodb/mongo-ruby-driver/blob/master/lib/mongo/operation/result.rb
30
+ result = db.command("$eval": command, nolock: true, await_data: true)
31
+ result.documents
32
+ end
33
+
34
+ Aggregate::Stages.constants.each do |klass|
35
+ define_method(klass.to_s.underscore) do |options|
36
+ @stages << "Aggregate::Stages::#{klass}".constantize.new(options)
37
+ self
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aggregate
4
+ module Stages
5
+ # derived stages are required to implement the following contract
6
+ # def to_s
7
+ # # return a properly formatted stage
8
+ # end
9
+ class Base < Aggregate::Values::Base
10
+ include ::Contracts::Core
11
+ include ::Contracts::Builtin
12
+ attr_reader :options
13
+ # :reek:NilCheck
14
+ def initialize(options)
15
+ value_handler = self.class.value_handlers.detect { |handler| handler.handles?(options) }
16
+ @options = value_handler.nil? ? options : value_handler.new(options, false)
17
+ end
18
+ end
19
+ end
20
+ end