mongoid 4.0.0 → 4.0.2

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +48 -1
  3. data/README.md +6 -2
  4. data/lib/config/locales/en.yml +2 -2
  5. data/lib/mongoid/atomic.rb +2 -2
  6. data/lib/mongoid/attributes.rb +2 -0
  7. data/lib/mongoid/contextual/aggregable/memory.rb +2 -2
  8. data/lib/mongoid/contextual/memory.rb +5 -5
  9. data/lib/mongoid/contextual/mongo.rb +13 -3
  10. data/lib/mongoid/criteria/#findable.rb# +141 -0
  11. data/lib/mongoid/document.rb +7 -7
  12. data/lib/mongoid/extensions.rb +13 -0
  13. data/lib/mongoid/findable.rb +27 -5
  14. data/lib/mongoid/persistable/creatable.rb +2 -1
  15. data/lib/mongoid/persistable/settable.rb +1 -1
  16. data/lib/mongoid/persistable/updatable.rb +2 -1
  17. data/lib/mongoid/query_cache.rb +10 -2
  18. data/lib/mongoid/railtie.rb +2 -15
  19. data/lib/mongoid/railties/database.rake +1 -1
  20. data/lib/mongoid/relations/accessors.rb +2 -2
  21. data/lib/mongoid/relations/binding.rb +1 -1
  22. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +1 -1
  23. data/lib/mongoid/relations/builders/embedded/one.rb +1 -1
  24. data/lib/mongoid/relations/builders/nested_attributes/one.rb +1 -1
  25. data/lib/mongoid/relations/counter_cache.rb +2 -2
  26. data/lib/mongoid/relations/many.rb +21 -0
  27. data/lib/mongoid/relations/one.rb +1 -1
  28. data/lib/mongoid/relations/referenced/many.rb +4 -4
  29. data/lib/mongoid/relations/referenced/many_to_many.rb +5 -5
  30. data/lib/mongoid/relations/synchronization.rb +4 -4
  31. data/lib/mongoid/relations/targets/enumerable.rb +10 -10
  32. data/lib/mongoid/reloadable.rb +3 -3
  33. data/lib/mongoid/sessions/options.rb +7 -2
  34. data/lib/mongoid/threaded.rb +26 -15
  35. data/lib/mongoid/traversable.rb +6 -2
  36. data/lib/mongoid/validatable/uniqueness.rb +3 -3
  37. data/lib/mongoid/version.rb +1 -1
  38. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +33 -1
  39. data/spec/app/models/contextable_item.rb +5 -0
  40. data/spec/app/models/id_key.rb +6 -0
  41. data/spec/mongoid/#atomic_spec.rb# +365 -0
  42. data/spec/mongoid/attributes/nested_spec.rb +139 -144
  43. data/spec/mongoid/attributes_spec.rb +36 -0
  44. data/spec/mongoid/contextual/atomic_spec.rb +7 -13
  45. data/spec/mongoid/contextual/memory_spec.rb +7 -2
  46. data/spec/mongoid/criteria/modifiable_spec.rb +5 -8
  47. data/spec/mongoid/criteria_spec.rb +86 -75
  48. data/spec/mongoid/document_spec.rb +9 -5
  49. data/spec/mongoid/extensions_spec.rb +14 -0
  50. data/spec/mongoid/findable_spec.rb +99 -11
  51. data/spec/mongoid/persistable/creatable_spec.rb +41 -0
  52. data/spec/mongoid/persistable/savable_spec.rb +37 -0
  53. data/spec/mongoid/persistable/settable_spec.rb +23 -0
  54. data/spec/mongoid/positional_spec.rb +5 -10
  55. data/spec/mongoid/query_cache_spec.rb +32 -0
  56. data/spec/mongoid/relations/embedded/many_spec.rb +74 -0
  57. data/spec/mongoid/relations/referenced/many_spec.rb +153 -0
  58. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +49 -0
  59. data/spec/mongoid/reloadable_spec.rb +23 -0
  60. data/spec/mongoid/sessions/options_spec.rb +2 -1
  61. data/spec/mongoid/sessions_spec.rb +30 -0
  62. data/spec/spec_helper.rb +2 -0
  63. metadata +10 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f25ce5318d49b1e171f4e6fa2d4067eb933ecf0d
