mongoid 7.0.4 → 7.0.5
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.tar.gz.sig +0 -0
- data/Rakefile +12 -0
- data/lib/mongoid/atomic/paths/embedded.rb +1 -1
- data/lib/mongoid/criteria/modifiable.rb +12 -2
- data/lib/mongoid/criteria/queryable/key.rb +67 -8
- data/lib/mongoid/criteria/queryable/selectable.rb +1 -1
- data/lib/mongoid/criteria/queryable/selector.rb +9 -31
- data/lib/mongoid/extensions/string.rb +2 -2
- data/lib/mongoid/positional.rb +1 -1
- data/lib/mongoid/query_cache.rb +1 -1
- data/lib/mongoid/validatable/macros.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/spec/README.md +18 -0
- data/spec/mongoid/clients/factory_spec.rb +2 -2
- data/spec/mongoid/clients/sessions_spec.rb +12 -3
- data/spec/mongoid/clients/transactions_spec.rb +16 -7
- data/spec/mongoid/contextual/geo_near_spec.rb +1 -0
- data/spec/mongoid/criteria/modifiable_spec.rb +59 -10
- data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +54 -0
- data/spec/mongoid/criteria/queryable/key_spec.rb +48 -6
- data/spec/mongoid/criteria/queryable/selector_spec.rb +37 -0
- data/spec/mongoid/criteria_spec.rb +3 -0
- data/spec/spec_helper.rb +6 -8
- data/spec/support/cluster_config.rb +158 -0
- metadata +435 -428
- metadata.gz.sig +0 -0
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 1d4a5f733ce016f190a456b5801a1e3a1efbe89a30d99a20cd4c73e5696e7004
         | 
| 4 | 
            +
              data.tar.gz: a40c8e747c7eeff97d8259bd6b11d35bf25de5434674c24f1c5ebe71ed5d6f3e
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 121ace21edf0fec13546294a101b4bb383eed7d7b7ead0d6bd3624ccfad5601a70a9e4b0363e710e687ba237835ea4a61da8d17ebab00a2537751a7fcbf5410f
         | 
| 7 | 
            +
              data.tar.gz: d39854dd3981a7c517e6ba00c0d85feb1e9bb6e928dabf233f603bf35f8299706c0981ed3cb9ba3c121e2af58ae42bc0e0e876a3a45f0264ac344d48469e9401
         | 
    
        checksums.yaml.gz.sig
    CHANGED
    
    | Binary file | 
    
        data.tar.gz.sig
    CHANGED
    
    | Binary file | 
    
        data/Rakefile
    CHANGED
    
    | @@ -33,3 +33,15 @@ RSpec::Core::RakeTask.new('spec:progress') do |spec| | |
| 33 33 | 
             
            end
         | 
| 34 34 |  | 
| 35 35 | 
             
            task :default => :spec
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            desc "Generate all documentation"
         | 
| 38 | 
            +
            task :docs => 'docs:yard'
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            namespace :docs do
         | 
| 41 | 
            +
              desc "Generate yard documention"
         | 
| 42 | 
            +
              task :yard do
         | 
| 43 | 
            +
                out = File.join('yard-docs', Mongoid::VERSION)
         | 
| 44 | 
            +
                FileUtils.rm_rf(out)
         | 
| 45 | 
            +
                system "yardoc -o #{out} --title mongoid-#{Mongoid::VERSION}"
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         | 
| @@ -3,6 +3,10 @@ module Mongoid | |
| 3 3 | 
             
              class Criteria
         | 
| 4 4 | 
             
                module Modifiable
         | 
| 5 5 |  | 
| 6 | 
            +
                  # @attribute [r] create_attrs Additional attributes to add to the Document upon creation.
         | 
| 7 | 
            +
                  # @api private
         | 
| 8 | 
            +
                  attr_reader :create_attrs
         | 
| 9 | 
            +
             | 
| 6 10 | 
             
                  # Build a document given the selector and return it.
         | 
