mongoid 2.0.0.beta.5 → 2.0.0.beta.7
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.
- data/lib/mongoid.rb +10 -2
- data/lib/mongoid/associations.rb +82 -58
- data/lib/mongoid/associations/embeds_one.rb +6 -6
- data/lib/mongoid/associations/foreign_key.rb +35 -0
- data/lib/mongoid/associations/meta_data.rb +9 -0
- data/lib/mongoid/associations/options.rb +1 -1
- data/lib/mongoid/associations/proxy.rb +9 -0
- data/lib/mongoid/associations/{belongs_to_related.rb → referenced_in.rb} +6 -5
- data/lib/mongoid/associations/{has_many_related.rb → references_many.rb} +69 -26
- data/lib/mongoid/associations/references_many_as_array.rb +78 -0
- data/lib/mongoid/associations/{has_one_related.rb → references_one.rb} +16 -2
- data/lib/mongoid/atomicity.rb +42 -0
- data/lib/mongoid/attributes.rb +148 -146
- data/lib/mongoid/callbacks.rb +5 -1
- data/lib/mongoid/collections.rb +31 -1
- data/lib/mongoid/components.rb +4 -1
- data/lib/mongoid/config.rb +2 -1
- data/lib/mongoid/criteria.rb +9 -0
- data/lib/mongoid/dirty.rb +211 -212
- data/lib/mongoid/document.rb +126 -185
- data/lib/mongoid/extensions.rb +5 -0
- data/lib/mongoid/extensions/array/conversions.rb +3 -5
- data/lib/mongoid/extensions/hash/conversions.rb +19 -22
- data/lib/mongoid/extensions/object/conversions.rb +3 -5
- data/lib/mongoid/extensions/set/conversions.rb +20 -0
- data/lib/mongoid/field.rb +11 -0
- data/lib/mongoid/finders.rb +8 -0
- data/lib/mongoid/hierarchy.rb +76 -0
- data/lib/mongoid/identity.rb +37 -29
- data/lib/mongoid/paths.rb +46 -47
- data/lib/mongoid/persistence.rb +111 -113
- data/lib/mongoid/persistence/insert.rb +1 -1
- data/lib/mongoid/persistence/insert_embedded.rb +10 -5
- data/lib/mongoid/persistence/remove_all.rb +3 -2
- data/lib/mongoid/persistence/update.rb +8 -3
- data/lib/mongoid/railtie.rb +3 -0
- data/lib/mongoid/railties/database.rake +33 -18
- data/lib/mongoid/timestamps.rb +9 -12
- data/lib/mongoid/validations/uniqueness.rb +16 -4
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +10 -11
- data/lib/rails/generators/mongoid/config/config_generator.rb +0 -16
- metadata +64 -24
    
        data/lib/mongoid/callbacks.rb
    CHANGED
    
    
    
        data/lib/mongoid/collections.rb
    CHANGED
    
    | @@ -7,7 +7,8 @@ module Mongoid #:nodoc | |
| 7 7 | 
             
                included do
         | 
| 8 8 | 
             
                  cattr_accessor :_collection, :collection_name
         | 
| 9 9 | 
             
                  self.collection_name = self.name.collectionize
         | 
| 10 | 
            -
             | 
| 10 | 
            +
             | 
| 11 | 
            +
                  delegate :collection, :db, :to => "self.class"
         | 
| 11 12 | 
             
                end
         | 
| 12 13 |  | 
| 13 14 | 
             
                module ClassMethods #:nodoc:
         | 
| @@ -22,6 +23,35 @@ module Mongoid #:nodoc | |
| 22 23 | 
             
                    add_indexes; self._collection
         | 
| 23 24 | 
             
                  end
         | 
| 24 25 |  | 
| 26 | 
            +
                  # Return the database associated with this collection.
         | 
| 27 | 
            +
                  #
         | 
| 28 | 
            +
                  # Example:
         | 
| 29 | 
            +
                  #
         | 
| 30 | 
            +
                  # <tt>Person.db</tt>
         | 
| 31 | 
            +
                  def db
         | 
| 32 | 
            +
                    collection.db
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  # Convenience method for getting index information from the collection.
         | 
| 36 | 
            +
                  #
         | 
| 37 | 
            +
                  # Example:
         | 
| 38 | 
            +
                  #
         | 
| 39 | 
            +
                  # <tt>Person.index_information</tt>
         | 
| 40 | 
            +
                  def index_information
         | 
