mongoid 5.4.0 → 6.4.8
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +3 -3
- data/Rakefile +26 -0
- data/lib/config/locales/en.yml +40 -0
- data/lib/mongoid/atomic/modifiers.rb +2 -2
- data/lib/mongoid/atomic.rb +5 -5
- data/lib/mongoid/attributes/readonly.rb +22 -0
- data/lib/mongoid/attributes.rb +22 -21
- data/lib/mongoid/cacheable.rb +36 -0
- data/lib/mongoid/changeable.rb +36 -0
- data/lib/mongoid/clients/options.rb +55 -250
- data/lib/mongoid/clients/sessions.rb +113 -0
- data/lib/mongoid/clients/storage_options.rb +2 -69
- data/lib/mongoid/clients.rb +10 -63
- data/lib/mongoid/composable.rb +29 -2
- data/lib/mongoid/config.rb +1 -0
- data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
- data/lib/mongoid/contextual/atomic.rb +4 -4
- data/lib/mongoid/contextual/map_reduce.rb +7 -3
- data/lib/mongoid/contextual/memory.rb +9 -4
- data/lib/mongoid/contextual/mongo.rb +65 -30
- data/lib/mongoid/contextual/none.rb +12 -0
- data/lib/mongoid/copyable.rb +13 -6
- data/lib/mongoid/criteria/marshalable.rb +2 -2
- data/lib/mongoid/criteria/modifiable.rb +29 -3
- data/lib/mongoid/criteria/options.rb +25 -0
- data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
- data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
- data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
- data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
- data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
- data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
- data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
- data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
- data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
- data/lib/mongoid/criteria/queryable/extensions/regexp.rb +79 -0
- data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
- data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
- data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
- data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
- data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
- data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
- data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
- data/lib/mongoid/criteria/queryable/key.rb +103 -0
- data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
- data/lib/mongoid/criteria/queryable/mergeable.rb +273 -0
- data/lib/mongoid/criteria/queryable/optional.rb +429 -0
- data/lib/mongoid/criteria/queryable/options.rb +153 -0
- data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
- data/lib/mongoid/criteria/queryable/selectable.rb +689 -0
- data/lib/mongoid/criteria/queryable/selector.rb +212 -0
- data/lib/mongoid/criteria/queryable/smash.rb +104 -0
- data/lib/mongoid/criteria/queryable.rb +87 -0
- data/lib/mongoid/criteria.rb +6 -2
- data/lib/mongoid/document.rb +34 -41
- data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
- data/lib/mongoid/errors/in_memory_collation_not_supported.rb +1 -1
- data/lib/mongoid/errors/invalid_field.rb +2 -2
- data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
- data/lib/mongoid/errors/invalid_relation.rb +66 -0
- data/lib/mongoid/errors/invalid_session_use.rb +24 -0
- data/lib/mongoid/errors.rb +3 -0
- data/lib/mongoid/evolvable.rb +1 -1
- data/lib/mongoid/extensions/big_decimal.rb +17 -8
- data/lib/mongoid/extensions/date.rb +4 -1
- data/lib/mongoid/extensions/decimal128.rb +3 -3
- data/lib/mongoid/extensions/hash.rb +1 -0
- data/lib/mongoid/extensions/regexp.rb +1 -0
- data/lib/mongoid/extensions/string.rb +6 -3
- data/lib/mongoid/extensions/time.rb +4 -1
- data/lib/mongoid/extensions.rb +0 -4
- data/lib/mongoid/factory.rb +2 -1
- data/lib/mongoid/fields/validators/macro.rb +18 -0
- data/lib/mongoid/findable.rb +2 -2
- data/lib/mongoid/indexable.rb +16 -14
- data/lib/mongoid/interceptable.rb +9 -22
- data/lib/mongoid/matchable/all.rb +2 -2
- data/lib/mongoid/matchable/and.rb +3 -3
- data/lib/mongoid/matchable/default.rb +2 -2
- data/lib/mongoid/matchable/elem_match.rb +28 -0
- data/lib/mongoid/matchable/exists.rb +2 -2
- data/lib/mongoid/matchable/gt.rb +4 -2
- data/lib/mongoid/matchable/gte.rb +4 -2
- data/lib/mongoid/matchable/in.rb +2 -2
- data/lib/mongoid/matchable/lt.rb +4 -2
- data/lib/mongoid/matchable/lte.rb +4 -2
- data/lib/mongoid/matchable/ne.rb +2 -2
- data/lib/mongoid/matchable/nin.rb +2 -2
- data/lib/mongoid/matchable/nor.rb +37 -0
- data/lib/mongoid/matchable/or.rb +3 -3
- data/lib/mongoid/matchable/regexp.rb +3 -3
- data/lib/mongoid/matchable/size.rb +2 -2
- data/lib/mongoid/matchable.rb +16 -7
- data/lib/mongoid/persistable/creatable.rb +5 -3
- data/lib/mongoid/persistable/deletable.rb +5 -3
- data/lib/mongoid/persistable/destroyable.rb +1 -5
- data/lib/mongoid/persistable/settable.rb +5 -5
- data/lib/mongoid/persistable/updatable.rb +7 -14
- data/lib/mongoid/persistable/upsertable.rb +2 -1
- data/lib/mongoid/persistable.rb +4 -6
- data/lib/mongoid/persistence_context.rb +220 -0
- data/lib/mongoid/query_cache.rb +67 -23
- data/lib/mongoid/railtie.rb +17 -1
- data/lib/mongoid/railties/controller_runtime.rb +86 -0
- data/lib/mongoid/relations/accessors.rb +3 -0
- data/lib/mongoid/relations/auto_save.rb +12 -4
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
- data/lib/mongoid/relations/counter_cache.rb +15 -5
- data/lib/mongoid/relations/eager/base.rb +3 -3
- data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +2 -2
- data/lib/mongoid/relations/eager/has_many.rb +1 -1
- data/lib/mongoid/relations/eager.rb +6 -11
- data/lib/mongoid/relations/embedded/batchable.rb +20 -18
- data/lib/mongoid/relations/embedded/in.rb +13 -1
- data/lib/mongoid/relations/embedded/many.rb +51 -10
- data/lib/mongoid/relations/embedded/one.rb +14 -1
- data/lib/mongoid/relations/macros.rb +9 -1
- data/lib/mongoid/relations/many.rb +4 -0
- data/lib/mongoid/relations/metadata.rb +3 -3
- data/lib/mongoid/relations/options.rb +2 -2
- data/lib/mongoid/relations/proxy.rb +1 -31
- data/lib/mongoid/relations/referenced/in.rb +19 -10
- data/lib/mongoid/relations/referenced/many.rb +30 -26
- data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
- data/lib/mongoid/relations/referenced/one.rb +15 -1
- data/lib/mongoid/relations/synchronization.rb +12 -12
- data/lib/mongoid/relations/targets/enumerable.rb +24 -4
- data/lib/mongoid/relations/touchable.rb +7 -4
- data/lib/mongoid/reloadable.rb +2 -2
- data/lib/mongoid/scopable.rb +3 -3
- data/lib/mongoid/serializable.rb +1 -1
- data/lib/mongoid/stateful.rb +1 -0
- data/lib/mongoid/tasks/database.rb +3 -2
- data/lib/mongoid/threaded.rb +74 -0
- data/lib/mongoid/traversable.rb +1 -1
- data/lib/mongoid/validatable/uniqueness.rb +1 -2
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid.rb +6 -6
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +18 -3
- data/spec/app/models/agent.rb +2 -0
- data/spec/app/models/album.rb +5 -1
- data/spec/app/models/array_field.rb +7 -0
- data/spec/app/models/artist.rb +21 -0
- data/spec/app/models/band.rb +3 -0
- data/spec/app/models/book.rb +2 -1
- data/spec/app/models/delegating_patient.rb +16 -0
- data/spec/app/models/dokument.rb +1 -0
- data/spec/app/models/ordered_post.rb +5 -0
- data/spec/app/models/oscar.rb +1 -2
- data/spec/app/models/page.rb +1 -1
- data/spec/app/models/person.rb +3 -3
- data/spec/app/models/princess.rb +2 -0
- data/spec/app/models/record.rb +1 -0
- data/spec/app/models/subscription.rb +1 -0
- data/spec/app/models/thing.rb +1 -1
- data/spec/config/mongoid.yml +15 -0
- data/spec/integration/document_spec.rb +22 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +3 -3
- data/spec/mongoid/atomic_spec.rb +5 -5
- data/spec/mongoid/attributes/nested_spec.rb +18 -14
- data/spec/mongoid/attributes/readonly_spec.rb +87 -44
- data/spec/mongoid/attributes_spec.rb +90 -5
- data/spec/mongoid/cacheable_spec.rb +112 -0
- data/spec/mongoid/changeable_spec.rb +58 -0
- data/spec/mongoid/clients/factory_spec.rb +80 -28
- data/spec/mongoid/clients/options_spec.rb +396 -95
- data/spec/mongoid/clients/sessions_spec.rb +334 -0
- data/spec/mongoid/clients_spec.rb +243 -101
- data/spec/mongoid/composable_spec.rb +7 -0
- data/spec/mongoid/config_spec.rb +67 -11
- data/spec/mongoid/contextual/atomic_spec.rb +3 -3
- data/spec/mongoid/contextual/geo_near_spec.rb +1 -0
- data/spec/mongoid/contextual/mongo_spec.rb +275 -22
- data/spec/mongoid/contextual/none_spec.rb +15 -0
- data/spec/mongoid/copyable_spec.rb +13 -4
- data/spec/mongoid/criteria/modifiable_spec.rb +297 -16
- data/spec/mongoid/criteria/options_spec.rb +29 -0
- data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
- data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
- data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
- data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
- data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
- data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
- data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
- data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
- data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
- data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
- data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
- data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
- data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
- data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
- data/spec/mongoid/{extensions/origin → criteria/queryable/extensions}/regexp_raw_spec.rb +2 -2
- data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +90 -0
- data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
- data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
- data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
- data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
- data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
- data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
- data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
- data/spec/mongoid/criteria/queryable/optional_spec.rb +1799 -0
- data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
- data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
- data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +4242 -0
- data/spec/mongoid/criteria/queryable/selector_spec.rb +844 -0
- data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
- data/spec/mongoid/criteria/scopable_spec.rb +81 -0
- data/spec/mongoid/criteria_spec.rb +156 -22
- data/spec/mongoid/document_spec.rb +100 -90
- data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
- data/spec/mongoid/extensions/big_decimal_spec.rb +321 -19
- data/spec/mongoid/extensions/boolean_spec.rb +14 -0
- data/spec/mongoid/extensions/date_spec.rb +2 -6
- data/spec/mongoid/extensions/date_time_spec.rb +2 -6
- data/spec/mongoid/extensions/decimal128_spec.rb +1 -1
- data/spec/mongoid/extensions/float_spec.rb +8 -1
- data/spec/mongoid/extensions/hash_spec.rb +15 -0
- data/spec/mongoid/extensions/integer_spec.rb +8 -1
- data/spec/mongoid/extensions/object_spec.rb +11 -0
- data/spec/mongoid/extensions/regexp_spec.rb +23 -0
- data/spec/mongoid/extensions/string_spec.rb +53 -4
- data/spec/mongoid/extensions/time_spec.rb +2 -6
- data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
- data/spec/mongoid/factory_spec.rb +11 -0
- data/spec/mongoid/fields_spec.rb +1 -1
- data/spec/mongoid/findable_spec.rb +47 -2
- data/spec/mongoid/indexable_spec.rb +15 -3
- data/spec/mongoid/interceptable_spec.rb +85 -19
- data/spec/mongoid/matchable/all_spec.rb +4 -4
- data/spec/mongoid/matchable/and_spec.rb +10 -10
- data/spec/mongoid/matchable/default_spec.rb +12 -12
- data/spec/mongoid/matchable/elem_match_spec.rb +86 -0
- data/spec/mongoid/matchable/exists_spec.rb +5 -5
- data/spec/mongoid/matchable/gt_spec.rb +18 -7
- data/spec/mongoid/matchable/gte_spec.rb +17 -7
- data/spec/mongoid/matchable/in_spec.rb +5 -5
- data/spec/mongoid/matchable/lt_spec.rb +18 -7
- data/spec/mongoid/matchable/lte_spec.rb +18 -7
- data/spec/mongoid/matchable/ne_spec.rb +5 -5
- data/spec/mongoid/matchable/nin_spec.rb +5 -5
- data/spec/mongoid/matchable/nor_spec.rb +209 -0
- data/spec/mongoid/matchable/or_spec.rb +7 -7
- data/spec/mongoid/matchable/regexp_spec.rb +5 -5
- data/spec/mongoid/matchable/size_spec.rb +3 -3
- data/spec/mongoid/matchable_spec.rb +199 -54
- data/spec/mongoid/persistable/creatable_spec.rb +7 -2
- data/spec/mongoid/persistable/deletable_spec.rb +35 -1
- data/spec/mongoid/persistable/destroyable_spec.rb +25 -2
- data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
- data/spec/mongoid/persistable/savable_spec.rb +34 -29
- data/spec/mongoid/persistable/settable_spec.rb +77 -27
- data/spec/mongoid/persistable/updatable_spec.rb +182 -3
- data/spec/mongoid/persistable_spec.rb +16 -16
- data/spec/mongoid/persistence_context_spec.rb +694 -0
- data/spec/mongoid/positional_spec.rb +1 -1
- data/spec/mongoid/query_cache_spec.rb +170 -12
- data/spec/mongoid/relations/accessors_spec.rb +1 -1
- data/spec/mongoid/relations/auto_save_spec.rb +39 -6
- data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +4 -4
- data/spec/mongoid/relations/builders_spec.rb +37 -10
- data/spec/mongoid/relations/counter_cache_spec.rb +64 -3
- data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +16 -0
- data/spec/mongoid/relations/eager_spec.rb +40 -0
- data/spec/mongoid/relations/embedded/many_spec.rb +305 -59
- data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
- data/spec/mongoid/relations/macros_spec.rb +415 -7
- data/spec/mongoid/relations/metadata_spec.rb +15 -1
- data/spec/mongoid/relations/proxy_spec.rb +27 -1
- data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
- data/spec/mongoid/relations/referenced/many_spec.rb +35 -25
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +14 -26
- data/spec/mongoid/relations/synchronization_spec.rb +48 -2
- data/spec/mongoid/relations/targets/enumerable_spec.rb +108 -0
- data/spec/mongoid/relations/touchable_spec.rb +40 -0
- data/spec/mongoid/reloadable_spec.rb +51 -0
- data/spec/mongoid/scopable_spec.rb +13 -0
- data/spec/mongoid/serializable_spec.rb +0 -50
- data/spec/mongoid/threaded_spec.rb +68 -0
- data/spec/mongoid/validatable/presence_spec.rb +1 -1
- data/spec/mongoid/validatable/uniqueness_spec.rb +18 -9
- data/spec/mongoid/validatable_spec.rb +16 -0
- data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
- data/spec/spec_helper.rb +101 -8
- data/spec/support/cluster_config.rb +158 -0
- data/spec/support/constraints.rb +101 -0
- data/spec/support/macros.rb +20 -0
- data/spec/support/session_registry.rb +50 -0
- data/spec/support/spec_config.rb +42 -0
- data.tar.gz.sig +0 -0
- metadata +163 -61
- metadata.gz.sig +0 -0
- data/lib/mongoid/clients/thread_options.rb +0 -19
- data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
- data/lib/mongoid/railties/document.rb +0 -12
- data/spec/mongoid/railties/document_spec.rb +0 -24
| @@ -0,0 +1,370 @@ | |
| 1 | 
            +
            require "spec_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Mongoid::Criteria::Queryable::Aggregable do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              let(:query) do
         | 