| 7 11 | 
             
                  # Complex criteria, such as $in and $or operations will get ignored.
         | 
| 8 12 | 
             
                  #
         | 
| @@ -57,6 +61,9 @@ module Mongoid | |
| 57 61 |  | 
| 58 62 | 
             
                  # Define attributes with which new documents will be created.
         | 
| 59 63 | 
             
                  #
         | 
| 64 | 
            +
                  # Note that if `find_or_create_by` is called after this in a method chain, the attributes in
         | 
| 65 | 
            +
                  # the query will override those from this method.
         | 
| 66 | 
            +
                  #
         | 
| 60 67 | 
             
                  # @example Define attributes to be used when a new document is created.
         | 
| 61 68 | 
             
                  #   Person.create_with(job: 'Engineer').find_or_create_by(employer: 'MongoDB')
         | 
| 62 69 | 
             
                  #
         | 
| @@ -64,7 +71,9 @@ module Mongoid | |
| 64 71 | 
             
                  #
         | 
| 65 72 | 
             
                  # @since 5.1.0
         | 
| 66 73 | 
             
                  def create_with(attrs = {})
         | 
| 67 | 
            -
                     | 
| 74 | 
            +
                    tap do
         | 
| 75 | 
            +
                      (@create_attrs ||= {}).merge!(attrs)
         | 
| 76 | 
            +
                    end
         | 
| 68 77 | 
             
                  end
         | 
| 69 78 |  | 
| 70 79 | 
             
                  # Find the first +Document+ given the conditions, or creates a new document
         | 
| @@ -172,7 +181,8 @@ module Mongoid | |
| 172 181 | 
             
                  #
         | 
| 173 182 | 
             
                  # @since 3.0.0
         | 
| 174 183 | 
             
                  def create_document(method, attrs = nil, &block)
         | 
| 175 | 
            -
                     | 
| 184 | 
            +
                    attrs = (create_attrs || {}).merge(attrs || {})
         | 
| 185 | 
            +
                    attributes = selector.reduce(attrs) do |hash, (key, value)|
         | 
| 176 186 | 
             
                      unless invalid_key?(hash, key) || invalid_embedded_doc?(value)
         | 
| 177 187 | 
             
                        hash[key] = value
         | 
| 178 188 | 
             
                      end
         | 
| @@ -3,16 +3,75 @@ module Mongoid | |
| 3 3 | 
             
              class Criteria
         | 
| 4 4 | 
             
                module Queryable
         | 
| 5 5 |  | 
| 6 | 
            -
                  #  | 
| 7 | 
            -
                  #  | 
| 6 | 
            +
                  # Key objects represent specifications for building query expressions
         | 
| 7 | 
            +
                  # utilizing MongoDB selectors.
         | 
| 8 | 
            +
                  #
         | 
| 9 | 
            +
                  # Simple key-value conditions are translated directly into expression
         | 
| 10 | 
            +
                  # hashes by Mongoid without utilizing Key objects. For example, the
         | 
| 11 | 
            +
                  # following condition:
         | 
| 12 | 
            +
                  #
         | 
| 13 | 
            +
                  #   Foo.where(price: 1)
         | 
| 14 | 
            +
                  #
         | 
| 15 | 
            +
                  # ... is translated to the following simple expression:
         | 
| 16 | 
            +
                  #
         | 
| 17 | 
            +
                  #   {price: 1}
         | 
| 18 | 
            +
                  #
         | 
| 19 | 
            +
                  # More complex conditions would start involving Key objects. For example:
         | 
| 20 | 
            +
                  #
         | 
| 21 | 
            +
                  #   Foo.where(:price.gt => 1)
         | 
| 22 | 
            +
                  #
         | 
| 23 | 
            +
                  # ... causes a Key instance to be created thusly:
         | 
| 24 | 
            +
                  #
         | 
| 25 | 
            +
                  #   Key.new(:price, :__override__, '$gt')
         | 
| 26 | 
            +
                  #
         | 