4
- data.tar.gz: 94846f4aff6c2ba1ccf34a63789b7503e536611b
3
+ metadata.gz: a5340f453822e7cbecd2710795296c23db607d92
4
+ data.tar.gz: 0adcfd1449d91980fb45bb60aa336e661b1482f9
5
5
  SHA512:
6
- metadata.gz: 96e54337599c2679fcb56acc7c817b1d119730f40d58eda3b0c8d2d4d66867c5c92ff6c475ce770ac52230fe8666ee29a1ecc81be1e8801a13359708bef76caf
7
- data.tar.gz: 693af581fa3e7c64cf8014a9ca3a4eb1c90baddfcb26c5162d1bd842da149092ad8c1d7ec34d5d4c45f9b58c739431e8f0a3a7794346798cb1cb469e08aa16d5
6
+ metadata.gz: 9b1733f089831c0b58049cb486a8c13687f16a0845d2d9eb2acfb8c5aa0c99de3bbe3a81d6ab0bae0be9c8e4493c77864d64626b341565b5be8f7d695fb93acc
7
+ data.tar.gz: 1c7a4d343e583880595366b2f4afcb58a8d0f763c8a3bc5f04cea4134d1fb947f420d3ce7cb9b070902a0fd50cd03e71c1c4188c7f349a0e591774435b6a9908
data/CHANGELOG.md CHANGED
@@ -3,6 +3,53 @@
3
3
  For instructions on upgrading to newer versions, visit