| 41 | 
            +
                    collection.index_information
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  # The MongoDB logger is not exposed through the driver to be changed
         | 
| 45 | 
            +
                  # after initialization of the connection, this is a hacky way around that
         | 
| 46 | 
            +
                  # if logging needs to be changed at runtime.
         | 
| 47 | 
            +
                  #
         | 
| 48 | 
            +
                  # Example:
         | 
| 49 | 
            +
                  #
         | 
| 50 | 
            +
                  # <tt>Person.logger = Logger.new($stdout)</tt>
         | 
| 51 | 
            +
                  def logger=(logger)
         | 
| 52 | 
            +
                    db.connection.instance_variable_set(:@logger, logger)
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 25 55 | 
             
                  # Macro for setting the collection name to store in.
         | 
| 26 56 | 
             
                  #
         | 
| 27 57 | 
             
                  # Example:
         | 
    
        data/lib/mongoid/components.rb
    CHANGED
    
    | @@ -9,13 +9,15 @@ module Mongoid #:nodoc | |
| 9 9 | 
             
                  include ActiveModel::Naming
         | 
| 10 10 | 
             
                  include ActiveModel::Serialization
         | 
| 11 11 | 
             
                  include ActiveModel::Serializers::JSON
         | 
| 12 | 
            +
                  include ActiveModel::Serializers::Xml
         | 
| 12 13 | 
             
                  include Mongoid::Associations
         | 
| 14 | 
            +
                  include Mongoid::Atomicity
         | 
| 13 15 | 
             
                  include Mongoid::Attributes
         | 
| 14 | 
            -
                  include Mongoid::Callbacks
         | 
| 15 16 | 
             
                  include Mongoid::Collections
         | 
| 16 17 | 
             
                  include Mongoid::Dirty
         | 
| 17 18 | 
             
                  include Mongoid::Extras
         | 
| 18 19 | 
             
                  include Mongoid::Fields
         | 
| 20 | 
            +
                  include Mongoid::Hierarchy
         | 
| 19 21 | 
             
                  include Mongoid::Indexes
         | 
| 20 22 | 
             
                  include Mongoid::Matchers
         | 
| 21 23 | 
             
                  include Mongoid::Memoization
         | 
| @@ -24,6 +26,7 @@ module Mongoid #:nodoc | |
| 24 26 | 
             
                  include Mongoid::Persistence
         | 
| 25 27 | 
             
                  include Mongoid::State
         | 
| 26 28 | 
             
                  include Mongoid::Validations
         | 
| 29 | 
            +
                  include Mongoid::Callbacks
         | 
| 27 30 | 
             
                  extend ActiveModel::Translation
         | 
| 28 31 | 
             
                  extend Mongoid::Finders
         | 
| 29 32 | 
             
                  extend Mongoid::NamedScope
         | 
    
        data/lib/mongoid/config.rb
    CHANGED
    
    | @@ -193,10 +193,11 @@ module Mongoid #:nodoc | |
| 193 193 | 
             
                  name = settings["database"] || mongo_uri.path.to_s.sub("/", "")
         | 
| 194 194 | 
             
                  host = settings["host"] || mongo_uri.host || "localhost"
         | 
| 195 195 | 
             
                  port = settings["port"] || mongo_uri.port || 27017
         | 
| 196 | 
            +
                  pool_size = settings["pool_size"] || 1 
         | 
| 196 197 | 
             
                  username = settings["username"] || mongo_uri.user
         | 
| 197 198 | 
             
                  password = settings["password"] || mongo_uri.password
         | 
| 198 199 |  | 
| 199 | 
            -
                  connection = Mongo::Connection.new(host, port, :logger => logger)
         | 
| 200 | 
            +
                  connection = Mongo::Connection.new(host, port, :logger => logger, :pool_size => pool_size)
         | 
| 200 201 | 
             
                  if username || password
         | 
| 201 202 | 
             
                    connection.add_auth(name, username, password)
         | 
| 202 203 | 
             
                    connection.apply_saved_authentication
         | 
    
        data/lib/mongoid/criteria.rb
    CHANGED
    
    | @@ -82,6 +82,15 @@ module Mongoid #:nodoc: | |
| 82 82 | 
             
                  self
         | 
| 83 83 | 
             
                end
         | 
| 84 84 |  | 
| 85 | 
            +
                # Return true if the criteria has some Document or not
         | 
| 86 | 
            +
                #
         | 