| 27 | 
            +
                  # This Key instance utilizes +operator+ but not +expanded+ nor +block+.
         | 
| 28 | 
            +
                  # The corresponding MongoDB query expression is:
         | 
| 29 | 
            +
                  #
         | 
| 30 | 
            +
                  #    {price: {'$gt' => 1}}
         | 
| 31 | 
            +
                  #
         | 
| 32 | 
            +
                  # A yet more more complex example is the following condition:
         | 
| 33 | 
            +
                  #
         | 
| 34 | 
            +
                  #   Foo.geo_spacial(:boundary.intersects_point => [1, 10])
         | 
| 35 | 
            +
                  #
         | 
| 36 | 
            +
                  # Processing this condition will cause a Key instance to be created as
         | 
| 37 | 
            +
                  # follows:
         | 
| 38 | 
            +
                  #
         | 
| 39 | 
            +
                  #   Key.new(:location, :__override__, '$geoIntersects', '$geometry') do |value|
         | 
| 40 | 
            +
                  #     { "type" => POINT, "coordinates" => value }
         | 
| 41 | 
            +
                  #   end
         | 
| 42 | 
            +
                  #
         | 
| 43 | 
            +
                  # ... eventually producing the following MongoDB query expression:
         | 
| 44 | 
            +
                  #
         | 
| 45 | 
            +
                  # {
         | 
| 46 | 
            +
                  #   boundary: {
         | 
| 47 | 
            +
                  #     '$geoIntersects' => {
         | 
| 48 | 
            +
                  #       '$geometry' => {
         | 
| 49 | 
            +
                  #         type: "Point" ,
         | 
| 50 | 
            +
                  #         coordinates: [ 1, 10 ]
         | 
| 51 | 
            +
                  #       }
         | 
| 52 | 
            +
                  #     }
         | 
| 53 | 
            +
                  #   }
         | 
| 54 | 
            +
                  # }
         | 
| 55 | 
            +
                  #
         | 
| 56 | 
            +
                  # Key instances can be thought of as procs that map a value to the
         | 
| 57 | 
            +
                  # MongoDB query expression required to obtain the key's condition,
         | 
| 58 | 
            +
                  # given the value.
         | 
| 8 59 | 
             
                  class Key
         | 
| 9 60 |  | 
| 10 | 
            -
                    # @ | 
| 11 | 
            -
                     | 
| 12 | 
            -
             | 
| 13 | 
            -
                    # @ | 
| 14 | 
            -
                     | 
| 15 | 
            -
             | 
| 61 | 
            +
                    # @return [ String | Symbol ] The name of the field.
         | 
| 62 | 
            +
                    attr_reader :name
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    # @return [ String ] The MongoDB query operator.
         | 
| 65 | 
            +
                    attr_reader :operator
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    # @return [ String ] The MongoDB expanded query operator.
         | 
| 68 | 
            +
                    attr_reader :expanded
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                    # @return [ Symbol ] The name of the merge strategy.
         | 
| 71 | 
            +
                    attr_reader :strategy
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    # @return [ Proc ] The optional block to transform values.
         | 
| 74 | 
            +
                    attr_reader :block
         | 
| 16 75 |  | 
| 17 76 | 
             
                    # Does the key equal another object?
         | 
| 18 77 | 
             
                    #
         | 
| @@ -24,7 +24,7 @@ module Mongoid | |
| 24 24 | 
             
                    # @since 2.0.0
         | 
| 25 25 | 
             
                    POLYGON = "Polygon"
         | 
| 26 26 |  | 
| 27 | 
            -
                    # @attribute [rw] negating If the next  | 
| 27 | 
            +
                    # @attribute [rw] negating If the next expression is negated.
         | 
| 28 28 | 
             
                    # @attribute [rw] selector The query selector.
         | 
| 29 29 | 
             
                    attr_accessor :negating, :selector
         | 
| 30 30 |  | 
| @@ -21,9 +21,10 @@ module Mongoid | |
| 21 21 | 
             
                      other.each_pair do |key, value|
         | 