4
4
  [mongoid.org](http://mongoid.org/en/mongoid/docs/upgrading.html).
5
5
 
6
+ ## 4.0.3 - Not released
7
+
8
+ ## 4.0.2
9
+
10
+ ### New Features
11
+
12
+ * \#3931 Add #find_or_create_by! method to many associations. (Tom Beynon)
13
+
14
+ * \#3731 Add find_by! method. (Guillermo Iguaran)
15
+
16
+ ### Resolved Issues
17
+
18
+ * \#3722 Use the right database name when combining #store_in and #with. (Arthur Neves)
19
+
20
+ * \#3934 Dont apply sort when doing a find_by. (Arthur Neves)
21
+
22
+ * \#3935 fix multiple fields sorting on contextual memory. (chamnap)
23
+
24
+ * \#3904 BSON::Document#symbolize_keys should return keys as symbols. (Arthur Neves)
25
+
26
+ * \#3948 Fix remove_undefined_indexes on rails 4.2, to symbolize right the Document keys. (Adam Wróbel)
27
+
28
+ * \#3626 Document#to_key, needs to return a ObjectId as String so we can query back using that id. (Arthur Neves)
29
+
30
+ * \#3888 raise UnknownAttributeError when 'set' is called on non existing field and Mongoid::Attributes::Dynamic is not included in model. (Shweta Kale)
31
+
32
+ * \#3889 'set' will allow to set value of non existing field when Mongoid::Attributes::Dynamic is included in model. (Shweta Kale)
33
+
34
+ * \#3812 Fixed validation context when saving (Yaroslav Zemlyanuhin)
35
+
36
+ ## 4.0.1
37
+
38
+ ### Resolved Issues
39
+
40
+ * \#3911 Fix relations named "parent". (nkriege)
41
+
42
+ * \#3792/\#3881 Fix many internal calls to #_id instead of #id to avoid issues
43
+ when overloading #id (Gauthier Delacroix)
44
+
45
+ * \#3847 Fix 'QueryCache#get_more' result, when collection has more documents than first query batch. (Angelica Korsun)
46
+
47
+ * \#3684 Dont raise MissingAttributeError, when using a only() scope. (Arthur Neves)
48
+
49
+ * \#3703 pluck method should not compact the values. (Arthur Neves)
50
+
51
+ * \#3773 Use nanoseconds for cache_key timestamp instead of plain seconds. (Máximo Mussini)
52
+
6
53
  ## 4.0.0
7
54
 
8
55
  ### Major Changes (Backwards Incompatible)
@@ -138,7 +185,7 @@ For instructions on upgrading to newer versions, visit
138
185
 
139
186
  * \#3138 `update_attributes` can now be accessed simply by calling `update`.
140
187
 
141
- * \#3083 A new rake task: `rake mongoid:remove_undefined_indexes` has been added to
188
+ * \#3083 A new rake task: `rake db:mongoid:remove_undefined_indexes` has been added to
142
189
  remove indexes from the database that are not explicitly defined in the models.
143
190
  (Aidan Feldman)
144
191
 
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
- Mongoid [![Build Status](https://travis-ci.org/mongoid/mongoid.svg)](https://travis-ci.org/mongoid/mongoid) [![Code Climate](https://codeclimate.com/github/mongoid/mongoid.png)](https://codeclimate.com/github/mongoid/mongoid) [![Coverage Status](https://coveralls.io/repos/mongoid/mongoid/badge.png?branch=master)](https://coveralls.io/r/mongoid/mongoid?branch=master) [![Gem Version](https://badge.fury.io/rb/mongoid.png)](http://badge.fury.io/rb/mongoid) [![Dependency Status](https://www.versioneye.com/ruby/mongoid/3.1.6/badge.png)](https://www.versioneye.com/ruby/mongoid/3.1.6)
2
- ========
1
+ # Mongoid
2
+ [![Build Status](https://travis-ci.org/mongoid/mongoid.svg?branch=master)](https://travis-ci.org/mongoid/mongoid)
3
+ [![Code Climate](https://codeclimate.com/github/mongoid/mongoid.svg)](https://codeclimate.com/github/mongoid/mongoid)
4
+ [![Coverage Status](https://img.shields.io/coveralls/mongoid/mongoid/master.svg)](https://coveralls.io/r/mongoid/mongoid?branch=master)
5
+ [![Dependency Status](https://www.versioneye.com/ruby/mongoid/4.0.0/badge.svg)](https://www.versioneye.com/ruby/mongoid/4.0.0)
6
+
3
7
 
4
8
  Mongoid is an ODM (Object-Document-Mapper) framework for MongoDB in Ruby.
5
9
 
@@ -19,7 +19,7 @@ en:
19
19
  message: "Calling %{method} on %{klass} resulted in a false return
20
20
  from a callback."
21
21
  summary: "If a before callback returns false when using Document.create!,
22
- Document#save!, or Documnet#update_attributes! this error will get raised
22
+ Document#save!, or Document#update_attributes! this error will get raised
23
23
  since the document did not actually get saved."
24
24
  resolution: "Double check all before callbacks to make sure they are
25
25
  not unintentionally returning false."
@@ -336,7 +336,7 @@ en:
336
336
  %{klass}.create! without setting the parent document as an
337
337
  attribute."
338
338
  resolution: "Ensure that you've set the parent relation if
339
- instantiating the embedded document direcly, or always create new
339
+ instantiating the embedded document directly, or always create new
340
340
  embedded documents via the parent relation."
341
341
  no_session_config:
342
342
  message: "No configuration could be found for a session named
@@ -125,7 +125,7 @@ module Mongoid
125
125
  # @return [ Hash ] The updates and their modifiers.
126
126
  #
127
127
  # @since 2.1.0
128
- def atomic_updates(use_indexes = false)
128
+ def atomic_updates(_use_indexes = false)
129
129
  process_flagged_destroys
130
130
  mods = Modifiers.new
131
131
  generate_atomic_updates(mods, self)
@@ -206,7 +206,7 @@ module Mongoid
206
206
  path = nil
207
207
  ids = docs.map do |doc|
208
208
  path ||= doc.flag_as_destroyed
209
- doc.id
209
+ doc._id
210
210
  end
211
211
  pulls[path] = { "_id" => { "$in" => ids }} and path = nil
212
212
  end
@@ -31,6 +31,8 @@ module Mongoid
31
31
  def attribute_present?(name)
32
32
  attribute = read_attribute(name)
33
33
  !attribute.blank? || attribute == false
34
+ rescue ActiveModel::MissingAttributeError
35
+ false
34
36
  end
35
37
 
36
38
  # Get the attributes that have not been cast.
@@ -81,7 +81,7 @@ module Mongoid
81
81
  if block_given?
82
82
  super()
83
83
  else
84
- count > 0 ? super(0) { |doc| doc.send(field) } : 0
84
+ count > 0 ? super(0) { |doc| doc.public_send(field) } : 0
85
85
  end
86
86
  end
87
87
 
@@ -101,7 +101,7 @@ module Mongoid
101
101
  #
102
102
  # @since 3.0.0
103
103
  def aggregate_by(field, method)
104
- count > 0 ? send(method) { |doc| doc.send(field) }.send(field) : nil
104
+ count > 0 ? send(method) { |doc| doc.public_send(field) }.public_send(field) : nil
105
105
  end
106
106
  end
107
107
  end
@@ -135,6 +135,7 @@ module Mongoid
135
135
  doc
136
136
  end
137
137
  alias :one :first
138
+ alias :find_first :first
138
139
 
139
140
  # Create the new in memory context.
140
141
  #
@@ -421,12 +422,11 @@ module Mongoid
421
422
  #
422
423
  # @since 3.0.0
423
424
  def in_place_sort(values)
424
- values.keys.reverse.each do |field|
425
- documents.sort! do |a, b|
425
+ documents.sort! do |a, b|
426
+ values.map do |field, direction|
426
427
  a_value, b_value = a[field], b[field]
427
- value = compare(a_value.__sortable__, b_value.__sortable__)
428
- values[field] < 0 ? value * -1 : value
429
- end
428
+ direction * compare(a_value.__sortable__, b_value.__sortable__)
429
+ end.find { |value| !value.zero? } || 0
430
430
  end
431
431
  end
432
432
 
@@ -54,7 +54,7 @@ module Mongoid
54
54
  def count(document = false, &block)
55
55
  return super(&block) if block_given?
56
56
  if document.is_a?(Document)
57
- return collection.find(criteria.and(_id: document.id).selector).count
57
+ return collection.find(criteria.and(_id: document._id).selector).count
58
58
  end
59
59
  return query.count(document) if document
60
60
  try_cache(:count) { query.count }
@@ -202,6 +202,16 @@ module Mongoid
202
202
  end
203
203
  alias :one :first
204
204
 
205
+ # Return the first result without applying sort
206
+ #
207
+ # @api private
208
+ #
209
+ # @since 4.0.2
210
+ def find_first
211
+ return documents.first if cached? && cache_loaded?
212
+ with_eager_loading(query.first)
213
+ end
214
+
205
215
  # Execute a $geoNear command against the database.
206
216
  #
207
217
  # @example Find documents close to 10, 10.
@@ -350,9 +360,9 @@ module Mongoid
350
360
  if normalized_select.size == 1
351
361
  doc[normalized_select.keys.first]
352
362
  else
353
- normalized_select.keys.map { |n| doc[n] }.compact
363
+ normalized_select.keys.map { |n| doc[n] }
354
364
  end
355
- end.compact
365
+ end
356
366
  end
357
367
 
358
368
  # Skips the provided number of documents.
@@ -0,0 +1,141 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+ module Findable
5
+
6
+ # Execute the criteria or raise an error if no documents found.
7
+ #
8
+ # @example Execute or raise
9
+ # criteria.execute_or_raise(id)
10
+ #
11
+ # @param [ Object ] args The arguments passed.
12
+ #
13
+ # @raise [ Errors::DocumentNotFound ] If nothing returned.
14
+ #
15
+ # @return [ Document, Array<Document> ] The document(s).
16
+ #
17
+ # @since 2.0.0
18
+ def execute_or_raise(ids, multi)
19
+ result = multiple_from_db(ids)
20
+ check_for_missing_documents!(result, ids)
21
+ multi ? result : result.first
22
+ end
23
+
24
+ # Find the matchind document(s) in the criteria for the provided ids.
25
+ #
26
+ # @example Find by an id.
27
+ # criteria.find(BSON::ObjectId.new)
28
+ #
29
+ # @example Find by multiple ids.
30
+ # criteria.find([ BSON::ObjectId.new, BSON::ObjectId.new ])
31
+ #
32
+ # @param [ Array<BSON::ObjectId> ] args The ids to search for.
33
+ #
34
+ # @return [ Array<Document>, Document ] The matching document(s).
35
+ #
36
+ # @since 1.0.0
37
+ def find(*args)
38
+ ids = args.__find_args__
39
+ raise_invalid if ids.any?(&:nil?)
40
+ p "YOOO"
41
+ p ids
42
+ for_ids(ids).execute_or_raise(ids, args.multi_arged?)
43
+ end
44
+
45
+ # Adds a criterion to the +Criteria+ that specifies an id that must be matched.
46
+ #
47
+ # @example Add a single id criteria.
48
+ # criteria.for_ids([ 1 ])
49
+ #
50
+ # @example Add multiple id criteria.
51
+ # criteria.for_ids([ 1, 2 ])
52
+ #
53
+ # @param [ Array ] ids The array of ids.
54
+ #
55
+ # @return [ Criteria ] The cloned criteria.
56
+ def for_ids(ids)
57
+ ids = mongoize_ids(ids)
58
+ if ids.size > 1
59
+ send(id_finder, { _id: { "$in" => ids }})
60
+ else
61
+ send(id_finder, { _id: ids.first })
62
+ end
63
+ end
64
+
65
+ # Get the documents from the identity map, and if not found hit the
66
+ # database.
67
+ #
68
+ # @example Get the documents from the map or criteria.
69
+ # criteria.multiple_from_map_or_db(ids)
70
+ #
71
+ # @param [ ids ] The searched ids.
72
+ #
73
+ # @return [ Array<Document> ] The found documents.
74
+ def multiple_from_db(ids)
75
+ return entries if embedded?
76
+ ids = mongoize_ids(ids)
77
+ ids.empty? ? [] : from_database(ids)
78
+ end
79
+
80
+ private
81
+
82
+ # Get the finder used to generate the id query.
83
+ #
84
+ # @api private
85
+ #
86
+ # @example Get the id finder.
87
+ # criteria.id_finder
88
+ #
89
+ # @return [ Symbol ] The name of the finder method.
90
+ #
91
+ # @since 3.1.0
92
+ def id_finder
93
+ @id_finder ||= extract_id ? :all_of : :where
94
+ end
95
+
96
+ # Get documents from the database only.
97
+ #
98
+ # @api private
99
+ #
100
+ # @example Get documents from the database.
101
+ # criteria.from_database(ids)
102
+ #
103
+ # @param [ Array<Object> ] ids The ids to fetch with.
104
+ #
105
+ # @return [ Array<Document> ] The matching documents.
106
+ #
107
+ # @since 3.0.0
108
+ def from_database(ids)
109
+ (ids.size > 1 ? any_in(id: ids) : where(id: ids.first)).entries
110
+ end
111
+
112
+ # Convert all the ids to their proper types.
113
+ #
114
+ # @api private
115
+ #
116
+ # @example Convert the ids.
117
+ # criteria.mongoize_ids(ids)
118
+ #
119
+ # @param [ Array<Object> ] ids The ids to convert.
120
+ #
121
+ # @return [ Array<Object> ] The converted ids.
122
+ #
123
+ # @since 3.0.0
124
+ def mongoize_ids(ids)
125
+ ids.map{ |id| klass.fields["_id"].mongoize(id) }
126
+ end
127
+
128
+ # Convenience method of raising an invalid options error.
129
+ #
130
+ # @example Raise the error.
131
+ # criteria.raise_invalid
132
+ #
133
+ # @raise [ Errors::InvalidOptions ] The error.
134
+ #
135
+ # @since 2.0.0
136
+ def raise_invalid
137
+ raise Errors::InvalidFind.new
138
+ end
139
+ end
140
+ end
141
+ end
@@ -78,11 +78,11 @@ module Mongoid
78
78
  # @example Get the identity
79
79
  # document.identity
80
80
  #
81
- # @return [ Array ] An array containing [document.class, document.id]
81
+ # @return [ Array ] An array containing [document.class, document._id]
82
82
  #
83
83
  # @since 3.0.0
84
84
  def identity
85
- [ self.class, self.id ]
85
+ [ self.class, self._id ]
86
86
  end
87
87
 
88
88
  # Instantiate a new +Document+, setting the Document's attributes if
@@ -134,11 +134,11 @@ module Mongoid
134
134
  # @example Return the key.
135
135
  # document.to_key
136
136
  #
137
- # @return [ Object ] The id of the document or nil if new.
137
+ # @return [ String ] The id of the document or nil if new.
138
138
  #
139
139
  # @since 2.4.0
140
140
  def to_key
141
- (persisted? || destroyed?) ? [ id ] : nil
141
+ (persisted? || destroyed?) ? [ id.to_s ] : nil
142
142
  end
143
143
 
144
144
  # Return an array with this +Document+ only in it.
@@ -199,7 +199,7 @@ module Mongoid
199
199
  end
200
200
 
201
201
  became = klass.new(clone_document)
202
- became.id = id
202
+ became._id = _id
203
203
  became.instance_variable_set(:@changed_attributes, changed_attributes)
204
204
  became.instance_variable_set(:@errors, ActiveModel::Errors.new(became))
205
205
  became.errors.instance_variable_set(:@messages, errors.instance_variable_get(:@messages))
@@ -225,7 +225,7 @@ module Mongoid
225
225
  # plural model name.
226
226
  #
227
227
  # If new_record? - will append /new
228
- # If not - will append /id-updated_at.to_s(:number)
228
+ # If not - will append /id-updated_at.to_s(:nsec)
229
229
  # Without updated_at - will append /id
230
230
  #
231
231
  # This is usually called insode a cache() block
@@ -238,7 +238,7 @@ module Mongoid
238
238
  # @since 2.4.0
239
239
  def cache_key
240
240
  return "#{model_key}/new" if new_record?
241
- return "#{model_key}/#{id}-#{updated_at.utc.to_s(:number)}" if do_or_do_not(:updated_at)
241
+ return "#{model_key}/#{id}-#{updated_at.utc.to_s(:nsec)}" if do_or_do_not(:updated_at)
242
242
  "#{model_key}/#{id}"
243
243
  end
244
244
 
@@ -12,6 +12,19 @@ class Symbol
12
12
  remove_method :size if instance_methods.include? :size # temporal fix for ruby 1.9
13
13
  end
14
14
 
15
+ class BSON::Document
16
+ # We need to override this as ActiveSupport creates a new Object, instead of a new Hash
17
+ # see https://github.com/rails/rails/commit/f1bad130d0c9bd77c94e43b696adca56c46a66aa
18
+ def transform_keys
19
+ return enum_for(:transform_keys) unless block_given?
20
+ result = {}
21
+ each_key do |key|
22
+ result[yield(key)] = self[key]
23
+ end
24
+ result
25
+ end
26
+ end
27
+
15
28
  require "mongoid/extensions/array"
16
29
  require "mongoid/extensions/big_decimal"
17
30
  require "mongoid/extensions/boolean"
@@ -90,21 +90,24 @@ module Mongoid
90
90
  with_default_scope.find(*args)
91
91
  end
92
92
 
93
- # Find the first +Document+ given the conditions, or raises
94
- # Mongoid::Errors::DocumentNotFound
93
+ # Find the first +Document+ given the conditions.
94
+ # If a matching Document is not found and
95
+ # Mongoid.raise_not_found_error is true it raises
96
+ # Mongoid::Errors::DocumentNotFound, return null nil elsewise.
95
97
  #
96
98
  # @example Find the document by attribute other than id
97
99
  # Person.find_by(:username => "superuser")
98
100
  #
99
101
  # @param [ Hash ] attrs The attributes to check.
100
102
  #
101
- # @raise [ Errors::DocumentNotFound ] If no document found.
103
+ # @raise [ Errors::DocumentNotFound ] If no document found
104
+ # and Mongoid.raise_not_found_error is true.
102
105
  #
103
- # @return [ Document ] A matching document.
106
+ # @return [ Document, nil ] A matching document.
104
107
  #
105
108
  # @since 3.0.0
106
109
  def find_by(attrs = {})
107
- result = where(attrs).first
110
+ result = where(attrs).find_first
108
111
  if result.nil? && Mongoid.raise_not_found_error
109
112
  raise(Errors::DocumentNotFound.new(self, attrs))
110
113
  end
@@ -112,6 +115,25 @@ module Mongoid
112
115
  result
113
116
  end
114
117
 
118
+ # Find the first +Document+ given the conditions, or raises
119
+ # Mongoid::Errors::DocumentNotFound
120
+ #
121
+ # @example Find the document by attribute other than id
122
+ # Person.find_by(:username => "superuser")
123
+ #
124
+ # @param [ Hash ] attrs The attributes to check.
125
+ #
126
+ # @raise [ Errors::DocumentNotFound ] If no document found.
127
+ #
128
+ # @return [ Document ] A matching document.
129
+ #
130
+ def find_by!(attrs = {})
131
+ result = where(attrs).find_first
132
+ raise(Errors::DocumentNotFound.new(self, attrs)) unless result
133
+ yield(result) if result && block_given?
134
+ result
135
+ end
136
+
115
137
  # Find the first +Document+ given the conditions.
116
138
  #
117
139
  # @example Find the first document.
@@ -111,7 +111,8 @@ module Mongoid
111
111
  #
112
112
  # @since 4.0.0
113
113
  def prepare_insert(options = {})
114
- return self if performing_validations?(options) && invalid?(:create)
114
+ return self if performing_validations?(options) &&
115
+ invalid?(options[:context] || :create)
115
116
  result = run_callbacks(:save) do
116
117
  run_callbacks(:create) do
117
118
  yield(self)
@@ -22,7 +22,7 @@ module Mongoid
22
22
  def set(setters)
23
23
  prepare_atomic_operation do |ops|
24
24
  process_atomic_operations(setters) do |field, value|
25
- send("#{field}=", value)
25
+ process_attribute(field.to_s, value)
26
26
  ops[atomic_attribute_name(field)] = attributes[field]
27
27
  end
28
28
  { "$set" => ops }
@@ -110,7 +110,8 @@ module Mongoid
110
110
  #
111
111
  # @since 4.0.0
112
112
  def prepare_update(options = {})
113
- return false if performing_validations?(options) && invalid?(:update)
113
+ return false if performing_validations?(options) &&
114
+ invalid?(options[:context] || :update)
114
115
  process_flagged_destroys
115
116
  result = run_callbacks(:save) do
116
117
  run_callbacks(:update) do
@@ -131,12 +131,16 @@ module Mongoid
131
131
 
132
132
  private
133
133
 
134
- def with_cache(context = :cursor, &block)
134
+ def with_cache(context = :cursor, more = false, &block)
135
135
  return yield unless QueryCache.enabled?
136
136
  return yield if system_collection?
137
137
  key = cache_key.push(context)
138
138
 
139
- if QueryCache.cache_table.has_key?(key)
139
+ if more
140
+ docs = yield
141
+ QueryCache.cache_table[key].push(*docs)
142
+ docs
143
+ elsif QueryCache.cache_table.has_key?(key)
140
144
  instrument(key) { QueryCache.cache_table[key] }
141
145
  else
142
146
  QueryCache.cache_table[key] = yield
@@ -230,6 +234,10 @@ module Mongoid
230
234
  with_cache { super }
231
235
  end
232
236
 
237
+ def get_more
238
+ with_cache(:cursor, true) { super }
239
+ end
240
+
233
241
  private
234
242
 
235
243
  def cache_key
@@ -13,19 +13,6 @@ module Rails
13
13
  # @since 2.0.0
14
14
  class Railtie < Rails::Railtie
15
15
 
16
- # Determine which generator to use. app_generators was introduced after
17
- # 3.0.0.
18
- #
19
- # @example Get the generators method.
20
- # railtie.generators
21
- #
22
- # @return [ Symbol ] The method name to use.
23
- #
24
- # @since 2.0.0.rc.4
25
- def self.generator
26
- config.respond_to?(:app_generators) ? :app_generators : :generators
27
- end
28
-
29
16
  # Mapping of rescued exceptions to HTTP responses
30
17
  #
31
18
  # @example
@@ -41,7 +28,7 @@ module Rails
41
28
  }
42
29
  end
43
30
 
44
- config.send(generator).orm :mongoid, migration: false
31
+ config.app_generators.orm :mongoid, migration: false
45
32
 
46
33
  if config.action_dispatch.rescue_responses
47
34
  config.action_dispatch.rescue_responses.merge!(rescue_responses)
@@ -98,7 +85,7 @@ module Rails
98
85
  # Due to all models not getting loaded and messing up inheritance queries
99
86
  # and indexing, we need to preload the models in order to address this.
100
87
  #
101
- # This will happen every request in development, once in ther other
88
+ # This will happen for every request in development, once in other
102
89
  # environments.
103
90
  #
104
91
  # @since 2.0.0
@@ -67,7 +67,7 @@ namespace :db do
67
67
 
68
68
  namespace :mongoid do
69
69
  task :load_models do
70
- ::Rails.application.eager_load!
70
+ ::Rails.application.eager_load! if defined?(Rails)
71
71
  end
72
72
  end
73
73
  end
@@ -12,7 +12,7 @@ module Mongoid
12
12
  # document is nil, then sets the relation on this document.
13
13
  #
14
14
  # @example Build the relation.
15
- # person.__build__(:addresses, { :id => 1 }, metadata)
15
+ # person.__build__(:addresses, { :_id => 1 }, metadata)
16
16
  #
17
17
  # @param [ String, Symbol ] name The name of the relation.
18
18
  # @param [ Hash, BSON::ObjectId ] object The id or attributes to use.
@@ -110,7 +110,7 @@ module Mongoid
110
110
 
111
111
  def needs_no_database_query?(object, metadata)
112
112
  object.is_a?(Document) && !object.embedded? &&
113
- object.id == attributes[metadata.key]
113
+ object._id == attributes[metadata.key]
114
114
  end
115
115
 
116
116
  # Is the current code executing without autobuild functionality?
@@ -91,7 +91,7 @@ module Mongoid
91
91
  # @api private
92
92
  #
93
93
  # @example Bind the foreign key.
94
- # binding.bind_foreign_key(post, person.id)
94
+ # binding.bind_foreign_key(post, person._id)
95
95
  #
96
96
  # @param [ Document ] keyed The document that stores the foreign key.
97
97
  # @param [ Object ] id The id of the bound document.
@@ -55,7 +55,7 @@ module Mongoid
55
55
  if inverse_metadata
56
56
  base.__send__(inverse_metadata.primary_key)
57
57
  else
58
- base.id
58
+ base._id
59
59
  end
60
60
  end
61
61
 
@@ -15,7 +15,7 @@ module Mongoid
15
15
  # @param [ String ] type Not used in this context.
16
16
  #
17
17
  # @return [ Document ] A single document.
18
- def build(type = nil)
18
+ def build(_type = nil)
19
19
  return object unless object.is_a?(Hash)
20
20
  if _loading? && base.persisted?
21
21
  Factory.from_db(klass, object)
@@ -68,7 +68,7 @@ module Mongoid
68
68
  # @since 2.0.0
69
69
  def acceptable_id?
70
70
  id = convert_id(existing.class, attributes[:id])
71
- existing.id == id || id.nil? || (existing.id != id && update_only?)
71
+ existing._id == id || id.nil? || (existing._id != id && update_only?)
72
72
  end
73
73
 
74
74
  # Can the existing relation be deleted?