| 87 | 
            +
                # Example:
         | 
| 88 | 
            +
                #
         | 
| 89 | 
            +
                # <tt>criteria.exists?</tt>
         | 
| 90 | 
            +
                def exists?
         | 
| 91 | 
            +
                  context.count > 0
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 85 94 | 
             
                # Merges the supplied argument hash into a single criteria
         | 
| 86 95 | 
             
                #
         | 
| 87 96 | 
             
                # Options:
         | 
    
        data/lib/mongoid/dirty.rb
    CHANGED
    
    | @@ -2,231 +2,230 @@ | |
| 2 2 | 
             
            module Mongoid #:nodoc:
         | 
| 3 3 | 
             
              module Dirty #:nodoc:
         | 
| 4 4 | 
             
                extend ActiveSupport::Concern
         | 
| 5 | 
            -
                module InstanceMethods #:nodoc:
         | 
| 6 | 
            -
                  # Gets the changes for a specific field.
         | 
| 7 | 
            -
                  #
         | 
| 8 | 
            -
                  # Example:
         | 
| 9 | 
            -
                  #
         | 
| 10 | 
            -
                  #   person = Person.new(:title => "Sir")
         | 
| 11 | 
            -
                  #   person.title = "Madam"
         | 
| 12 | 
            -
                  #   person.attribute_change("title") # [ "Sir", "Madam" ]
         | 
| 13 | 
            -
                  #
         | 
| 14 | 
            -
                  # Returns:
         | 
| 15 | 
            -
                  #
         | 
| 16 | 
            -
                  # An +Array+ containing the old and new values.
         | 
| 17 | 
            -
                  def attribute_change(name)
         | 
| 18 | 
            -
                    modifications[name]
         | 
| 19 | 
            -
                  end
         | 
| 20 5 |  | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 6 | 
            +
                # Gets the changes for a specific field.
         | 
| 7 | 
            +
                #
         | 
| 8 | 
            +
                # Example:
         | 
| 9 | 
            +
                #
         | 
| 10 | 
            +
                #   person = Person.new(:title => "Sir")
         | 
| 11 | 
            +
                #   person.title = "Madam"
         | 
| 12 | 
            +
                #   person.attribute_change("title") # [ "Sir", "Madam" ]
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                # Returns:
         | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                # An +Array+ containing the old and new values.
         | 
| 17 | 
            +
                def attribute_change(name)
         | 
| 18 | 
            +
                  modifications[name]
         | 
| 19 | 
            +
                end
         | 
| 35 20 |  | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
                  end
         | 
| 21 | 
            +
                # Determines if a specific field has chaged.
         | 
| 22 | 
            +
                #
         | 
| 23 | 
            +
                # Example:
         | 
| 24 | 
            +
                #
         | 
| 25 | 
            +
                #   person = Person.new(:title => "Sir")
         | 
| 26 | 
            +
                #   person.title = "Madam"
         | 
| 27 | 
            +
                #   person.attribute_changed?("title") # true
         | 
| 28 | 
            +
                #
         | 
| 29 | 
            +
                # Returns:
         | 
| 30 | 
            +
                #
         | 
| 31 | 
            +
                # +true+ if changed, +false+ if not.
         | 
| 32 | 
            +
                def attribute_changed?(name)
         | 
| 33 | 
            +
                  modifications.include?(name)
         | 
| 34 | 
            +
                end
         | 
| 51 35 |  | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
                   | 
| 36 | 
            +
                # Gets the old value for a specific field.
         | 
| 37 | 
            +
                #
         | 
| 38 | 
            +
                # Example:
         | 
| 39 | 
            +
                #
         | 
| 40 | 
            +
                #   person = Person.new(:title => "Sir")
         | 
| 41 | 
            +
                #   person.title = "Madam"
         | 
| 42 | 
            +
                #   person.attribute_was("title") # "Sir"
         | 
| 43 | 
            +
                #
         | 
| 44 | 
            +
                # Returns:
         | 
| 45 | 
            +
                #
         | 
| 46 | 
            +
                # The old field value.
         | 
| 47 | 
            +
                def attribute_was(name)
         | 
| 48 | 
            +
                  change = modifications[name]
         | 
| 49 | 
            +
                  change ? change[0] : nil
         | 
| 50 | 
            +
                end
         | 
| 66 51 |  | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 52 | 
            +
                # Gets the names of all the fields that have changed in the document.
         | 
| 53 | 
            +
                #
         | 