| 6 | 
            +
                Mongoid::Query.new("id" => "_id", "alias" => "a")
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              shared_examples_for "an aggregable object" do
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                it "clones the queryable" do
         | 
| 12 | 
            +
                  expect(aggregation).to_not equal(query)
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                it "sets the aggrating flag" do
         | 
| 16 | 
            +
                  expect(aggregation).to be_aggregating
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              describe "#project" do
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                context "when no selection or options exist" do
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  let(:aggregation) do
         | 
| 25 | 
            +
                    query.project(author: 1, title: 0)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  let!(:pipeline) do
         | 
| 29 | 
            +
                    aggregation.pipeline
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  it "sets the projection" do
         | 
| 33 | 
            +
                    expect(pipeline).to eq([
         | 
| 34 | 
            +
                      { "$project" => { "author" => 1, "title" => 0 }}
         | 
| 35 | 
            +
                    ])
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  it_behaves_like "an aggregable object"
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                context "when the field is aliased" do
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  let(:aggregation) do
         | 
| 44 | 
            +
                    query.project(id: 1, title: "$docTitle")
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  let!(:pipeline) do
         | 
| 48 | 
            +
                    aggregation.pipeline
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  it "sets the aliased projection" do
         | 
| 52 | 
            +
                    expect(pipeline).to eq([
         | 
| 53 | 
            +
                      { "$project" => { "_id" => 1, "title" => "$docTitle" }}
         | 
| 54 | 
            +
                    ])
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  it_behaves_like "an aggregable object"
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                context "when selection exists" do
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  let(:aggregation) do
         | 