| 22 22 | 
             
                        if value.is_a?(Hash) && self[key.to_s].is_a?(Hash)
         | 
| 23 23 | 
             
                          value = self[key.to_s].merge(value) do |_key, old_val, new_val|
         | 
| 24 | 
            -
                             | 
| 24 | 
            +
                            case _key
         | 
| 25 | 
            +
                            when '$in'
         | 
| 25 26 | 
             
                              new_val & old_val
         | 
| 26 | 
            -
                             | 
| 27 | 
            +
                            when '$nin'
         | 
| 27 28 | 
             
                              (old_val + new_val).uniq
         | 
| 28 29 | 
             
                            else
         | 
| 29 30 | 
             
                              new_val
         | 
| @@ -52,10 +53,13 @@ module Mongoid | |
| 52 53 | 
             
                    def store(key, value)
         | 
| 53 54 | 
             
                      name, serializer = storage_pair(key)
         | 
| 54 55 | 
             
                      if multi_selection?(name)
         | 
| 55 | 
            -
                         | 
| 56 | 
            +
                        store_name = name
         | 
| 57 | 
            +
                        store_value = evolve_multi(value)
         | 
| 56 58 | 
             
                      else
         | 
| 57 | 
            -
                         | 
| 59 | 
            +
                        store_name = localized_key(name, serializer)
         | 
| 60 | 
            +
                        store_value = evolve(serializer, value)
         | 
| 58 61 | 
             
                      end
         | 
| 62 | 
            +
                      super(store_name, store_value)
         | 
| 59 63 | 
             
                    end
         | 
| 60 64 | 
             
                    alias :[]= :store
         | 
| 61 65 |  | 
| @@ -178,33 +182,7 @@ module Mongoid | |
| 178 182 | 
             
                    #
         | 
| 179 183 | 
             
                    # @since 1.0.0
         | 
| 180 184 | 
             
                    def multi_selection?(key)
         | 
| 181 | 
            -
                       | 
| 182 | 
            -
                    end
         | 
| 183 | 
            -
             | 
| 184 | 
            -
                    # Determines if the selection operator takes a list. Returns true for $in and $nin.
         | 
| 185 | 
            -
                    #
         | 
| 186 | 
            -
                    # @api private
         | 
| 187 | 
            -
                    #
         | 
| 188 | 
            -
                    # @example Does the selection operator take multiple values?
         | 
| 189 | 
            -
                    #   selector.multi_value?("$nin")
         | 
| 190 | 
            -
                    #
         | 
| 191 | 
            -
                    # @param [ String ] key The key to check.
         | 
| 192 | 
            -
                    #
         | 
| 193 | 
            -
                    # @return [ true, false ] If the key is $in or $nin.
         | 
| 194 | 
            -
                    #
         | 
| 195 | 
            -
                    # @since 2.1.1
         | 
| 196 | 
            -
                    def multi_value?(key)
         | 
| 197 | 
            -
                      key =~ /\$nin|\$in/
         | 
| 198 | 
            -
                    end
         | 
| 199 | 
            -
             | 
| 200 | 
            -
                    private
         | 
| 201 | 
            -
             | 
| 202 | 
            -
                    def in?(key)
         | 
| 203 | 
            -
                      key =~ /\$in/
         | 
| 204 | 
            -
                    end
         | 
| 205 | 
            -
             | 
| 206 | 
            -
                    def nin?(key)
         | 
| 207 | 
            -
                      key =~ /\$nin/
         | 
| 185 | 
            +
                      %w($and $or $nor).include?(key)
         | 
| 208 186 | 
             
                    end
         | 
| 209 187 | 
             
                  end
         | 
| 210 188 | 
             
                end
         | 
| @@ -69,7 +69,7 @@ module Mongoid | |
| 69 69 | 
             
                  #
         | 
| 70 70 | 
             
                  # @since 2.3.1
         | 
| 71 71 | 
             
                  def mongoid_id?
         | 
