Mongoid v4.0.0 Release Notes

  • Major Changes (Backwards Incompatible)

    • ๐Ÿšš #3320 Remove Rails dependencies on database rake tasks. (Arthur Neves)

      All db:* rake tasks should work as before when using Rails. When not in a Rails, just load the database tasks using:

      load 'mongoid/tasks/database.rake'
      
    • ๐Ÿ‘ Mongoid 4 now only supports MongoDB 2.4.0 and higher.

    • ๐Ÿ“‡ Document#metadata has been renamed to Document#relation_metadata to avoid common conflicts. Relation proxies also have this renamed to the same as well.

    • 0๏ธโƒฃ Scopes and default scopes must now all be defined within lambdas or procs.

    • ๐Ÿ”– skip_version_check config option was removed.

    • ๐Ÿšš IdentityMap removed. (Arthur Neves)

    • Eager load rework. Eager load now doesnt need the identity map to load related documents. A set of preloaders can eager load the associations passed to .includes method. (Arthur Neves)

    • ๐Ÿ‘ Mongoid now supports the new read preferences that the core drivers provide. These include:

      • :primary: Will always read from a primary node. (default)
      • :primary_preferred: Attempt a primary first, then secondary if none available.
      • :secondary: Will always read from a secondary node.
      • :secondary_preferred: Attempt a secondary first, then primary if none available.
      • :nearest: Attempt to read from the node with the lowest latency.

      Sample syntax:

      Person.with(read: :secondary).first
      

      The :consistency option is no longer valid, use the :read option now.

    • 0๏ธโƒฃ Mongoid now defaults all writes to propagate (formerly "safe mode") and now has different propagate semantics:

      • { w: -1 }: Don't verify writes and raise no network errors.
      • { w: 0 }: Don't verify writes and raise network errors.
      • { w: 1 }: Verify writes on the primary node. (default)
      • { w: n }: Verify writes on n number of nodes.
      • { w: "majority" }: Verify writes on a majority of nodes.

      Sample syntax:

      Person.with(write: {w: :majority}).create!(name: "John")
      

      The :safe option is no longer valid use the :write option now.

    • #3230 Array and Hash fields now validate that the correct types are getting set, instead of allowing any value. (Rodrigo Saito)

    • #3043/#2949 Rework on the internals of persistence options. (Arthur Neves)

    • Mongoid now requires Active Model 4 or higher.

    • Document#set now accepts multiple attributes in the form of a hash, instead of the previous (field, value) args. Field aliases and typecasting are also now supported in this operation.

      document.set(name: "Photek", likes: 10000)
      
    • Document#rename now accepts multiple attributes in the form of a hash, instead of the previous (field, value) args. Field aliases are supported.

      document.rename(first_name: "fn", last_name: "ln")
      
    • Document#inc now accepts multiple attributes in the form of a hash, instead of previously only being able to increment one value at a time. Aliases and serialization is supported.

      document.inc(score: 10, place: -1, lives: -10)
      
    • Document#pop now accepts multiple attributes in the form of a hash, instead of previously only being able to pop one value at a time. Aliases and serialization is supported.

      document.pop(names: 1, aliases: -1)
      
    • Document#bit now accepts multiple attributes in the form of a hash, instead of previously only being able to apply one set of operations at a time. Aliases and serialization are supported.

      document.bit(age: { and: 13 }, score: { or: 13 })
      
    • Document#pull now accepts multiple attributes in the form of a hash, instead of previously only being able to pull one value at a time. Aliases and serialization is supported.

      document.pull(names: "James", aliases: "007")
      
    • Document#pull_all now accepts multiple attributes in the form of a hash, instead of previously only being able to pull one value at a time. Aliases and serialization is supported.

      document.pull_all(names: ["James", "Bond"], aliases: ["007"])
      
    • ๐Ÿšš Document#push_all has been removed since it was deprecated in MongoDB 2.4. Use Document.push instead.

    • Document#push now accepts multiple attributes in the form of a hash, and can handle the pushing of single values or multiple values to the field via $push with $each. Aliases and serialization is supported.

      document.push(names: "James", aliases: [ "007", "Jim" ])
      
    • Document#add_to_set now accepts multiple attributes in the form of a hash, and now aliases and serialization are supported.

      document.add_to_set(names: "James", aliases: "007")
      
    • Criteria atomic operations API is now changed to match the changes in the single document atomic API, for example:

      Band.where(name: "Depeche Mode").inc(likes: 10, followers: 20)
      
    • #3399 #create and #create! on relations can now take an array of attributes as the first parameter to create multiple documents at once.

      person.addresses.create([{ street: "Bond" }, { street: "Upper" }])
      person.addresses.create!([{ street: "Bond" }, { street: "Upper" }])
      
    • โœ… #3141 rake db:test:prepare now sets up all defined indexes if Mongoid is the only ODM/ORM in the environment.

    • โšก๏ธ #3138 update_attributes can now be accessed simply by calling update.

    • #3083 A new rake task: rake db:mongoid:remove_undefined_indexes has been added to remove indexes from the database that are not explicitly defined in the models. (Aidan Feldman)

    • #3029 The relation_field field that is added for a single use case with polymorphic relations has been removed. So where the following would work before:

      class Eye
        include Mongoid::Document
        belongs_to :eyeable, polymorphic: true
      end
      
      class Face
        include Mongoid::Document
        has_one :left_eye, class_name: "Eye", as: :eyeable
        has_one :right_eye, class_name: "Eye", as: :eyeable
      end
      

      This would now need to be modeled as (with the appropriate migration):

      class Eye
        include Mongoid::Document
        belongs_to :left_socket, class_name: "Face", inverse_of: :left_eye
        belongs_to :right_socket, class_name: "Face", inverse_of: :right_eye
      end
      
      class Face
        include Mongoid::Document
        has_one :left_eye, class_name: "Eye", inverse_of: :left_socket
        has_one :right_eye, class_name: "Eye", inverse_of: :right_socket
      end
      
    • โšก๏ธ #3075 update_attribute now properly calls the setter method instead of using write_attribute.

    • #3060 Allow atomically blocks to allow multiple calls of the same type. (Brian Norton)

    • #3037 Model indexes are no longer stored in an index_options hash on the model class. Instead, an array named index_specifications now exists on the class which contains a list of Indexable::Specification objects. This is so we could properly handle the case of indexes with the same keys but different order.

    • #2956 Caching on queries now only happens when cache is specifically called. (Arthur Neves)

    • #2659 Mongoid::Railtie now properly uses only one initializer and the name has changed to mongoid.load-config.

    • ๐Ÿ‘€ #2656 rake db:reseed is now rake db:reset (Arthur Neves)

    • #2648 Boolean becomes Mongoid::Boolean to avoid polluting the global namespace with a commonly used class by other libraries.

    • #2603 Return values from setters are now always the set value, regardless of calling the setter or using send.

    • ๐Ÿšš #2597 Mongoid::Observer was removed in line with Rails 4.

    • #2563 The allow_dynamic_fields configuration option has been removed as dynamic fields are now allowed on a per-model level. In order to allow a model to use dynamic fields, simply include the module in each. (Josh Martin)

      class Band
        include Mongoid::Document
        include Mongoid::Attributes::Dynamic
      end
      
    • #2497 Calling to_json no longer tampers with the return value from the driver, and proper returns { "$oid" : object_id.to_s } instead of just the string representation previously.

    • ๐Ÿšš #2433 Mongoid::Paranoia has been removed.

    • ๐Ÿšš #2432 Mongoid::Versioning has been removed.

    • 0๏ธโƒฃ #2218 Creating or instantiating documents that have default scopes will now apply the default scope to the document, if the scope is not complex.

    • ๐Ÿ”’ #2200 Mass assignment security now mirrors Rails 4's behavior. without_protection option was also removed. attr_accessible class method was removed. Mongoid and Strong parameters should work fine for mass assignment protection.

    • delete_all and destroy_all no longer take a :conditions hash but just the raw attributes.

    • #1908 Documents now loaded from criteria using #only or #without will now raise an error when attempting to save, update, or delete these records. Additionally fields excluded from the fields retrieved from the database will also raise an exception when trying to access them.

    • โšก๏ธ #1344 Atomic updates can now be executed in an atomically block, which will delay any atomic updates on the document the block was called on until the block is complete.

      Update calls can be executed as normal in the block:

      document.atomically do
        document.inc(likes: 10)
        document.bit(members: { and: 10 })
        document.set(name: "Photek")
      end
      

      The document is also yielded to the block:

      document.atomically do |doc|
        doc.inc(likes: 10)
        doc.bit(members: { and: 10 })
        doc.set(name: "Photek")
      end
      

      The atomic commands are have a fluid interface:

      document.atomically do |doc|
        doc.inc(likes: 10).bit(members: { and: 10 }).set(name: "Photek")
      end
      

      If the fluid interface is leveraged without the atomically block, the operations will persist in individual calls. For example, the following would hit the database 3 times without the block provided:

      doc.inc(likes: 10).bit(members: { and: 10 }).set(name: "Photek")
      

      The block is only good for 1 document at a time, so embedded and root document updates cannot be mixed at this time.

    ๐Ÿ†• New Features

    • ๐Ÿ”Š Mongoid now uses ActiveSupport::LogSubscriber to subscribe logs, and ActiveSupport::Notifications to send operation logs. (Arthur Neves) Example of log subscription:

      ActiveSupport::Notifications.subscribe('query.moped') do |event| .. end

    • ๐Ÿ‘€ Field types can now use symbols as well as class names. See: https://github.com/mongoid/mongoid/blob/master/lib/mongoid/fields.rb#L16 for the available mappings.

    • 0๏ธโƒฃ #3580 Fields can now be reset to their default values, with the methods:

      document.reset_name_to_default!

    • #3513 Documents now have a #destroy! method that will raise a Mongoid::Errors::DocumentNotDestroyed error if a destroy callback returns a false value.

    • #3496 Added class level and criteria level find_or_create_by!.

    • โฑ #3479 Map/reduce now respects criteria no timeout options if output is not inline.

    • #3478 Criteria objects now have a #none method that will cause the criteria to never hit the database and always have zero documents.

      Band.none Band.none.where(name: "Tool") # Always has zero documents.

    • #3410 Mongoid now has a query cache that can be used as a middleware in Rack applications. (Arthur Neves)

      For Rails:

      config.middleware.use(Mongoid::QueryCache::Middleware)

    • #3319 Counters can now be reset from a document instance:

      document.reset_counters(:relation)

    • โšก๏ธ #3310 embedded_in relations now accept a touch option to update parents.

    • #3302 Aliasing using alias_attribute now properly handles aliases in criteria.

    • #3155 Range field will persist the exclude_end when provided. (Daniel Libanori)

    • #3146 Adding :overwrite field option, when it`s true, it wont check duplicates. (Daniel Libanori)

    • ๐Ÿš… #3002 Reloading the Rails console will also now clear Mongoid's identity map.

    • #2938 A configuration option duplicate_fields_exception has been added that when set to true will raise an exception when defining a field that will override an existing method. (Arthur Neves)

    • #2924 MongoDB 2.4 beta text search now has a DSL provided by Mongoid. Like other queries, text searches are lazy evaluated, and available off the class or criteria level.

      Note that any 3rd party gem that provides a text_search method will now no longer work with Mongoid, and will need to change its syntax. Examples:

      Band.text_search("mode").project(name: 1).each do |doc|
        # ...
      end
      
      Band.limit(10).text_search("phase").language("latin")
      Band.where(:likes.gt => 1000).text_search("lucy")
      
    • #2855 Multiple extensions can now be supplied to relations. (Daniel Libanori)

    Resolved Issues

    • #3676 Make pluck work with embedded associations (Arthur Neves)

    • #2898 Dirty attribute methods now properly handle field aliases. (Niels Ganser)

    • #3620 Add ActiveModel module instance methods to prohibited_methods list. (Arthur Neves)

    • #3610 Don't allow atomic operations on read-only attributes (Frederico Araujo)

    • #3619 Don't validate documents that are flagged for destruction. (Christopher J. Bottaro)

    • #3617 Don't skip index creation on cyclic documents. (shaiker)

    • ๐Ÿ›  #3568 Fixed missing attributes error on present localized fields.

    • ๐Ÿ›  #3514 Fixed query cache to work on first/last calls.

    • #3383/#3495 Fix has_and_belongs_to_many eager load. (Arthur Neves)

    • #3492 $rename operations should not mongoize values. (Vladislav Melanitskiy)

    • #3490 Allow localized fields to work with boolean false values.

    • #3487 Map Boolean to Mongoid::Boolean in field definitions. (Arthur Neves)

    • โšก๏ธ #3449 Touch needs to work for create and update. (Greggory Rothmeier)

    • #3347 Creating documents off of scopes for embedded relations now properly sets the parent document on the created children.

    • ๐Ÿ›  #3432 Fixed mongoization of DateTime losing precision.

    • ๐Ÿ›  #3397 Fixed $ne matcher for embedded documents to match server behavior.

    • #3352 Allow named scopes named "open" to work through 1-n relations.

    • #3348 Fixing compounded indexes having the same keys with different directions. (Arthur Neves)

    • #2701 Fixing extra query on belongs_to binding. (Arthur Neves)

    • #3089 Allow demongoization of strings to floats (Daniel Libanori)

    • โšก๏ธ #3278 Counter cache should update the document in memory too. (Arthur Neves)

    • #3242 Has_many relation must use the inverse foreign_key. (Arthur Neves)

    • #3233 Don't double call validation callbacks when cascading children and relation validation is turned on.

    • #3197 Improvements in the calls to aggregates on root and embedded collections. (Wojciech Piekutowski)

    • #3144/#3219 Fixing name colission on @_children ivar. (Arthur Neves)

    • #3088 Range field can accept a hash, which could be the attribute from the db. (Daniel Libanori)

    • ๐Ÿ›  #3116 Relations instance variables are now all prefixed with _.

    • #3093 Only flatten 1 level when atomically pushing arrays.

    • #3063 Document#becomes now properly sets base object on errors. (Adam Ross Cohen)

    • #3019 Atomic operations will no longer attempt to persist if the document is not persisted.

    • ๐Ÿšš #2903 Removed unused string to_a extension.