| 54 | 
            +
                # Example:
         | 
| 55 | 
            +
                #
         | 
| 56 | 
            +
                #   person = Person.new(:title => "Sir")
         | 
| 57 | 
            +
                #   person.title = "Madam"
         | 
| 58 | 
            +
                #   person.changed # returns [ "title" ]
         | 
| 59 | 
            +
                #
         | 
| 60 | 
            +
                # Returns:
         | 
| 61 | 
            +
                #
         | 
| 62 | 
            +
                # An +Array+ of changed field names.
         | 
| 63 | 
            +
                def changed
         | 
| 64 | 
            +
                  modifications.keys
         | 
| 65 | 
            +
                end
         | 
| 81 66 |  | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
                   | 
| 95 | 
            -
             | 
| 96 | 
            -
                    modifications
         | 
| 97 | 
            -
                  end
         | 
| 67 | 
            +
                # Alerts to whether the document has been modified or not.
         | 
| 68 | 
            +
                #
         | 
| 69 | 
            +
                # Example:
         | 
| 70 | 
            +
                #
         | 
| 71 | 
            +
                #   person = Person.new(:title => "Sir")
         | 
| 72 | 
            +
                #   person.title = "Madam"
         | 
| 73 | 
            +
                #   person.changed? # returns true
         | 
| 74 | 
            +
                #
         | 
| 75 | 
            +
                # Returns:
         | 
| 76 | 
            +
                #
         | 
| 77 | 
            +
                # +true+ if changed, +false+ if not.
         | 
| 78 | 
            +
                def changed?
         | 
| 79 | 
            +
                  !modifications.empty?
         | 
| 80 | 
            +
                end
         | 
| 98 81 |  | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 82 | 
            +
                # Gets all the modifications that have happened to the object as a +Hash+
         | 
| 83 | 
            +
                # with the keys being the names of the fields, and the values being an
         | 
| 84 | 
            +
                # +Array+ with the old value and new value.
         | 
| 85 | 
            +
                #
         | 
| 86 | 
            +
                # Example:
         | 
| 87 | 
            +
                #
         | 
| 88 | 
            +
                #   person = Person.new(:title => "Sir")
         | 
| 89 | 
            +
                #   person.title = "Madam"
         | 
| 90 | 
            +
                #   person.changes # returns { "title" => [ "Sir", "Madam" ] }
         | 
| 91 | 
            +
                #
         | 
| 92 | 
            +
                # Returns:
         | 
| 93 | 
            +
                #
         | 
| 94 | 
            +
                # A +Hash+ of changes.
         | 
| 95 | 
            +
                def changes
         | 
| 96 | 
            +
                  modifications
         | 
| 97 | 
            +
                end
         | 
| 108 98 |  | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
                   | 
| 116 | 
            -
                   | 
| 117 | 
            -
             | 
| 118 | 
            -
                  # Returns:
         | 
| 119 | 
            -
                  #
         | 
| 120 | 
            -
                  # A +Hash+ of new values.
         | 
| 121 | 
            -
                  def setters
         | 
| 122 | 
            -
                    modifications.inject({}) do |sets, (field, changes)|
         | 
| 123 | 
            -
                      key = embedded? ? "#{_position}.#{field}" : field
         | 
| 124 | 
            -
                      sets[key] = changes[1]; sets
         | 
| 125 | 
            -
                    end
         | 
| 126 | 
            -
                  end
         | 
| 99 | 
            +
                # Call this method after save, so the changes can be properly switched.
         | 
| 100 | 
            +
                #
         | 
| 101 | 
            +
                # Example:
         | 
| 102 | 
            +
                #
         | 
| 103 | 
            +
                # <tt>person.move_changes</tt>
         | 
| 104 | 
            +
                def move_changes
         | 
| 105 | 
            +
                  @previous_modifications = modifications.dup
         | 
| 106 | 
            +
                  @modifications = {}
         | 
| 107 | 
            +
                end
         | 
| 127 108 |  | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
                   | 
| 142 | 
            -
                     | 
| 109 | 
            +
                # Gets all the new values for each of the changed fields, to be passed to
         | 
| 110 | 
            +
                # a MongoDB $set modifier.
         | 
| 111 | 
            +
                #
         | 
| 112 | 
            +
                # Example:
         | 
| 113 | 
            +
                #
         | 
| 114 | 
            +
                #   person = Person.new(:title => "Sir")
         | 