| 63 | 
            +
                    query.where(name: "test").project(author: 1, title: 0)
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  let!(:pipeline) do
         | 
| 67 | 
            +
                    aggregation.pipeline
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  it "converts the selection to a $match" do
         | 
| 71 | 
            +
                    expect(pipeline).to eq([
         | 
| 72 | 
            +
                      { "$match" => { "name" => "test" }},
         | 
| 73 | 
            +
                      { "$project" => { "author" => 1, "title" => 0 }}
         | 
| 74 | 
            +
                    ])
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  it_behaves_like "an aggregable object"
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                context "when options exist" do
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                  context "when the option is a sort" do
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    let(:aggregation) do
         | 
| 85 | 
            +
                      query.asc(:name).project(author: 1, title: 0)
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                    let!(:pipeline) do
         | 
| 89 | 
            +
                      aggregation.pipeline
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                    it "converts the option to a $sort" do
         | 
| 93 | 
            +
                      expect(pipeline).to eq([
         | 
| 94 | 
            +
                        { "$sort" => { "name" => 1 }},
         | 
| 95 | 
            +
                        { "$project" => { "author" => 1, "title" => 0 }}
         | 
| 96 | 
            +
                      ])
         | 
| 97 | 
            +
                    end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  context "when the option is a limit" do
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                    let(:aggregation) do
         | 
