mongoid 5.4.1 → 6.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.
- checksums.yaml +5 -5
- data/README.md +3 -3
- data/lib/config/locales/en.yml +19 -0
- data/lib/mongoid.rb +4 -4
- data/lib/mongoid/atomic.rb +2 -2
- data/lib/mongoid/atomic/modifiers.rb +8 -12
- data/lib/mongoid/attributes.rb +22 -21
- data/lib/mongoid/attributes/readonly.rb +22 -0
- data/lib/mongoid/cacheable.rb +36 -0
- data/lib/mongoid/changeable.rb +36 -0
- data/lib/mongoid/clients.rb +8 -63
- data/lib/mongoid/clients/options.rb +55 -250
- data/lib/mongoid/clients/storage_options.rb +1 -69
- data/lib/mongoid/composable.rb +29 -3
- data/lib/mongoid/config.rb +1 -0
- data/lib/mongoid/contextual/atomic.rb +5 -8
- data/lib/mongoid/contextual/map_reduce.rb +0 -4
- data/lib/mongoid/contextual/memory.rb +2 -2
- data/lib/mongoid/contextual/mongo.rb +40 -22
- data/lib/mongoid/contextual/none.rb +12 -0
- data/lib/mongoid/copyable.rb +13 -6
- data/lib/mongoid/criteria.rb +5 -2
- data/lib/mongoid/criteria/marshalable.rb +2 -2
- data/lib/mongoid/criteria/modifiable.rb +17 -1
- data/lib/mongoid/criteria/options.rb +25 -0
- data/lib/mongoid/criteria/queryable.rb +87 -0
- data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
- data/lib/mongoid/criteria/queryable/extensions.rb +28 -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/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 +271 -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 +662 -0
- data/lib/mongoid/criteria/queryable/selector.rb +212 -0
- data/lib/mongoid/criteria/queryable/smash.rb +104 -0
- data/lib/mongoid/document.rb +30 -37
- data/lib/mongoid/errors.rb +2 -0
- 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/evolvable.rb +1 -1
- data/lib/mongoid/extensions.rb +0 -4
- 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/string.rb +4 -3
- data/lib/mongoid/extensions/time.rb +4 -1
- data/lib/mongoid/fields/validators/macro.rb +18 -0
- data/lib/mongoid/findable.rb +2 -2
- data/lib/mongoid/indexable.rb +15 -13
- data/lib/mongoid/interceptable.rb +5 -22
- data/lib/mongoid/matchable.rb +13 -7
- 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/or.rb +3 -3
- data/lib/mongoid/matchable/regexp.rb +3 -3
- data/lib/mongoid/matchable/size.rb +2 -2
- data/lib/mongoid/persistable.rb +3 -5
- data/lib/mongoid/persistable/creatable.rb +2 -2
- data/lib/mongoid/persistable/deletable.rb +1 -1
- data/lib/mongoid/persistable/settable.rb +1 -1
- data/lib/mongoid/persistable/updatable.rb +5 -12
- data/lib/mongoid/persistable/upsertable.rb +1 -1
- data/lib/mongoid/persistence_context.rb +215 -0
- data/lib/mongoid/query_cache.rb +3 -6
- 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.rb +6 -11
- 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/embedded/batchable.rb +12 -36
- data/lib/mongoid/relations/embedded/in.rb +13 -1
- data/lib/mongoid/relations/embedded/many.rb +28 -10
- data/lib/mongoid/relations/embedded/one.rb +14 -1
- data/lib/mongoid/relations/macros.rb +9 -1
- 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 +23 -17
- 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 +11 -11
- data/lib/mongoid/relations/touchable.rb +6 -3
- data/lib/mongoid/reloadable.rb +1 -1
- data/lib/mongoid/serializable.rb +1 -1
- data/lib/mongoid/traversable.rb +1 -1
- data/lib/mongoid/validatable/uniqueness.rb +1 -2
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +14 -3
- data/spec/app/models/album.rb +5 -1
- data/spec/app/models/artist.rb +21 -0
- data/spec/app/models/book.rb +2 -1
- 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/mongoid/atomic/modifiers_spec.rb +17 -17
- data/spec/mongoid/atomic_spec.rb +17 -17
- data/spec/mongoid/attributes/nested_spec.rb +14 -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 +31 -3
- data/spec/mongoid/clients/options_spec.rb +382 -96
- 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/mongo_spec.rb +165 -20
- data/spec/mongoid/contextual/none_spec.rb +15 -0
- data/spec/mongoid/copyable_spec.rb +13 -4
- data/spec/mongoid/criteria/modifiable_spec.rb +239 -7
- 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 +4174 -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_spec.rb +152 -21
- data/spec/mongoid/document_spec.rb +37 -88
- 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 +320 -18
- 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/string_spec.rb +21 -0
- data/spec/mongoid/extensions/time_spec.rb +2 -6
- data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
- data/spec/mongoid/findable_spec.rb +46 -1
- data/spec/mongoid/indexable_spec.rb +15 -3
- data/spec/mongoid/interceptable_spec.rb +68 -10
- 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/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 +173 -53
- data/spec/mongoid/persistable/creatable_spec.rb +7 -2
- data/spec/mongoid/persistable/deletable_spec.rb +16 -1
- data/spec/mongoid/persistable/destroyable_spec.rb +6 -2
- data/spec/mongoid/persistable/savable_spec.rb +35 -30
- data/spec/mongoid/persistable/settable_spec.rb +45 -29
- data/spec/mongoid/persistable/updatable_spec.rb +184 -5
- data/spec/mongoid/persistence_context_spec.rb +680 -0
- data/spec/mongoid/positional_spec.rb +10 -10
- data/spec/mongoid/query_cache_spec.rb +89 -0
- 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 +63 -47
- data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
- data/spec/mongoid/relations/macros_spec.rb +395 -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 +13 -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/touchable_spec.rb +40 -0
- data/spec/mongoid/reloadable_spec.rb +51 -0
- data/spec/mongoid/serializable_spec.rb +0 -50
- 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/spec_helper.rb +20 -11
- metadata +524 -469
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/mongoid/clients/thread_options.rb +0 -19
- data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
- metadata.gz.sig +0 -0
@@ -538,6 +538,135 @@ describe Mongoid::Criteria::Modifiable do
|
|
538
538
|
it "sets the additional attributes" do
|
539
539
|
expect(document.origin).to eq("Essex")
|
540
540
|
end
|
541
|
+
|
542
|
+
context 'when attributes contain keys also in the criteria selector' do
|
543
|
+
|
544
|
+
context 'when the selector has symbol keys' do
|
545
|
+
|
546
|
+
context 'when the attributes use symbol keys' do
|
547
|
+
|
548
|
+
let(:document) do
|
549
|
+
Band.where(name: 'Tool').first_or_create(name: 'Essex')
|
550
|
+
end
|
551
|
+
|
552
|
+
it 'uses the values from the attributes' do
|
553
|
+
expect(document.name).to eq('Essex')
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
context 'when the attributes use string keys' do
|
558
|
+
|
559
|
+
let(:document) do
|
560
|
+
Band.where(name: 'Tool').first_or_create('name' => 'Essex')
|
561
|
+
end
|
562
|
+
|
563
|
+
it 'uses the values from the attributes' do
|
564
|
+
expect(document.name).to eq('Essex')
|
565
|
+
end
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
context 'when the selector has string keys' do
|
570
|
+
|
571
|
+
context 'when the attributes use symbol keys' do
|
572
|
+
|
573
|
+
let(:document) do
|
574
|
+
Band.where('name' => 'Tool').first_or_create(name: 'Essex')
|
575
|
+
end
|
576
|
+
|
577
|
+
it 'uses the values from the attributes' do
|
578
|
+
expect(document.name).to eq('Essex')
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
context 'when the attributes use string keys' do
|
583
|
+
|
584
|
+
let(:document) do
|
585
|
+
Band.where('name' => 'Tool').first_or_create('name' => 'Essex')
|
586
|
+
end
|
587
|
+
|
588
|
+
it 'uses the values from the attributes' do
|
589
|
+
expect(document.name).to eq('Essex')
|
590
|
+
end
|
591
|
+
end
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
context 'when the query criteria is on a hash attribute' do
|
596
|
+
|
597
|
+
let(:document) do
|
598
|
+
Person.where(map: { foo: :bar }).first_or_create
|
599
|
+
end
|
600
|
+
|
601
|
+
it 'uses the values from the attributes' do
|
602
|
+
expect(document.map).to eq({ foo: :bar })
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
context 'when the criteria has a selector with query operators' do
|
607
|
+
|
608
|
+
let(:document) do
|
609
|
+
Band.in(genres: ['Hiphop', 'Soul']).first_or_create(name: 'Smooth')
|
610
|
+
end
|
611
|
+
|
612
|
+
it 'does not create a document with the query operators' do
|
613
|
+
expect(document.attributes.keys).not_to include('genres')
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
617
|
+
context 'when the criteria has a nested selector with query operators' do
|
618
|
+
|
619
|
+
let(:band) do
|
620
|
+
record = Record.new(producers: ['testing'])
|
621
|
+
band = Band.create(records: [record])
|
622
|
+
end
|
623
|
+
|
624
|
+
let(:document) do
|
625
|
+
band.records.in(producers: ['nonexistent']).first_or_create(name: 'new-embedded-doc')
|
626
|
+
band.reload
|
627
|
+
end
|
628
|
+
|
629
|
+
it 'creates a new embedded document' do
|
630
|
+
expect(document.records.size).to eq(2)
|
631
|
+
end
|
632
|
+
|
633
|
+
it 'does not alter the existing embedded document' do
|
634
|
+
expect(document.records[0].producers).to eq(['testing'])
|
635
|
+
end
|
636
|
+
|
637
|
+
it 'does not create a document with the query operators as attributes' do
|
638
|
+
expect(document.records[1].producers).to be_nil
|
639
|
+
end
|
640
|
+
|
641
|
+
it 'applies the attribute to the new embedded document' do
|
642
|
+
expect(document.records[1].name).to eq('new-embedded-doc')
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
context 'when the criteria has a deeply-nested selector with query operators' do
|
647
|
+
|
648
|
+
let(:criteria) do
|
649
|
+
band = Band.create
|
650
|
+
Mongoid::Criteria.new(Record) do |criteria|
|
651
|
+
criteria.embedded = true
|
652
|
+
criteria.metadata = Band.reflect_on_association(:records)
|
653
|
+
criteria.parent_document = band
|
654
|
+
criteria.selector = { "records" => { "producers"=>{"$in"=>["nonexistent"] } } }
|
655
|
+
end
|
656
|
+
end
|
657
|
+
|
658
|
+
let(:document) do
|
659
|
+
criteria.first_or_create(name: 'new-record')
|
660
|
+
end
|
661
|
+
|
662
|
+
it 'does not create a document with the query operators' do
|
663
|
+
expect(document.attributes.keys).not_to include('producers')
|
664
|
+
end
|
665
|
+
|
666
|
+
it 'applies the attribute to the new embedded document' do
|
667
|
+
expect(document.name).to eq('new-record')
|
668
|
+
end
|
669
|
+
end
|
541
670
|
end
|
542
671
|
|
543
672
|
context "when attributes are not provided" do
|
@@ -736,6 +865,59 @@ describe Mongoid::Criteria::Modifiable do
|
|
736
865
|
end
|
737
866
|
end
|
738
867
|
end
|
868
|
+
|
869
|
+
context 'when attributes contain keys also in the criteria selector' do
|
870
|
+
|
871
|
+
context 'when the selector has symbol keys' do
|
872
|
+
|
873
|
+
context 'when the attributes use symbol keys' do
|
874
|
+
|
875
|
+
let(:document) do
|
876
|
+
Band.where(name: 'Tool').first_or_create!(name: 'Essex')
|
877
|
+
end
|
878
|
+
|
879
|
+
it 'uses the values from the attributes' do
|
880
|
+
expect(document.name).to eq('Essex')
|
881
|
+
end
|
882
|
+
end
|
883
|
+
|
884
|
+
context 'when the attributes use string keys' do
|
885
|
+
|
886
|
+
let(:document) do
|
887
|
+
Band.where(name: 'Tool').first_or_create!('name' => 'Essex')
|
888
|
+
end
|
889
|
+
|
890
|
+
it 'uses the values from the attributes' do
|
891
|
+
expect(document.name).to eq('Essex')
|
892
|
+
end
|
893
|
+
end
|
894
|
+
end
|
895
|
+
|
896
|
+
context 'when the selector has string keys' do
|
897
|
+
|
898
|
+
context 'when the attributes use symbol keys' do
|
899
|
+
|
900
|
+
let(:document) do
|
901
|
+
Band.where('name' => 'Tool').first_or_create!(name: 'Essex')
|
902
|
+
end
|
903
|
+
|
904
|
+
it 'uses the values from the attributes' do
|
905
|
+
expect(document.name).to eq('Essex')
|
906
|
+
end
|
907
|
+
end
|
908
|
+
|
909
|
+
context 'when the attributes use string keys' do
|
910
|
+
|
911
|
+
let(:document) do
|
912
|
+
Band.where('name' => 'Tool').first_or_create!('name' => 'Essex')
|
913
|
+
end
|
914
|
+
|
915
|
+
it 'uses the values from the attributes' do
|
916
|
+
expect(document.name).to eq('Essex')
|
917
|
+
end
|
918
|
+
end
|
919
|
+
end
|
920
|
+
end
|
739
921
|
end
|
740
922
|
end
|
741
923
|
|
@@ -830,6 +1012,59 @@ describe Mongoid::Criteria::Modifiable do
|
|
830
1012
|
end
|
831
1013
|
end
|
832
1014
|
end
|
1015
|
+
|
1016
|
+
context 'when attributes contain keys also in the criteria selector' do
|
1017
|
+
|
1018
|
+
context 'when the selector has symbol keys' do
|
1019
|
+
|
1020
|
+
context 'when the attributes use symbol keys' do
|
1021
|
+
|
1022
|
+
let(:document) do
|
1023
|
+
Band.where(name: 'Tool').first_or_initialize(name: 'Essex')
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
it 'uses the values from the attributes' do
|
1027
|
+
expect(document.name).to eq('Essex')
|
1028
|
+
end
|
1029
|
+
end
|
1030
|
+
|
1031
|
+
context 'when the attributes use string keys' do
|
1032
|
+
|
1033
|
+
let(:document) do
|
1034
|
+
Band.where(name: 'Tool').first_or_initialize('name' => 'Essex')
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
it 'uses the values from the attributes' do
|
1038
|
+
expect(document.name).to eq('Essex')
|
1039
|
+
end
|
1040
|
+
end
|
1041
|
+
end
|
1042
|
+
|
1043
|
+
context 'when the selector has string keys' do
|
1044
|
+
|
1045
|
+
context 'when the attributes use symbol keys' do
|
1046
|
+
|
1047
|
+
let(:document) do
|
1048
|
+
Band.where('name' => 'Tool').first_or_initialize(name: 'Essex')
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
it 'uses the values from the attributes' do
|
1052
|
+
expect(document.name).to eq('Essex')
|
1053
|
+
end
|
1054
|
+
end
|
1055
|
+
|
1056
|
+
context 'when the attributes use string keys' do
|
1057
|
+
|
1058
|
+
let(:document) do
|
1059
|
+
Band.where('name' => 'Tool').first_or_initialize('name' => 'Essex')
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
it 'uses the values from the attributes' do
|
1063
|
+
expect(document.name).to eq('Essex')
|
1064
|
+
end
|
1065
|
+
end
|
1066
|
+
end
|
1067
|
+
end
|
833
1068
|
end
|
834
1069
|
end
|
835
1070
|
|
@@ -1275,8 +1510,7 @@ describe Mongoid::Criteria::Modifiable do
|
|
1275
1510
|
end
|
1276
1511
|
|
1277
1512
|
it 'gives the write method args precedence' do
|
1278
|
-
|
1279
|
-
#expect(new_person.username).to eq('Beet')
|
1513
|
+
expect(new_person.username).to eq('Beet')
|
1280
1514
|
expect(new_person.age).to eq(50)
|
1281
1515
|
end
|
1282
1516
|
end
|
@@ -1332,8 +1566,7 @@ describe Mongoid::Criteria::Modifiable do
|
|
1332
1566
|
context 'when a write method is chained' do
|
1333
1567
|
|
1334
1568
|
it 'executes the method' do
|
1335
|
-
|
1336
|
-
#expect(criteria.create_with(attrs).new.username).to eq('Beet')
|
1569
|
+
expect(criteria.create_with(attrs).new.username).to eq('Turnip')
|
1337
1570
|
expect(criteria.create_with(attrs).new.age).to eq(25)
|
1338
1571
|
end
|
1339
1572
|
end
|
@@ -1345,9 +1578,8 @@ describe Mongoid::Criteria::Modifiable do
|
|
1345
1578
|
end
|
1346
1579
|
|
1347
1580
|
it 'executes the query' do
|
1348
|
-
|
1349
|
-
|
1350
|
-
#expect(new_person.age).to eq(50)
|
1581
|
+
expect(new_person.username).to eq('Beet')
|
1582
|
+
expect(new_person.age).to eq(50)
|
1351
1583
|
end
|
1352
1584
|
end
|
1353
1585
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Criteria::Options do
|
4
|
+
|
5
|
+
|
6
|
+
context 'when a persistence context with options is set on the class of the criteria' do
|
7
|
+
|
8
|
+
let(:context) do
|
9
|
+
Band.with(connect_timeout: 10) do |klass|
|
10
|
+
klass.where(name: 'FKA Twigs').persistence_context
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'uses the persistence context of the class of the criteria' do
|
15
|
+
expect(context.options).to eq({ connect_timeout: 10 })
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when a persistence context with options is not set on the class of the criteria' do
|
20
|
+
|
21
|
+
let(:context) do
|
22
|
+
Band.where(name: 'FKA Twigs').persistence_context
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'uses the persistence context of the class of the criteria' do
|
26
|
+
expect(context.options).to eq({ })
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -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
|