| 115 | 
            +
                #   person.title = "Madam"
         | 
| 116 | 
            +
                #   person.setters # returns { "title" => "Madam" }
         | 
| 117 | 
            +
                #
         | 
| 118 | 
            +
                # Returns:
         | 
| 119 | 
            +
                #
         | 
| 120 | 
            +
                # A +Hash+ of new values.
         | 
| 121 | 
            +
                def setters
         | 
| 122 | 
            +
                  modifications.inject({}) do |sets, (field, changes)|
         | 
| 123 | 
            +
                    key = embedded? ? "#{_position}.#{field}" : field
         | 
| 124 | 
            +
                    sets[key] = changes[1]; sets
         | 
| 143 125 | 
             
                  end
         | 
| 126 | 
            +
                end
         | 
| 144 127 |  | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 161 | 
            -
                      modifications.delete(name)
         | 
| 162 | 
            -
                    end
         | 
| 163 | 
            -
                  end
         | 
| 128 | 
            +
                # Gets all the modifications that have happened to the object before the
         | 
| 129 | 
            +
                # object was saved.
         | 
| 130 | 
            +
                #
         | 
| 131 | 
            +
                # Example:
         | 
| 132 | 
            +
                #
         | 
| 133 | 
            +
                #   person = Person.new(:title => "Sir")
         | 
| 134 | 
            +
                #   person.title = "Madam"
         | 
| 135 | 
            +
                #   person.save!
         | 
| 136 | 
            +
                #   person.previous_changes # returns { "title" => [ "Sir", "Madam" ] }
         | 
| 137 | 
            +
                #
         | 
| 138 | 
            +
                # Returns:
         | 
| 139 | 
            +
                #
         | 
| 140 | 
            +
                # A +Hash+ of changes before save.
         | 
| 141 | 
            +
                def previous_changes
         | 
| 142 | 
            +
                  @previous_modifications
         | 
| 143 | 
            +
                end
         | 
| 164 144 |  | 
| 165 | 
            -
             | 
| 166 | 
            -
             | 
| 167 | 
            -
             | 
| 168 | 
            -
             | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 145 | 
            +
                # Resets a changed field back to its old value.
         | 
| 146 | 
            +
                #
         | 
| 147 | 
            +
                # Example:
         | 
| 148 | 
            +
                #
         | 
| 149 | 
            +
                #   person = Person.new(:title => "Sir")
         | 
| 150 | 
            +
                #   person.title = "Madam"
         | 
| 151 | 
            +
                #   person.reset_attribute!("title")
         | 
| 152 | 
            +
                #   person.title # "Sir"
         | 
| 153 | 
            +
                #
         | 
| 154 | 
            +
                # Returns:
         | 
| 155 | 
            +
                #
         | 
| 156 | 
            +
                # The old field value.
         | 
| 157 | 
            +
                def reset_attribute!(name)
         | 
| 158 | 
            +
                  value = attribute_was(name)
         | 
| 159 | 
            +
                  if value
         | 
| 160 | 
            +
                    @attributes[name] = value
         | 
| 161 | 
            +
                    modifications.delete(name)
         | 
| 175 162 | 
             
                  end
         | 
| 163 | 
            +
                end
         | 
| 176 164 |  | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
             | 
| 185 | 
            -
             | 
| 186 | 
            -
                   | 
| 165 | 
            +
                # Sets up the modifications hash. This occurs just after the document is
         | 
| 166 | 
            +
                # instantiated.
         | 
| 167 | 
            +
                #
         | 
| 168 | 
            +
                # Example:
         | 
| 169 | 
            +
                #
         | 
| 170 | 
            +
                # <tt>document.setup_notifications</tt>
         | 
| 171 | 
            +
                def setup_modifications
         | 
| 172 | 
            +
                  @accessed ||= {}
         | 
| 173 | 
            +
                  @modifications ||= {}
         | 
| 174 | 
            +
                  @previous_modifications ||= {}
         | 
| 175 | 
            +
                end
         | 
| 187 176 |  | 
| 188 | 
            -
             | 
| 177 | 
            +
                # Reset all modifications for the document. This will wipe all the marked
         | 
| 178 | 
            +
                # changes, but not reset the values.
         | 
| 179 | 
            +
                #
         | 
| 180 | 
            +
                # Example:
         | 
| 181 | 
            +
                #
         | 
| 182 | 
            +
                # <tt>document.reset_modifications</tt>
         | 