| 105 | 
            +
                      query.limit(10).project(author: 1, title: 0)
         | 
| 106 | 
            +
                    end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                    let!(:pipeline) do
         | 
| 109 | 
            +
                      aggregation.pipeline
         | 
| 110 | 
            +
                    end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                    it "converts the option to a $sort" do
         | 
| 113 | 
            +
                      expect(pipeline).to eq([
         | 
| 114 | 
            +
                        { "$limit" => 10 },
         | 
| 115 | 
            +
                        { "$project" => { "author" => 1, "title" => 0 }}
         | 
| 116 | 
            +
                      ])
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                  context "when the option is a skip" do
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                    let(:aggregation) do
         | 
| 125 | 
            +
                      query.skip(10).project(author: 1, title: 0)
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    let!(:pipeline) do
         | 
| 129 | 
            +
                      aggregation.pipeline
         | 
| 130 | 
            +
                    end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                    it "converts the option to a $sort" do
         | 
| 133 | 
            +
                      expect(pipeline).to eq([
         | 
| 134 | 
            +
                        { "$skip" => 10 },
         | 
| 135 | 
            +
                        { "$project" => { "author" => 1, "title" => 0 }}
         | 
| 136 | 
            +
                      ])
         | 
| 137 | 
            +
                    end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 140 | 
            +
                  end
         | 