| 72 | 
            -
                    self =~ /\A(|_)id | 
| 72 | 
            +
                    self =~ /\A(|_)id\z/
         | 
| 73 73 | 
             
                  end
         | 
| 74 74 |  | 
| 75 75 | 
             
                  # Is the string a number? The literals "NaN", "Infinity", and "-Infinity"
         | 
| @@ -96,7 +96,7 @@ module Mongoid | |
| 96 96 | 
             
                  #
         | 
| 97 97 | 
             
                  # @since 1.0.0
         | 
| 98 98 | 
             
                  def reader
         | 
| 99 | 
            -
                    delete("=").sub(/\_before\_type\_cast | 
| 99 | 
            +
                    delete("=").sub(/\_before\_type\_cast\z/, '')
         | 
| 100 100 | 
             
                  end
         | 
| 101 101 |  | 
| 102 102 | 
             
                  # Is this string a writer?
         | 
    
        data/lib/mongoid/positional.rb
    CHANGED
    
    
    
        data/lib/mongoid/query_cache.rb
    CHANGED
    
    
| @@ -48,7 +48,7 @@ module Mongoid | |
| 48 48 | 
             
                  #     include Mongoid::Document
         | 
| 49 49 | 
             
                  #     field :title
         | 
| 50 50 | 
             
                  #
         | 
| 51 | 
            -
                  #     validates_format_of :title, with:  | 
| 51 | 
            +
                  #     validates_format_of :title, with: /\A[a-z0-9 \-_]*\z/i
         | 
| 52 52 | 
             
                  #   end
         | 
| 53 53 | 
             
                  #
         | 
| 54 54 | 
             
                  # @param [ Array ] args The names of the fields to validate.
         | 
    
        data/lib/mongoid/version.rb
    CHANGED
    
    
    
        data/spec/README.md
    ADDED
    
    | @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            # Running Mongoid Tests
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## Overview
         | 
| 4 | 
            +
            ### Quick Start
         | 
| 5 | 
            +
            Spin up a MongoDB deployment against which to run the Mongoid specs. Mongoid specs support a variety of MongoDB topologies, but the simplest is a single MongoDB instance:
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                # Launch mongod in one terminal
         | 
| 8 | 
            +
                mkdir /tmp/mdb
         | 
| 9 | 
            +
                mongod --dbpath /tmp/mdb
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            Run the test suite in a separate terminal:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                rake
         | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| 16 | 
            +
            ## Caveats
         | 
| 17 | 
            +
            ### "Too many open files" error
         | 
| 18 | 
            +
            On MacOS, you may encounter a "Too many open files" error on the MongoDB server when running the tests. If this happens, stop the server, run the command `ulimit -n 10000` in the same terminal session as the server, and restart the server. This will increase the number of files that can be opened. Then, re-run the tests.
         | 
| @@ -132,8 +132,8 @@ describe Mongoid::Clients::Factory do | |
| 132 132 |  | 
| 133 133 | 
             
                        let(:config) do
         | 
| 134 134 | 
             
                          {
         | 
| 135 | 
            -
                            default: { hosts: [ "127.0.0.1:1234" ], database: database_id },
         | 
| 136 | 
            -
                            secondary: { uri: "mongodb://127.0.0.1:1234,127.0.0.1:5678/mongoid_test" }
         | 
| 135 | 
            +
                            default: { hosts: [ "127.0.0.1:1234" ], database: database_id, server_selection_timeout: 1 },
         | 
| 136 | 
            +
                            secondary: { uri: "mongodb://127.0.0.1:1234,127.0.0.1:5678/mongoid_test?serverSelectionTimeoutMS=1000" }
         | 
| 137 137 | 
             
                          }
         | 
| 138 138 | 
             
                        end
         | 
| 139 139 |  | 
| @@ -16,17 +16,26 @@ describe Mongoid::Clients::Sessions do | |
| 16 16 | 
             
              end
         | 
| 17 17 |  | 
| 18 18 | 
             
              let(:subscriber) do
         | 
| 19 | 
            -
                Mongoid::Clients.with_name(:other) | 
| 19 | 
            +
                client = Mongoid::Clients.with_name(:other)
         | 
| 20 | 
            +
                monitoring = if client.respond_to?(:monitoring, true)
         | 
| 21 | 
            +
                  client.send(:monitoring)
         | 
| 22 | 
            +
                else
         | 
| 23 | 
            +
                  # driver 2.5
         | 
| 24 | 
            +
                  client.instance_variable_get('@monitoring')
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
                monitoring.subscribers['Command'].find do |s|
         | 
| 20 27 | 
             
                  s.is_a?(EventSubscriber)
         | 
| 21 28 | 
             
                end
         | 
| 22 29 | 
             
              end
         | 
| 23 30 |  | 
| 24 31 | 
             
              let(:insert_events) do
         | 
| 25 | 
            -
                 | 
| 32 | 
            +
                # Driver 2.5 sends command_name as a symbol
         | 
| 33 | 
            +
                subscriber.started_events.select { |event| event.command_name.to_s == 'insert' }
         | 
| 26 34 | 
             
              end
         | 
| 27 35 |  | 
| 28 36 | 
             
              let(:update_events) do
         | 
| 29 | 
            -
                 | 
| 37 | 
            +
                # Driver 2.5 sends command_name as a symbol
         | 
| 38 | 
            +
                subscriber.started_events.select { |event| event.command_name.to_s == 'update' }
         | 
| 30 39 | 
             
              end
         | 
| 31 40 |  | 
| 32 41 | 
             
              context 'when a session is used on a model class' do
         | 
| @@ -1,18 +1,27 @@ | |
| 1 1 | 
             
            require "spec_helper"
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe Mongoid::Clients::Sessions do
         | 
| 4 | 
            +
              before(:all) do
         | 
| 5 | 
            +
                unless Mongo::VERSION >= '2.6'
         | 
| 6 | 
            +
                  skip 'Driver does not support transactions'
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
              end
         | 
| 4 9 |  | 
| 5 10 | 
             
              before(:all) do
         | 
| 6 | 
            -
                 | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            +
                if Mongo::VERSION >= '2.6'
         | 
| 12 | 
            +
                  CONFIG[:clients][:other] = CONFIG[:clients][:default].dup
         | 
| 13 | 
            +
                  CONFIG[:clients][:other][:database] = 'other'
         | 
| 14 | 
            +
                  Mongoid::Clients.clients.values.each(&:close)
         | 
| 15 | 
            +
                  Mongoid::Config.send(:clients=, CONFIG[:clients])
         | 
| 16 | 
            +
                  Mongoid::Clients.with_name(:other).subscribe(Mongo::Monitoring::COMMAND, EventSubscriber.new)
         | 
| 17 | 
            +
                end
         | 
| 11 18 | 
             
              end
         | 
| 12 19 |  | 
| 13 20 | 
             
              after(:all) do
         | 
| 14 | 
            -
                 | 
| 15 | 
            -
             | 
| 21 | 
            +
                if Mongo::VERSION >= '2.6'
         | 
| 22 | 
            +
                  Mongoid::Clients.with_name(:other).close
         | 
| 23 | 
            +
                  Mongoid::Clients.clients.delete(:other)
         | 
| 24 | 
            +
                end
         | 
| 16 25 | 
             
              end
         | 
| 17 26 |  | 
| 18 27 | 
             
              let(:subscriber) do
         | 
| @@ -1643,11 +1643,15 @@ describe Mongoid::Criteria::Modifiable do | |
| 1643 1643 | 
             
                    { 'username' => 'Turnip' }
         | 
| 1644 1644 | 
             
                  end
         | 
| 1645 1645 |  | 
| 1646 | 
            -
                  it ' | 
| 1647 | 
            -
                    expect(Person.create_with(attrs).selector).to  | 
| 1646 | 
            +
                  it 'does not modify the selector' do
         | 
| 1647 | 
            +
                    expect(Person.create_with(attrs).selector[:username]).to be_nil
         | 
| 1648 1648 | 
             
                  end
         | 
| 1649 1649 |  | 
| 1650 | 
            -
                   | 
| 1650 | 
            +
                  it 'create_attrs is modified' do
         | 
| 1651 | 
            +
                    expect(Person.create_with(attrs).create_attrs).to eq(attrs)
         | 
| 1652 | 
            +
                  end
         | 
| 1653 | 
            +
             | 
| 1654 | 
            +
                  context 'when a create is chained' do
         | 
| 1651 1655 |  | 
| 1652 1656 | 
             
                    context 'when a write method is chained' do
         | 
| 1653 1657 |  | 
| @@ -1671,6 +1675,25 @@ describe Mongoid::Criteria::Modifiable do | |
| 1671 1675 | 
             
                        expect(new_person.age).to eq(50)
         | 
| 1672 1676 | 
             
                      end
         | 
| 1673 1677 |  | 
| 1678 | 
            +
                      context 'when a matching document is already in the collection' do
         | 
| 1679 | 
            +
                        let(:query) do
         | 
| 1680 | 
            +
                          { 'username' => 'foo', 'age' => 12 }
         | 
| 1681 | 
            +
                        end
         | 
| 1682 | 
            +
             | 
| 1683 | 
            +
                        let(:person) do
         | 
| 1684 | 
            +
                          Person.create!(query)
         | 
| 1685 | 
            +
                        end
         | 
| 1686 | 
            +
             | 
| 1687 | 
            +
                        let(:found_person) do
         | 
| 1688 | 
            +
                          Person.create_with(attrs).find_or_create_by(query)
         | 
| 1689 | 
            +
                        end
         | 
| 1690 | 
            +
             | 
| 1691 | 
            +
                        it 'finds the matching document' do
         | 
| 1692 | 
            +
                          person
         | 
| 1693 | 
            +
                          expect(found_person.id).to eq(person.id)
         | 
| 1694 | 
            +
                        end
         | 
| 1695 | 
            +
                      end
         | 
| 1696 | 
            +
             | 
| 1674 1697 | 
             
                      context 'when the attributes are shared with the write method args' do
         | 
| 1675 1698 |  | 
| 1676 1699 | 
             
                        let(:query) do
         | 
| @@ -1681,7 +1704,7 @@ describe Mongoid::Criteria::Modifiable do | |
| 1681 1704 | 
             
                          Person.create_with(attrs).find_or_create_by(query)
         | 
| 1682 1705 | 
             
                        end
         | 
| 1683 1706 |  | 
| 1684 | 
            -
                        it 'gives the  | 
| 1707 | 
            +
                        it 'gives the find method args precedence' do
         | 
| 1685 1708 | 
             
                          expect(new_person.username).to eq('Beet')
         | 
| 1686 1709 | 
             
                          expect(new_person.age).to eq(50)
         | 
| 1687 1710 | 
             
                        end
         | 
| @@ -1708,8 +1731,12 @@ describe Mongoid::Criteria::Modifiable do | |
| 1708 1731 | 
             
                        { 'username' => 'Beet', 'age' => 50 }
         | 
| 1709 1732 | 
             
                      end
         | 
| 1710 1733 |  | 
| 1734 | 
            +
                      it 'does not modify the selector' do
         | 
| 1735 | 
            +
                        expect(criteria.create_with(attrs).selector).to eq(criteria_selector)
         | 
| 1736 | 
            +
                      end
         | 
| 1737 | 
            +
             | 
| 1711 1738 | 
             
                      it 'overwrites all the original attributes' do
         | 
| 1712 | 
            -
                        expect(criteria.create_with(attrs). | 
| 1739 | 
            +
                        expect(criteria.create_with(attrs).create_attrs).to eq(attrs)
         | 
| 1713 1740 | 
             
                      end
         | 
| 1714 1741 | 
             
                    end
         | 
| 1715 1742 | 
             
                  end
         | 
| @@ -1720,8 +1747,12 @@ describe Mongoid::Criteria::Modifiable do | |
| 1720 1747 | 
             
                      { 'username' => 'Beet' }
         | 
| 1721 1748 | 
             
                    end
         | 
| 1722 1749 |  | 
| 1750 | 
            +
                    it 'does not modify the selector' do
         | 
| 1751 | 
            +
                      expect(criteria.create_with(attrs).selector).to eq(criteria_selector)
         | 
| 1752 | 
            +
                    end
         | 
| 1753 | 
            +
             | 
| 1723 1754 | 
             
                    it 'only overwrites the shared attributes' do
         | 
| 1724 | 
            -
                      expect(criteria.create_with(attrs). | 
| 1755 | 
            +
                      expect(criteria.create_with(attrs).create_attrs).to eq(attrs)
         | 
| 1725 1756 | 
             
                    end
         | 
| 1726 1757 | 
             
                  end
         | 
| 1727 1758 |  | 
| @@ -1730,12 +1761,11 @@ describe Mongoid::Criteria::Modifiable do | |
| 1730 1761 | 
             
                    let(:attrs) do
         | 
| 1731 1762 | 
             
                      { 'username' => 'Turnip' }
         | 
| 1732 1763 | 
             
                    end
         | 
| 1733 | 
            -
             | 
| 1734 1764 | 
             
                    let(:query) do
         | 
| 1735 1765 | 
             
                      { 'username' => 'Beet', 'age' => 50 }
         | 
| 1736 1766 | 
             
                    end
         | 
| 1737 1767 |  | 
| 1738 | 
            -
                    context 'when a  | 
| 1768 | 
            +
                    context 'when a create method is chained' do
         | 
| 1739 1769 |  | 
| 1740 1770 | 
             
                      it 'executes the method' do
         | 
| 1741 1771 | 
             
                        expect(criteria.create_with(attrs).new.username).to eq('Turnip')
         | 
| @@ -1749,9 +1779,28 @@ describe Mongoid::Criteria::Modifiable do | |
| 1749 1779 | 
             
                        criteria.create_with(attrs).find_or_create_by(query)
         | 
| 1750 1780 | 
             
                      end
         | 
| 1751 1781 |  | 
| 1752 | 
            -
                      it ' | 
| 1782 | 
            +
                      it 'gives the find method arg precedence' do
         | 
| 1753 1783 | 
             
                        expect(new_person.username).to eq('Beet')
         | 
| 1754 | 
            -
                        expect(new_person.age).to  | 
| 1784 | 
            +
                        expect(new_person.age).to be(50)
         | 
| 1785 | 
            +
                      end
         | 
| 1786 | 
            +
             | 
| 1787 | 
            +
                      context 'when a matching document is already in the collection' do
         | 
| 1788 | 
            +
                        let(:query) do
         | 
| 1789 | 
            +
                          { 'username' => 'foo', 'age' => 12 }
         | 
| 1790 | 
            +
                        end
         | 
| 1791 | 
            +
             | 
| 1792 | 
            +
                        let(:person) do
         | 
| 1793 | 
            +
                          Person.create!(query)
         | 
| 1794 | 
            +
                        end
         | 
| 1795 | 
            +
             | 
| 1796 | 
            +
                        let(:found_person) do
         | 
| 1797 | 
            +
                          criteria.create_with(attrs).find_or_create_by(query)
         | 
| 1798 | 
            +
                        end
         | 
| 1799 | 
            +
             | 
| 1800 | 
            +
                        it 'finds the matching document' do
         | 
| 1801 | 
            +
                          person
         | 
| 1802 | 
            +
                          expect(found_person.id).to eq(person.id)
         | 
| 1803 | 
            +
                        end
         | 
| 1755 1804 | 
             
                      end
         | 
| 1756 1805 | 
             
                    end
         | 
| 1757 1806 | 
             
                  end
         |