| 183 | 
            +
                def reset_modifications
         | 
| 184 | 
            +
                  @accessed = {}
         | 
| 185 | 
            +
                  @modifications = {}
         | 
| 186 | 
            +
                end
         | 
| 189 187 |  | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
                   | 
| 188 | 
            +
                protected
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                # Audit the original value for a field that can be modified in place.
         | 
| 191 | 
            +
                #
         | 
| 192 | 
            +
                # Example:
         | 
| 193 | 
            +
                #
         | 
| 194 | 
            +
                # <tt>person.accessed("aliases", [ "007" ])</tt>
         | 
| 195 | 
            +
                def accessed(name, value)
         | 
| 196 | 
            +
                  @accessed ||= {}
         | 
| 197 | 
            +
                  @accessed[name] = value.dup if (value.is_a?(Array) || value.is_a?(Hash)) && !@accessed.has_key?(name)
         | 
| 198 | 
            +
                  value
         | 
| 199 | 
            +
                end
         | 
| 200 200 |  | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 214 | 
            -
             | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 201 | 
            +
                # Get all normal modifications plus in place potential changes.
         | 
| 202 | 
            +
                #
         | 
| 203 | 
            +
                # Example:
         | 
| 204 | 
            +
                #
         | 
| 205 | 
            +
                # <tt>person.modifications</tt>
         | 
| 206 | 
            +
                #
         | 
| 207 | 
            +
                # Returns:
         | 
| 208 | 
            +
                #
         | 
| 209 | 
            +
                # All changes to the document.
         | 
| 210 | 
            +
                def modifications
         | 
| 211 | 
            +
                  @accessed.each_pair do |field, value|
         | 
| 212 | 
            +
                    current = @attributes[field]
         | 
| 213 | 
            +
                    @modifications[field] = [ value, current ] if current != value
         | 
| 214 | 
            +
                  end
         | 
| 215 | 
            +
                  @accessed.clear
         | 
| 216 | 
            +
                  @modifications
         | 
| 217 | 
            +
                end
         | 
| 218 218 |  | 
| 219 | 
            -
             | 
| 220 | 
            -
             | 
| 221 | 
            -
             | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
                    end
         | 
| 219 | 
            +
                # Audit the change of a field's value.
         | 
| 220 | 
            +
                #
         | 
| 221 | 
            +
                # Example:
         | 
| 222 | 
            +
                #
         | 
| 223 | 
            +
                # <tt>person.modify("name", "Jack", "John")</tt>
         | 
| 224 | 
            +
                def modify(name, old_value, new_value)
         | 
| 225 | 
            +
                  @attributes[name] = new_value
         | 
| 226 | 
            +
                  if @modifications && (old_value != new_value)
         | 
| 227 | 
            +
                    original = @modifications[name].first if @modifications[name]
         | 
| 228 | 
            +
                    @modifications[name] = [ (original || old_value), new_value ]
         | 
| 230 229 | 
             
                  end
         | 
| 231 230 | 
             
                end
         | 
| 232 231 |  | 
| @@ -243,10 +242,10 @@ module Mongoid #:nodoc: | |
| 243 242 | 
             
                  #   person.title_was # "Sir"
         | 
| 244 243 | 
             
                  #   person.reset_title!
         | 
| 245 244 | 
             
                  def add_dirty_methods(name)
         | 
| 246 | 
            -
                    define_method("#{name}_change") { attribute_change(name) }
         | 
| 247 | 
            -
                    define_method("#{name}_changed?") { attribute_changed?(name) }
         | 
| 248 | 
            -
                    define_method("#{name}_was") { attribute_was(name) }
         | 
| 249 | 
            -
                    define_method("reset_#{name}!") { reset_attribute!(name) }
         | 
| 245 | 
            +
                    define_method("#{name}_change") { attribute_change(name) } unless instance_methods.include?("#{name}_change")
         | 
| 246 | 
            +
                    define_method("#{name}_changed?") { attribute_changed?(name) } unless instance_methods.include?("#{name}_changed?")
         | 
| 247 | 
            +
                    define_method("#{name}_was") { attribute_was(name) } unless instance_methods.include?("#{name}_was")
         | 
| 248 | 
            +
                    define_method("reset_#{name}!") { reset_attribute!(name) } unless instance_methods.include?("reset_#{name}!")
         | 
| 250 249 | 
             
                  end
         | 
| 251 250 | 
             
                end
         | 
| 252 251 | 
             
              end
         |