| 141 | 
            +
                end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                context "when selection and options exist" do
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                  let(:aggregation) do
         | 
| 146 | 
            +
                    query.skip(10).where(name: "test").project(author: 1, title: 0)
         | 
| 147 | 
            +
                  end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  let!(:pipeline) do
         | 
| 150 | 
            +
                    aggregation.pipeline
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                  it "converts the option to a $sort" do
         | 
| 154 | 
            +
                    expect(pipeline).to eq([
         | 
| 155 | 
            +
                      { "$match" => { "name" => "test" }},
         | 
| 156 | 
            +
                      { "$skip" => 10 },
         | 
| 157 | 
            +
                      { "$project" => { "author" => 1, "title" => 0 }}
         | 
| 158 | 
            +
                    ])
         | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                  it_behaves_like "an aggregable object"
         | 
| 162 | 
            +
                end
         | 
| 163 | 
            +
              end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
              describe "#unwind" do
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                context "when another pipeline operation exists" do
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                  let(:aggregation) do
         | 
| 170 | 
            +
                    query.project(name: 1).unwind(:author)
         | 
| 171 | 
            +
                  end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                  let!(:pipeline) do
         | 
| 174 | 
            +
                    aggregation.pipeline
         | 
| 175 | 
            +
                  end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                  it "adds the unwind to the pipeline" do
         | 
