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.
Files changed (43) hide show
  1. data/lib/mongoid.rb +10 -2
  2. data/lib/mongoid/associations.rb +82 -58
  3. data/lib/mongoid/associations/embeds_one.rb +6 -6
  4. data/lib/mongoid/associations/foreign_key.rb +35 -0
  5. data/lib/mongoid/associations/meta_data.rb +9 -0
  6. data/lib/mongoid/associations/options.rb +1 -1
  7. data/lib/mongoid/associations/proxy.rb +9 -0
  8. data/lib/mongoid/associations/{belongs_to_related.rb → referenced_in.rb} +6 -5
  9. data/lib/mongoid/associations/{has_many_related.rb → references_many.rb} +69 -26
  10. data/lib/mongoid/associations/references_many_as_array.rb +78 -0
  11. data/lib/mongoid/associations/{has_one_related.rb → references_one.rb} +16 -2
  12. data/lib/mongoid/atomicity.rb +42 -0
  13. data/lib/mongoid/attributes.rb +148 -146
  14. data/lib/mongoid/callbacks.rb +5 -1
  15. data/lib/mongoid/collections.rb +31 -1
  16. data/lib/mongoid/components.rb +4 -1
  17. data/lib/mongoid/config.rb +2 -1
  18. data/lib/mongoid/criteria.rb +9 -0
  19. data/lib/mongoid/dirty.rb +211 -212
  20. data/lib/mongoid/document.rb +126 -185
  21. data/lib/mongoid/extensions.rb +5 -0
  22. data/lib/mongoid/extensions/array/conversions.rb +3 -5
  23. data/lib/mongoid/extensions/hash/conversions.rb +19 -22
  24. data/lib/mongoid/extensions/object/conversions.rb +3 -5
  25. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  26. data/lib/mongoid/field.rb +11 -0
  27. data/lib/mongoid/finders.rb +8 -0
  28. data/lib/mongoid/hierarchy.rb +76 -0
  29. data/lib/mongoid/identity.rb +37 -29
  30. data/lib/mongoid/paths.rb +46 -47
  31. data/lib/mongoid/persistence.rb +111 -113
  32. data/lib/mongoid/persistence/insert.rb +1 -1
  33. data/lib/mongoid/persistence/insert_embedded.rb +10 -5
  34. data/lib/mongoid/persistence/remove_all.rb +3 -2
  35. data/lib/mongoid/persistence/update.rb +8 -3
  36. data/lib/mongoid/railtie.rb +3 -0
  37. data/lib/mongoid/railties/database.rake +33 -18
  38. data/lib/mongoid/timestamps.rb +9 -12
  39. data/lib/mongoid/validations/uniqueness.rb +16 -4
  40. data/lib/mongoid/version.rb +1 -1
  41. data/lib/mongoid/versioning.rb +10 -11
  42. data/lib/rails/generators/mongoid/config/config_generator.rb +0 -16
  43. metadata +64 -24
@@ -11,7 +11,11 @@ module Mongoid #:nodoc:
11
11
  :destroy,
12
12
  :save,
13
13
  :update,
14
- :validate
14
+ :validation
15
+ end
16
+
17
+ def valid?(*) #nodoc
18
+ _run_validation_callbacks { super }
15
19
  end
16
20
  end
17
21
  end
@@ -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
- delegate :collection, :to => "self.class"
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:
@@ -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
@@ -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
@@ -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
- # 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
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
- # 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
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
- # 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
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
- # 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
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
- # 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
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
- # 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
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
- # 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
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
- # 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
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
- # 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)
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
- # 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 ||= {}
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
- # 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
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
- protected
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
- # 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
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
- # 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
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
- # 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 ]
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