| 178 | 
            +
                    expect(pipeline).to eq([
         | 
| 179 | 
            +
                      { "$project" => { "name" => 1 }},
         | 
| 180 | 
            +
                      { "$unwind" => "$author" }
         | 
| 181 | 
            +
                    ])
         | 
| 182 | 
            +
                  end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                  it_behaves_like "an aggregable object"
         | 
| 185 | 
            +
                end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                context "when provided a symbol" do
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                  context "when the symbol begins with $" do
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                    let(:aggregation) do
         | 
| 192 | 
            +
                      query.unwind(:$author)
         | 
| 193 | 
            +
                    end
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                    let!(:pipeline) do
         | 
| 196 | 
            +
                      aggregation.pipeline
         | 
| 197 | 
            +
                    end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                    it "converts the symbol to a string" do
         | 
| 200 | 
            +
                      expect(pipeline).to eq([{ "$unwind" => "$author" }])
         | 
| 201 | 
            +
                    end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 204 | 
            +
                  end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                  context "when the symbol does not begin with $" do
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                    let(:aggregation) do
         | 
| 209 | 
            +
                      query.unwind(:author)
         | 
| 210 | 
            +
                    end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                    let!(:pipeline) do
         | 
| 213 | 
            +
                      aggregation.pipeline
         | 
| 214 | 
            +
                    end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                    it "converts the symbol to a string and prepends $" do
         | 
| 217 | 
            +
                      expect(pipeline).to eq([{ "$unwind" => "$author" }])
         | 
| 218 | 
            +
                    end
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 221 | 
            +
                  end
         | 
| 222 | 
            +
                end
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                context "when provided a string" do
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                  context "when the string begins with $" do
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                    let(:aggregation) do
         | 
| 229 | 
            +
                      query.unwind("$author")
         | 
| 230 | 
            +
                    end
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                    let!(:pipeline) do
         | 
| 233 | 
            +
                      aggregation.pipeline
         | 
| 234 | 
            +
                    end
         | 
| 235 | 
            +
             | 
| 236 | 
            +
                    it "sets the string" do
         | 
| 237 | 
            +
                      expect(pipeline).to eq([{ "$unwind" => "$author" }])
         | 
| 238 | 
            +
                    end
         | 
| 239 | 
            +
             | 
| 240 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 241 | 
            +
                  end
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                  context "when the string does not begin with $" do
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                    let(:aggregation) do
         | 
| 246 | 
            +
                      query.unwind(:author)
         | 
| 247 | 
            +
                    end
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                    let!(:pipeline) do
         | 
| 250 | 
            +
                      aggregation.pipeline
         | 
| 251 | 
            +
                    end
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                    it "prepends $ to the string" do
         | 
| 254 | 
            +
                      expect(pipeline).to eq([{ "$unwind" => "$author" }])
         | 
| 255 | 
            +
                    end
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 258 | 
            +
                  end
         | 
| 259 | 
            +
                end
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                context "when provided a string alias" do
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                  context "when the string does not begin with $" do
         | 
| 264 | 
            +
             | 
| 265 | 
            +
                    let(:aggregation) do
         | 
| 266 | 
            +
                      query.unwind(:alias)
         | 
| 267 | 
            +
                    end
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                    let!(:pipeline) do
         | 
| 270 | 
            +
                      aggregation.pipeline
         | 
| 271 | 
            +
                    end
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                    it "prepends $ to the string" do
         | 
| 274 | 
            +
                      expect(pipeline).to eq([{ "$unwind" => "$a" }])
         | 
| 275 | 
            +
                    end
         | 
| 276 | 
            +
             | 
| 277 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 278 | 
            +
                  end
         | 
| 279 | 
            +
                end
         | 
| 280 | 
            +
              end
         | 
| 281 | 
            +
             | 
| 282 | 
            +
              describe "#group" do
         | 
| 283 | 
            +
             | 
| 284 | 
            +
                context "when the expression fields are not aliased" do
         | 
| 285 | 
            +
             | 
| 286 | 
            +
                  context "when using full notation" do
         | 
| 287 | 
            +
             | 
| 288 | 
            +
                    let(:aggregation) do
         | 
| 289 | 
            +
                      query.group(count: { "$sum" => 1 }, max: { "$max" => "likes" })
         | 
| 290 | 
            +
                    end
         | 
| 291 | 
            +
             | 
| 292 | 
            +
                    let!(:pipeline) do
         | 
| 293 | 
            +
                      aggregation.pipeline
         | 
| 294 | 
            +
                    end
         | 
| 295 | 
            +
             | 
| 296 | 
            +
                    it "adds the group operation to the pipeline" do
         | 
| 297 | 
            +
                      expect(pipeline).to eq([
         | 
| 298 | 
            +
                        { "$group" => { "count" => { "$sum" => 1 }, "max" => { "$max" => "likes" }}}
         | 
| 299 | 
            +
                      ])
         | 
| 300 | 
            +
                    end
         | 
| 301 | 
            +
             | 
| 302 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 303 | 
            +
                  end
         | 
| 304 | 
            +
             | 
| 305 | 
            +
                  context "when using symbol shortcuts" do
         | 
| 306 | 
            +
             | 
| 307 | 
            +
                    let(:aggregation) do
         | 
| 308 | 
            +
                      query.group(:count.sum => 1, :max.max => "likes")
         | 
| 309 | 
            +
                    end
         | 
| 310 | 
            +
             | 
| 311 | 
            +
                    let!(:pipeline) do
         | 
| 312 | 
            +
                      aggregation.pipeline
         | 
| 313 | 
            +
                    end
         | 
| 314 | 
            +
             | 
| 315 | 
            +
                    it "adds the group operation to the pipeline" do
         | 
| 316 | 
            +
                      expect(pipeline).to eq([
         | 
| 317 | 
            +
                        { "$group" => { "count" => { "$sum" => 1 }, "max" => { "$max" => "likes" }}}
         | 
| 318 | 
            +
                      ])
         | 
| 319 | 
            +
                    end
         | 
| 320 | 
            +
             | 
| 321 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 322 | 
            +
                  end
         | 
| 323 | 
            +
                end
         | 
| 324 | 
            +
             | 
| 325 | 
            +
                context "when the expression fields are aliased" do
         | 
| 326 | 
            +
             | 
| 327 | 
            +
                  context "when using full notation" do
         | 
| 328 | 
            +
             | 
| 329 | 
            +
                    let(:aggregation) do
         | 
| 330 | 
            +
                      query.group(count: { "$sum" => 1 }, max: { "$max" => "alias" })
         | 
| 331 | 
            +
                    end
         | 
| 332 | 
            +
             | 
| 333 | 
            +
                    let!(:pipeline) do
         | 
| 334 | 
            +
                      aggregation.pipeline
         | 
| 335 | 
            +
                    end
         | 
| 336 | 
            +
             | 
| 337 | 
            +
                    it "adds the group operation to the pipeline" do
         | 
| 338 | 
            +
                      pending
         | 
| 339 | 
            +
                      fail
         | 
| 340 | 
            +
                      expect(pipeline).to eq([
         | 
| 341 | 
            +
                        { "$group" => { "count" => { "$sum" => 1 }, "max" => { "$max" => "a" }}}
         | 
| 342 | 
            +
                      ])
         | 
| 343 | 
            +
                    end
         | 
| 344 | 
            +
             | 
| 345 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 346 | 
            +
                  end
         | 
| 347 | 
            +
             | 
| 348 | 
            +
                  context "when using symbol shortcuts" do
         | 
| 349 | 
            +
             | 
| 350 | 
            +
                    let(:aggregation) do
         | 
| 351 | 
            +
                      query.group(:count.sum => 1, :max.max => "alias")
         | 
| 352 | 
            +
                    end
         | 
| 353 | 
            +
             | 
| 354 | 
            +
                    let!(:pipeline) do
         | 
| 355 | 
            +
                      aggregation.pipeline
         | 
| 356 | 
            +
                    end
         | 
| 357 | 
            +
             | 
| 358 | 
            +
                    it "adds the group operation to the pipeline" do
         | 
| 359 | 
            +
                      pending
         | 
| 360 | 
            +
                      fail
         | 
| 361 | 
            +
                      expect(pipeline).to eq([
         | 
| 362 | 
            +
                        { "$group" => { "count" => { "$sum" => 1 }, "max" => { "$max" => "a" }}}
         | 
| 363 | 
            +
                      ])
         | 
| 364 | 
            +
                    end
         | 
| 365 | 
            +
             | 
| 366 | 
            +
                    it_behaves_like "an aggregable object"
         | 
| 367 | 
            +
                  end
         | 
| 368 | 
            +
                end
         | 
| 369 | 
            +
              end
         | 
| 370 | 
            +
            end
         |