mongoid 3.0.6 → 3.0.9
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/CHANGELOG.md +57 -1
- data/lib/config/locales/en.yml +6 -2
- data/lib/mongoid/attributes.rb +1 -1
- data/lib/mongoid/attributes/processing.rb +58 -11
- data/lib/mongoid/config.rb +13 -0
- data/lib/mongoid/contextual/map_reduce.rb +1 -1
- data/lib/mongoid/contextual/memory.rb +5 -4
- data/lib/mongoid/contextual/mongo.rb +2 -2
- data/lib/mongoid/criteria.rb +10 -1
- data/lib/mongoid/dirty.rb +0 -1
- data/lib/mongoid/document.rb +2 -1
- data/lib/mongoid/extensions/array.rb +1 -1
- data/lib/mongoid/extensions/big_decimal.rb +15 -0
- data/lib/mongoid/extensions/hash.rb +18 -0
- data/lib/mongoid/factory.rb +1 -1
- data/lib/mongoid/fields.rb +31 -0
- data/lib/mongoid/hierarchy.rb +15 -0
- data/lib/mongoid/indexes.rb +22 -2
- data/lib/mongoid/indexes/validators/options.rb +2 -2
- data/lib/mongoid/multi_parameter_attributes.rb +1 -1
- data/lib/mongoid/nested_attributes.rb +1 -1
- data/lib/mongoid/persistence.rb +1 -1
- data/lib/mongoid/persistence/insertion.rb +1 -0
- data/lib/mongoid/railtie.rb +1 -15
- data/lib/mongoid/relations/accessors.rb +1 -1
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +17 -6
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +41 -50
- data/lib/mongoid/relations/embedded/batchable.rb +1 -1
- data/lib/mongoid/relations/metadata.rb +1 -0
- data/lib/mongoid/relations/referenced/many.rb +5 -1
- data/lib/mongoid/relations/targets/enumerable.rb +10 -0
- data/lib/mongoid/threaded.rb +22 -4
- data/lib/mongoid/validations/uniqueness.rb +1 -2
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +13 -1
- metadata +3 -3
data/CHANGELOG.md
CHANGED
@@ -3,7 +3,63 @@
|
|
3
3
|
For instructions on upgrading to newer versions, visit
|
4
4
|
[mongoid.org](http://mongoid.org/docs/upgrading.html).
|
5
5
|
|
6
|
-
## 3.0.
|
6
|
+
## 3.0.9
|
7
|
+
|
8
|
+
### Resolved Issues
|
9
|
+
|
10
|
+
* \#2463 Fixed the broken `rails g mongoid:config` from a fresh repo.
|
11
|
+
|
12
|
+
* \#2456 The descendants cache is now reset when the document is inherited
|
13
|
+
again. (Kostyantyn Stepanyuk)
|
14
|
+
|
15
|
+
* \#2453 `Model#write_attribute` now properly works with aliased fields.
|
16
|
+
(Campbell Allen)
|
17
|
+
|
18
|
+
* \#2444 Removed extra dirty methods creation call. (Kostyantyn Stepanyuk)
|
19
|
+
|
20
|
+
* \#2440/\#2435 Pass mass assignment options down to children when setting via
|
21
|
+
nested attributes or embedded documents.
|
22
|
+
|
23
|
+
* \#2439 Fixed memory leak in threaded selection of returned fields.
|
24
|
+
(Tim Olsen)
|
25
|
+
|
26
|
+
* mongoid/moped\#82 Aliased fields now work with `Criteria#distinct`.
|
27
|
+
|
28
|
+
* \#2423 Fixed embedded document's `update_all` to perform the correct $set
|
29
|
+
when using off a criteria.
|
30
|
+
|
31
|
+
* \#2414 Index definitions now respect aliased fields.
|
32
|
+
|
33
|
+
* \#2413 Enumerable targets now properly return enumerators when no blocks
|
34
|
+
are provided. (Andrew Smith)
|
35
|
+
|
36
|
+
* \#2411 BigDecimal fields are properly stored as strings when mongoizing
|
37
|
+
integers and floats.
|
38
|
+
|
39
|
+
* \#2409 Don't warn about missing mongoid.yml if configured programatically.
|
40
|
+
|
41
|
+
* \#2403 Return false on `update_all` of an embeds many with no documents.
|
42
|
+
|
43
|
+
* \#2401 Bring back the ability to merge a criteria with a hash.
|
44
|
+
|
45
|
+
* \#2399 Reject blank id values on has_many `Model#object_ids=`.
|
46
|
+
(Tiago Rafael Godinho)
|
47
|
+
|
48
|
+
* \#2393 Ensure `inverse_of` is respected when using polymorphic relations.
|
49
|
+
|
50
|
+
* \#2388 Map/reduce properly uses `sort` instead of `orderby` in the execution
|
51
|
+
of the command. (Alex Tsibulya)
|
52
|
+
|
53
|
+
* \#2386 Allow geo haystack and bits parameters in indexes. (Bradley Rees)
|
54
|
+
|
55
|
+
* \#2380 `Model#becomes` now properly copies over dirty attributes.
|
56
|
+
|
57
|
+
* \#2331 Don't double push child documents when extra saves are called in an
|
58
|
+
after_create callback.
|
59
|
+
|
60
|
+
## 3.0.8 (Yanked)
|
61
|
+
|
62
|
+
## 3.0.6
|
7
63
|
|
8
64
|
### Resolved Issues
|
9
65
|
|
data/lib/config/locales/en.yml
CHANGED
@@ -152,8 +152,12 @@ en:
|
|
152
152
|
\_\_drop_dups: true|false\n
|
153
153
|
\_\_name: 'index_name'\n
|
154
154
|
\_\_sparse: true|false\n
|
155
|
-
\_\_unique: true|false\n
|
156
|
-
|
155
|
+
\_\_unique: true|false\n
|
156
|
+
\_\_min: 1\n
|
157
|
+
\_\_max: 1\n
|
158
|
+
\_\_bits: 26\n
|
159
|
+
\_\_bucket_size : 1\n
|
160
|
+
Valid types are: 1, -1, '2d', 'geoHaystack'\n\n
|
157
161
|
Example:\n
|
158
162
|
\_\_class Band\n
|
159
163
|
\_\_\_\_include Mongoid::Document\n
|
data/lib/mongoid/attributes.rb
CHANGED
@@ -19,19 +19,41 @@ module Mongoid
|
|
19
19
|
#
|
20
20
|
# @since 2.0.0.rc.7
|
21
21
|
def process_attributes(attrs = nil, role = :default, guard_protected_attributes = true)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
with_mass_assignment(role, guard_protected_attributes) do
|
23
|
+
attrs ||= {}
|
24
|
+
if !attrs.empty?
|
25
|
+
attrs = sanitize_for_mass_assignment(attrs, role) if guard_protected_attributes
|
26
|
+
attrs.each_pair do |key, value|
|
27
|
+
next if pending_attribute?(key, value)
|
28
|
+
process_attribute(key, value)
|
29
|
+
end
|
28
30
|
end
|
31
|
+
yield self if block_given?
|
32
|
+
process_pending
|
29
33
|
end
|
30
|
-
yield self if block_given?
|
31
|
-
process_pending
|
32
34
|
end
|
33
35
|
|
34
|
-
|
36
|
+
private
|
37
|
+
|
38
|
+
# Get the current mass assignment options for this model.
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
#
|
42
|
+
# @return [ Hash ] The mass assignment options.
|
43
|
+
#
|
44
|
+
# @since 3.0.7
|
45
|
+
def mass_assignment_options
|
46
|
+
@mass_assignment_options ||= {}
|
47
|
+
end
|
48
|
+
|
49
|
+
# Set the mass assignment options for the current model.
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
#
|
53
|
+
# @return [ Hash ] The mass assignment options.
|
54
|
+
#
|
55
|
+
# @since 3.0.7
|
56
|
+
attr_writer :mass_assignment_options
|
35
57
|
|
36
58
|
# If the key provided is the name of a relation or a nested attribute, we
|
37
59
|
# need to wait until all other attributes are set before processing
|
@@ -121,6 +143,8 @@ module Mongoid
|
|
121
143
|
# @example Process the pending items.
|
122
144
|
# document.process_pending
|
123
145
|
#
|
146
|
+
# @param [ Hash ] options The mass assignment options.
|
147
|
+
#
|
124
148
|
# @since 2.0.0.rc.7
|
125
149
|
def process_pending
|
126
150
|
process_nested and process_relations
|
@@ -133,18 +157,41 @@ module Mongoid
|
|
133
157
|
# @example Process the relations.
|
134
158
|
# document.process_relations
|
135
159
|
#
|
160
|
+
# @param [ Hash ] options The mass assignment options.
|
161
|
+
#
|
136
162
|
# @since 2.0.0.rc.7
|
137
163
|
def process_relations
|
138
164
|
pending_relations.each_pair do |name, value|
|
139
165
|
metadata = relations[name]
|
140
166
|
if value.is_a?(Hash)
|
141
|
-
metadata.nested_builder(value, {}).build(self)
|
167
|
+
metadata.nested_builder(value, {}).build(self, mass_assignment_options)
|
142
168
|
else
|
143
169
|
send("#{name}=", value)
|
144
170
|
end
|
145
171
|
end
|
146
172
|
end
|
173
|
+
|
174
|
+
# Execute the block with the provided mass assignment options set.
|
175
|
+
#
|
176
|
+
# @api private
|
177
|
+
#
|
178
|
+
# @example Execute with mass assignment.
|
179
|
+
# model.with_mass_assignment(:default, true)
|
180
|
+
#
|
181
|
+
# @param [ Symbol ] role The role.
|
182
|
+
# @param [ true, false ] guard_protected_attributes To enable mass
|
183
|
+
# assignment.
|
184
|
+
#
|
185
|
+
# @since 3.0.7
|
186
|
+
def with_mass_assignment(role, guard_protected_attributes)
|
187
|
+
begin
|
188
|
+
self.mass_assignment_options =
|
189
|
+
{ as: role, without_protection: !guard_protected_attributes }
|
190
|
+
yield
|
191
|
+
ensure
|
192
|
+
self.mass_assignment_options = nil
|
193
|
+
end
|
194
|
+
end
|
147
195
|
end
|
148
196
|
end
|
149
197
|
end
|
150
|
-
|
data/lib/mongoid/config.rb
CHANGED
@@ -26,6 +26,19 @@ module Mongoid
|
|
26
26
|
option :use_activesupport_time_zone, default: true
|
27
27
|
option :use_utc, default: false
|
28
28
|
|
29
|
+
# Has Mongoid been configured? This is checking that at least a valid
|
30
|
+
# session config exists.
|
31
|
+
#
|
32
|
+
# @example Is Mongoid configured?
|
33
|
+
# config.configured?
|
34
|
+
#
|
35
|
+
# @return [ true, false ] If Mongoid is configured.
|
36
|
+
#
|
37
|
+
# @since 3.0.9
|
38
|
+
def configured?
|
39
|
+
sessions.has_key?(:default)
|
40
|
+
end
|
41
|
+
|
29
42
|
# Connect to the provided database name on the default session.
|
30
43
|
#
|
31
44
|
# @note Use only in development or test environments for convenience.
|
@@ -216,7 +216,7 @@ module Mongoid
|
|
216
216
|
def apply_criteria_options
|
217
217
|
command[:query] = criteria.selector
|
218
218
|
if sort = criteria.options[:sort]
|
219
|
-
command[:
|
219
|
+
command[:sort] = sort
|
220
220
|
end
|
221
221
|
if limit = criteria.options[:limit]
|
222
222
|
command[:limit] = limit
|
@@ -281,14 +281,15 @@ module Mongoid
|
|
281
281
|
#
|
282
282
|
# @since 3.0.4
|
283
283
|
def update_documents(attributes, docs)
|
284
|
-
return false
|
285
|
-
updates = {}
|
284
|
+
return false if !attributes || docs.empty?
|
285
|
+
updates = { "$set" => {}}
|
286
286
|
docs.each do |doc|
|
287
287
|
@selector ||= root.atomic_selector
|
288
288
|
doc.write_attributes(attributes)
|
289
|
-
updates.merge!(doc.
|
289
|
+
updates["$set"].merge!(doc.atomic_updates["$set"])
|
290
|
+
doc.move_changes
|
290
291
|
end
|
291
|
-
collection.find(selector).update(
|
292
|
+
collection.find(selector).update(updates)
|
292
293
|
end
|
293
294
|
|
294
295
|
# Get the limiting value.
|
@@ -113,7 +113,7 @@ module Mongoid
|
|
113
113
|
#
|
114
114
|
# @since 3.0.0
|
115
115
|
def distinct(field)
|
116
|
-
query.distinct(field)
|
116
|
+
query.distinct(klass.database_field_name(field))
|
117
117
|
end
|
118
118
|
|
119
119
|
# Iterate over the context. If provided a block, yield to a Mongoid
|
@@ -602,7 +602,7 @@ module Mongoid
|
|
602
602
|
Threaded.set_selection(criteria.object_id, fields) unless fields.blank?
|
603
603
|
yield
|
604
604
|
ensure
|
605
|
-
Threaded.
|
605
|
+
Threaded.delete_selection(criteria.object_id)
|
606
606
|
end
|
607
607
|
end
|
608
608
|
|
data/lib/mongoid/criteria.rb
CHANGED
@@ -320,7 +320,7 @@ module Mongoid
|
|
320
320
|
# @since 1.0.0
|
321
321
|
def initialize(klass)
|
322
322
|
@klass = klass
|
323
|
-
super(klass.aliased_fields, klass.fields)
|
323
|
+
klass ? super(klass.aliased_fields, klass.fields) : super({}, {})
|
324
324
|
end
|
325
325
|
|
326
326
|
# Eager loads all the provided relations. Will load all the documents
|
@@ -390,6 +390,15 @@ module Mongoid
|
|
390
390
|
# @example Merge the criteria with another criteria.
|
391
391
|
# criteri.merge(other_criteria)
|
392
392
|
#
|
393
|
+
# @example Merge the criteria with a hash. The hash must contain a klass
|
394
|
+
# key and the key/value pairs correspond to method names/args.
|
395
|
+
|
396
|
+
# criteria.merge({
|
397
|
+
# klass: Band,
|
398
|
+
# where: { name: "Depeche Mode" },
|
399
|
+
# order_by: { name: 1 }
|
400
|
+
# })
|
401
|
+
#
|
393
402
|
# @param [ Criteria ] other The other criterion to merge with.
|
394
403
|
#
|
395
404
|
# @return [ Criteria ] A cloned self.
|
data/lib/mongoid/dirty.rb
CHANGED
data/lib/mongoid/document.rb
CHANGED
@@ -215,7 +215,8 @@ module Mongoid
|
|
215
215
|
unless klass.include?(Mongoid::Document)
|
216
216
|
raise ArgumentError, "A class which includes Mongoid::Document is expected"
|
217
217
|
end
|
218
|
-
became = klass.
|
218
|
+
became = klass.new(as_document.__deep_copy__)
|
219
|
+
became.instance_variable_set(:@changed_attributes, changed_attributes)
|
219
220
|
became.instance_variable_set(:@errors, errors)
|
220
221
|
became.instance_variable_set(:@new_record, new_record?)
|
221
222
|
became.instance_variable_set(:@destroyed, destroyed?)
|
@@ -45,6 +45,21 @@ module Mongoid
|
|
45
45
|
object.numeric? ? ::BigDecimal.new(object.to_s) : object
|
46
46
|
end
|
47
47
|
end
|
48
|
+
|
49
|
+
# Mongoize an object of any type to how it's stored in the db as a big
|
50
|
+
# decimal.
|
51
|
+
#
|
52
|
+
# @example Mongoize the object.
|
53
|
+
# BigDecimal.mongoize(123)
|
54
|
+
#
|
55
|
+
# @param [ Object ] object The object to Mongoize
|
56
|
+
#
|
57
|
+
# @return [ String ] The mongoized object.
|
58
|
+
#
|
59
|
+
# @since 3.0.7
|
60
|
+
def mongoize(object)
|
61
|
+
object ? object.to_s : object
|
62
|
+
end
|
48
63
|
end
|
49
64
|
end
|
50
65
|
end
|
@@ -97,6 +97,24 @@ module Mongoid
|
|
97
97
|
true
|
98
98
|
end
|
99
99
|
|
100
|
+
# Convert this hash to a criteria. Will iterate over each keys in the
|
101
|
+
# hash which must correspond to method on a criteria object. The hash
|
102
|
+
# must also include a "klass" key.
|
103
|
+
#
|
104
|
+
# @example Convert the hash to a criteria.
|
105
|
+
# { klass: Band, where: { name: "Depeche Mode" }.to_criteria
|
106
|
+
#
|
107
|
+
# @return [ Criteria ] The criteria.
|
108
|
+
#
|
109
|
+
# @since 3.0.7
|
110
|
+
def to_criteria
|
111
|
+
criteria = Criteria.new(delete(:klass) || delete("klass"))
|
112
|
+
each_pair do |method, args|
|
113
|
+
criteria = criteria.__send__(method, args)
|
114
|
+
end
|
115
|
+
criteria
|
116
|
+
end
|
117
|
+
|
100
118
|
module ClassMethods
|
101
119
|
|
102
120
|
# Turn the object from the ruby type we deal with to a Mongo friendly
|
data/lib/mongoid/factory.rb
CHANGED
@@ -12,7 +12,7 @@ module Mongoid
|
|
12
12
|
#
|
13
13
|
# @param [ Class ] klass The class to instantiate from if _type is not present.
|
14
14
|
# @param [ Hash ] attributes The document attributes.
|
15
|
-
# @param [ Hash ]
|
15
|
+
# @param [ Hash ] options The mass assignment scoping options.
|
16
16
|
#
|
17
17
|
# @return [ Document ] The instantiated document.
|
18
18
|
def build(klass, attributes = nil, options = {})
|
data/lib/mongoid/fields.rb
CHANGED
@@ -109,6 +109,21 @@ module Mongoid
|
|
109
109
|
self.class.attribute_names
|
110
110
|
end
|
111
111
|
|
112
|
+
# Get the name of the provided field as it is stored in the database.
|
113
|
+
# Used in determining if the field is aliased or not.
|
114
|
+
#
|
115
|
+
# @example Get the database field name.
|
116
|
+
# model.database_field_name(:authorization)
|
117
|
+
#
|
118
|
+
# @param [ String, Symbol ] name The name to get.
|
119
|
+
#
|
120
|
+
# @return [ String ] The name of the field as it's stored in the db.
|
121
|
+
#
|
122
|
+
# @since 3.0.7
|
123
|
+
def database_field_name(name)
|
124
|
+
self.class.database_field_name(name)
|
125
|
+
end
|
126
|
+
|
112
127
|
# Is the document using object ids?
|
113
128
|
#
|
114
129
|
# @note Refactored from using delegate for class load performance.
|
@@ -175,6 +190,22 @@ module Mongoid
|
|
175
190
|
fields.keys
|
176
191
|
end
|
177
192
|
|
193
|
+
# Get the name of the provided field as it is stored in the database.
|
194
|
+
# Used in determining if the field is aliased or not.
|
195
|
+
#
|
196
|
+
# @example Get the database field name.
|
197
|
+
# Model.database_field_name(:authorization)
|
198
|
+
#
|
199
|
+
# @param [ String, Symbol ] name The name to get.
|
200
|
+
#
|
201
|
+
# @return [ String ] The name of the field as it's stored in the db.
|
202
|
+
#
|
203
|
+
# @since 3.0.7
|
204
|
+
def database_field_name(name)
|
205
|
+
normalized = name.to_s
|
206
|
+
aliased_fields[normalized] || normalized
|
207
|
+
end
|
208
|
+
|
178
209
|
# Defines all the fields that are accessible on the Document
|
179
210
|
# For each field that is defined, a getter and setter will be
|
180
211
|
# added as an instance method to the Document.
|
data/lib/mongoid/hierarchy.rb
CHANGED
@@ -44,6 +44,20 @@ module Mongoid
|
|
44
44
|
children
|
45
45
|
end
|
46
46
|
|
47
|
+
# Marks all children as being persisted.
|
48
|
+
#
|
49
|
+
# @example Flag all the children.
|
50
|
+
# document.flag_children_persisted
|
51
|
+
#
|
52
|
+
# @return [ Array<Document> ] The flagged children.
|
53
|
+
#
|
54
|
+
# @since 3.0.7
|
55
|
+
def flag_children_persisted
|
56
|
+
_children.each do |child|
|
57
|
+
child.new_record = false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
47
61
|
# Determines if the document is a subclass of another document.
|
48
62
|
#
|
49
63
|
# @example Check if the document is a subclass
|
@@ -141,6 +155,7 @@ module Mongoid
|
|
141
155
|
# @since 2.0.0.rc.6
|
142
156
|
def inherited(subclass)
|
143
157
|
super
|
158
|
+
@_type = nil
|
144
159
|
subclass.fields = fields.dup
|
145
160
|
subclass.pre_processed_defaults = pre_processed_defaults.dup
|
146
161
|
subclass.post_processed_defaults = post_processed_defaults.dup
|
data/lib/mongoid/indexes.rb
CHANGED
@@ -78,7 +78,7 @@ module Mongoid
|
|
78
78
|
# @since 1.0.0
|
79
79
|
def index(spec, options = nil)
|
80
80
|
Validators::Options.validate(self, spec, options || {})
|
81
|
-
index_options[spec] = normalize_index_options(options)
|
81
|
+
index_options[normalize_spec(spec)] = normalize_index_options(options)
|
82
82
|
end
|
83
83
|
|
84
84
|
private
|
@@ -88,7 +88,7 @@ module Mongoid
|
|
88
88
|
# @api private
|
89
89
|
#
|
90
90
|
# @example Normalize the index options.
|
91
|
-
#
|
91
|
+
# Model.normalize_index_options(drop_dups: true)
|
92
92
|
#
|
93
93
|
# @param [ Hash ] options The index options.
|
94
94
|
#
|
@@ -98,8 +98,28 @@ module Mongoid
|
|
98
98
|
def normalize_index_options(options)
|
99
99
|
opts = options || {}
|
100
100
|
opts[:dropDups] = opts.delete(:drop_dups) if opts.has_key?(:drop_dups)
|
101
|
+
opts[:bucketSize] = opts.delete(:bucket_size) if opts.has_key?(:bucket_size)
|
101
102
|
opts
|
102
103
|
end
|
104
|
+
|
105
|
+
# Normalize the spec, in case aliased fields are provided.
|
106
|
+
#
|
107
|
+
# @api private
|
108
|
+
#
|
109
|
+
# @example Normalize the spec.
|
110
|
+
# Model.normalize_spec(name: 1)
|
111
|
+
#
|
112
|
+
# @param [ Hash ] spec The index specification.
|
113
|
+
#
|
114
|
+
# @return [ Hash ] The normalized specification.
|
115
|
+
#
|
116
|
+
# @since 3.0.7
|
117
|
+
def normalize_spec(spec)
|
118
|
+
spec.inject({}) do |normalized, (name, direction)|
|
119
|
+
normalized[database_field_name(name).to_sym] = direction
|
120
|
+
normalized
|
121
|
+
end
|
122
|
+
end
|
103
123
|
end
|
104
124
|
end
|
105
125
|
end
|
@@ -7,8 +7,8 @@ module Mongoid
|
|
7
7
|
module Options
|
8
8
|
extend self
|
9
9
|
|
10
|
-
VALID_OPTIONS = [ :background, :drop_dups, :name, :sparse, :unique, :max, :min ]
|
11
|
-
VALID_TYPES = [ 1, -1, "2d" ]
|
10
|
+
VALID_OPTIONS = [ :background, :drop_dups, :name, :sparse, :unique, :max, :min, :bits, :bucket_size ]
|
11
|
+
VALID_TYPES = [ 1, -1, "2d", "geoHaystack" ]
|
12
12
|
|
13
13
|
# Validate the index specification.
|
14
14
|
#
|
@@ -66,7 +66,7 @@ module Mongoid
|
|
66
66
|
multi_parameter_attributes.each_pair do |key, values|
|
67
67
|
begin
|
68
68
|
values = (values.keys.min..values.keys.max).map { |i| values[i] }
|
69
|
-
field = self.class.fields[
|
69
|
+
field = self.class.fields[database_field_name(key)]
|
70
70
|
attributes[key] = instantiate_object(field, values)
|
71
71
|
rescue => e
|
72
72
|
errors << Errors::AttributeAssignmentError.new(
|
@@ -52,7 +52,7 @@ module Mongoid
|
|
52
52
|
autosave(metadata.merge!(autosave: true))
|
53
53
|
re_define_method(meth) do |attrs|
|
54
54
|
_assigning do
|
55
|
-
metadata.nested_builder(attrs, options).build(self)
|
55
|
+
metadata.nested_builder(attrs, options).build(self, mass_assignment_options)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
data/lib/mongoid/persistence.rb
CHANGED
@@ -159,7 +159,7 @@ module Mongoid
|
|
159
159
|
unless attribute_writable?(normalized)
|
160
160
|
raise Errors::ReadonlyAttribute.new(normalized, value)
|
161
161
|
end
|
162
|
-
write_attribute(
|
162
|
+
write_attribute(database_field_name(normalized), value)
|
163
163
|
save(validate: false)
|
164
164
|
end
|
165
165
|
|
data/lib/mongoid/railtie.rb
CHANGED
@@ -60,20 +60,6 @@ module Rails
|
|
60
60
|
|
61
61
|
# Initialize Mongoid. This will look for a mongoid.yml in the config
|
62
62
|
# directory and configure mongoid appropriately.
|
63
|
-
#
|
64
|
-
# @example mongoid.yml
|
65
|
-
#
|
66
|
-
# development:
|
67
|
-
# host: localhost
|
68
|
-
# database: mongoid
|
69
|
-
# slaves:
|
70
|
-
# # - host: localhost
|
71
|
-
# # port: 27018
|
72
|
-
# # - host: localhost
|
73
|
-
# # port: 27019
|
74
|
-
# allow_dynamic_fields: false
|
75
|
-
# persist_in_safe_mode: false
|
76
|
-
#
|
77
63
|
initializer "setup database" do
|
78
64
|
config_file = Rails.root.join("config", "mongoid.yml")
|
79
65
|
if config_file.file?
|
@@ -95,7 +81,7 @@ module Rails
|
|
95
81
|
# alert to create one.
|
96
82
|
initializer "warn when configuration is missing" do
|
97
83
|
config.after_initialize do
|
98
|
-
unless Rails.root.join("config", "mongoid.yml").file?
|
84
|
+
unless Rails.root.join("config", "mongoid.yml").file? || ::Mongoid.configured?
|
99
85
|
puts "\nMongoid config not found. Create a config file at: config/mongoid.yml"
|
100
86
|
puts "to generate one run: rails generate mongoid:config\n\n"
|
101
87
|
end
|
@@ -228,7 +228,7 @@ module Mongoid
|
|
228
228
|
def ids_setter(name, metadata)
|
229
229
|
ids_method = "#{name.to_s.singularize}_ids="
|
230
230
|
re_define_method(ids_method) do |ids|
|
231
|
-
send(metadata.setter, metadata.klass.find(ids))
|
231
|
+
send(metadata.setter, metadata.klass.find(ids.reject(&:blank?)))
|
232
232
|
end
|
233
233
|
self
|
234
234
|
end
|
@@ -16,18 +16,19 @@ module Mongoid
|
|
16
16
|
# many.build(person)
|
17
17
|
#
|
18
18
|
# @param [ Document ] parent The parent document of the relation.
|
19
|
+
# @param [ Hash ] options The mass assignment options.
|
19
20
|
#
|
20
21
|
# @return [ Array ] The attributes.
|
21
|
-
def build(parent)
|
22
|
+
def build(parent, options = {})
|
22
23
|
@existing = parent.send(metadata.name)
|
23
24
|
if over_limit?(attributes)
|
24
25
|
raise Errors::TooManyNestedAttributeRecords.new(existing, options[:limit])
|
25
26
|
end
|
26
27
|
attributes.each do |attrs|
|
27
28
|
if attrs.respond_to?(:with_indifferent_access)
|
28
|
-
process_attributes(parent, attrs)
|
29
|
+
process_attributes(parent, attrs, options)
|
29
30
|
else
|
30
|
-
process_attributes(parent, attrs[1])
|
31
|
+
process_attributes(parent, attrs[1], options)
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
@@ -85,11 +86,17 @@ module Mongoid
|
|
85
86
|
# Process each set of attributes one at a time for each potential
|
86
87
|
# new, existing, or ignored document.
|
87
88
|
#
|
89
|
+
# @api private
|
90
|
+
#
|
88
91
|
# @example Process the attributes
|
89
92
|
# builder.process_attributes({ "id" => 1, "street" => "Bond" })
|
90
93
|
#
|
94
|
+
# @param [ Document ] parent The parent document.
|
91
95
|
# @param [ Hash ] attrs The single document attributes to process.
|
92
|
-
|
96
|
+
# @param [ Hash ] options the mass assignment options.
|
97
|
+
#
|
98
|
+
# @since 2.0.0
|
99
|
+
def process_attributes(parent, attrs, options)
|
93
100
|
return if reject?(parent, attrs)
|
94
101
|
if id = attrs.extract_id
|
95
102
|
first = existing.first
|
@@ -100,10 +107,14 @@ module Mongoid
|
|
100
107
|
doc.destroy unless doc.embedded? || doc.destroyed?
|
101
108
|
else
|
102
109
|
attrs.delete_id
|
103
|
-
metadata.embedded?
|
110
|
+
if metadata.embedded?
|
111
|
+
doc.assign_attributes(attrs, options)
|
112
|
+
else
|
113
|
+
doc.update_attributes(attrs, options)
|
114
|
+
end
|
104
115
|
end
|
105
116
|
else
|
106
|
-
existing.push(Factory.build(metadata.klass, attrs)) unless destroyable?(attrs)
|
117
|
+
existing.push(Factory.build(metadata.klass, attrs, options)) unless destroyable?(attrs)
|
107
118
|
end
|
108
119
|
end
|
109
120
|
end
|
@@ -10,25 +10,27 @@ module Mongoid
|
|
10
10
|
# Builds the relation depending on the attributes and the options
|
11
11
|
# passed to the macro.
|
12
12
|
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# document, or a removal of the relation.
|
13
|
+
# @example Build a 1-1 nested document.
|
14
|
+
# one.build(person, as: :admin)
|
16
15
|
#
|
17
|
-
#
|
16
|
+
# @note This attempts to perform 3 operations, either one of an update of
|
17
|
+
# the existing relation, a replacement of the relation with a new
|
18
|
+
# document, or a removal of the relation.
|
18
19
|
#
|
19
|
-
#
|
20
|
+
# @param [ Document ] parent The parent document.
|
21
|
+
# @param [ Hash ] options The mass assignment options.
|
20
22
|
#
|
21
|
-
#
|
23
|
+
# @return [ Document ] The built document.
|
22
24
|
#
|
23
|
-
#
|
24
|
-
def build(parent)
|
25
|
+
# @since 2.0.0
|
26
|
+
def build(parent, options = {})
|
25
27
|
return if reject?(parent, attributes)
|
26
28
|
@existing = parent.send(metadata.name)
|
27
29
|
if update?
|
28
30
|
attributes.delete_id
|
29
|
-
existing.attributes
|
31
|
+
existing.assign_attributes(attributes, options)
|
30
32
|
elsif replace?
|
31
|
-
parent.send(metadata.setter, Factory.build(metadata.klass, attributes))
|
33
|
+
parent.send(metadata.setter, Factory.build(metadata.klass, attributes, options))
|
32
34
|
elsif delete?
|
33
35
|
parent.send(metadata.setter, nil)
|
34
36
|
end
|
@@ -37,19 +39,14 @@ module Mongoid
|
|
37
39
|
# Create the new builder for nested attributes on one-to-one
|
38
40
|
# relations.
|
39
41
|
#
|
40
|
-
#
|
42
|
+
# @example Instantiate the builder.
|
43
|
+
# One.new(metadata, attributes, options)
|
41
44
|
#
|
42
|
-
#
|
45
|
+
# @param [ Metadata ] metadata The relation metadata.
|
46
|
+
# @param [ Hash ] attributes The attributes hash to attempt to set.
|
47
|
+
# @param [ Hash ] options The options defined.
|
43
48
|
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
# metadata: The relation metadata
|
47
|
-
# attributes: The attributes hash to attempt to set.
|
48
|
-
# options: The options defined.
|
49
|
-
#
|
50
|
-
# Returns:
|
51
|
-
#
|
52
|
-
# A new builder.
|
49
|
+
# @since 2.0.0
|
53
50
|
def initialize(metadata, attributes, options)
|
54
51
|
@attributes = attributes.with_indifferent_access
|
55
52
|
@metadata = metadata
|
@@ -62,13 +59,14 @@ module Mongoid
|
|
62
59
|
# Is the id in the attribtues acceptable for allowing an update to
|
63
60
|
# the existing relation?
|
64
61
|
#
|
65
|
-
#
|
62
|
+
# @api private
|
66
63
|
#
|
67
|
-
#
|
64
|
+
# @example Is the id acceptable?
|
65
|
+
# one.acceptable_id?
|
68
66
|
#
|
69
|
-
#
|
67
|
+
# @return [ true, false ] If the id part of the logic will allow an update.
|
70
68
|
#
|
71
|
-
#
|
69
|
+
# @since 2.0.0
|
72
70
|
def acceptable_id?
|
73
71
|
id = convert_id(existing.class, attributes[:id])
|
74
72
|
existing.id == id || id.nil? || (existing.id != id && update_only?)
|
@@ -76,56 +74,49 @@ module Mongoid
|
|
76
74
|
|
77
75
|
# Can the existing relation be deleted?
|
78
76
|
#
|
79
|
-
#
|
77
|
+
# @example Can the existing object be deleted?
|
78
|
+
# one.delete?
|
80
79
|
#
|
81
|
-
#
|
80
|
+
# @return [ true, false ] If the relation should be deleted.
|
82
81
|
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
# True if the relation should be deleted.
|
82
|
+
# @since 2.0.0
|
86
83
|
def delete?
|
87
84
|
destroyable? && !attributes[:id].nil?
|
88
85
|
end
|
89
86
|
|
90
|
-
# Can the existing relation potentially be
|
91
|
-
#
|
92
|
-
# Example:
|
87
|
+
# Can the existing relation potentially be destroyed?
|
93
88
|
#
|
94
|
-
#
|
89
|
+
# @example Is the object destroyable?
|
90
|
+
# one.destroyable?({ :_destroy => "1" })
|
95
91
|
#
|
96
|
-
#
|
92
|
+
# @return [ true, false ] If the relation can potentially be
|
93
|
+
# destroyed.
|
97
94
|
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
# Returns:
|
101
|
-
#
|
102
|
-
# True if the relation can potentially be deleted.
|
95
|
+
# @since 2.0.0
|
103
96
|
def destroyable?
|
104
97
|
[ 1, "1", true, "true" ].include?(destroy) && allow_destroy?
|
105
98
|
end
|
106
99
|
|
107
100
|
# Is the document to be replaced?
|
108
101
|
#
|
109
|
-
#
|
102
|
+
# @example Is the document to be replaced?
|
103
|
+
# one.replace?
|
110
104
|
#
|
111
|
-
#
|
105
|
+
# @return [ true, false ] If the document should be replaced.
|
112
106
|
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
# True if the document should be replaced.
|
107
|
+
# @since 2.0.0
|
116
108
|
def replace?
|
117
109
|
!existing && !destroyable? && !attributes.blank?
|
118
110
|
end
|
119
111
|
|
120
112
|
# Should the document be updated?
|
121
113
|
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
# <tt>update?</tt>
|
114
|
+
# @example Should the document be updated?
|
115
|
+
# one.update?
|
125
116
|
#
|
126
|
-
#
|
117
|
+
# @return [ true, false ] If the object should have its attributes updated.
|
127
118
|
#
|
128
|
-
#
|
119
|
+
# @since 2.0.0
|
129
120
|
def update?
|
130
121
|
existing && !destroyable? && acceptable_id?
|
131
122
|
end
|
@@ -194,7 +194,7 @@ module Mongoid
|
|
194
194
|
docs.map do |doc|
|
195
195
|
attributes = { metadata: metadata, _parent: base }
|
196
196
|
attributes.merge!(doc)
|
197
|
-
Factory.build(klass, attributes)
|
197
|
+
Factory.build(klass, attributes, base.send(:mass_assignment_options))
|
198
198
|
end
|
199
199
|
else
|
200
200
|
docs
|
@@ -163,7 +163,11 @@ module Mongoid
|
|
163
163
|
#
|
164
164
|
# @since 2.1.0
|
165
165
|
def each
|
166
|
-
|
166
|
+
if block_given?
|
167
|
+
target.each { |doc| yield(doc) }
|
168
|
+
else
|
169
|
+
to_enum
|
170
|
+
end
|
167
171
|
end
|
168
172
|
|
169
173
|
# Determine if any documents in this relation exist in the database.
|
@@ -139,15 +139,25 @@ module Mongoid
|
|
139
139
|
# the cursor while loading the documents and then iterates over the
|
140
140
|
# _added docs.
|
141
141
|
#
|
142
|
+
# If no block is passed then it returns an enumerator containing all
|
143
|
+
# docs.
|
144
|
+
#
|
142
145
|
# @example Iterate over the enumerable.
|
143
146
|
# enumerable.each do |doc|
|
144
147
|
# puts doc
|
145
148
|
# end
|
146
149
|
#
|
150
|
+
# @example return an enumerator containing all the docs
|
151
|
+
#
|
152
|
+
# a = enumerable.each
|
153
|
+
#
|
147
154
|
# @return [ true ] That the enumerable is now _loaded.
|
148
155
|
#
|
149
156
|
# @since 2.1.0
|
150
157
|
def each
|
158
|
+
unless block_given?
|
159
|
+
return to_enum
|
160
|
+
end
|
151
161
|
if _loaded?
|
152
162
|
_loaded.each_pair do |id, doc|
|
153
163
|
yield(doc)
|
data/lib/mongoid/threaded.rb
CHANGED
@@ -301,13 +301,14 @@ module Mongoid
|
|
301
301
|
# @example Get the field selection options.
|
302
302
|
# Threaded.selection
|
303
303
|
#
|
304
|
-
# @param [
|
304
|
+
# @param [ Integer ] criteria_instance_id The criteria instance id.
|
305
305
|
#
|
306
306
|
# @return [ Hash ] The field selection.
|
307
307
|
#
|
308
308
|
# @since 2.4.4
|
309
|
-
def selection(
|
310
|
-
Thread.current["[mongoid][
|
309
|
+
def selection(criteria_instance_id)
|
310
|
+
selections = Thread.current["[mongoid][selections]"]
|
311
|
+
selections[criteria_instance_id] if selections
|
311
312
|
end
|
312
313
|
|
313
314
|
# Set the field selection on the current thread.
|
@@ -322,7 +323,24 @@ module Mongoid
|
|
322
323
|
#
|
323
324
|
# @since 2.4.4
|
324
325
|
def set_selection(criteria_instance_id, value)
|
325
|
-
Thread.current["[mongoid][
|
326
|
+
Thread.current["[mongoid][selections]"] ||= {}
|
327
|
+
Thread.current["[mongoid][selections]"][criteria_instance_id] = value
|
328
|
+
end
|
329
|
+
|
330
|
+
# Delete the field selection on the current thread.
|
331
|
+
#
|
332
|
+
# @example Delete the field selection.
|
333
|
+
# Threaded.delete_selection(Person)
|
334
|
+
#
|
335
|
+
# @param [ Integer ] criteria_instance_id The criteria instance id.
|
336
|
+
#
|
337
|
+
# @return [ Boolean ] Whether there was a field selection.
|
338
|
+
#
|
339
|
+
# @since 3.0.7
|
340
|
+
def delete_selection(criteria_instance_id)
|
341
|
+
selections = Thread.current["[mongoid][selections]"]
|
342
|
+
return false unless selections
|
343
|
+
!!selections.delete(criteria_instance_id)
|
326
344
|
end
|
327
345
|
|
328
346
|
# Get the global session override.
|
@@ -167,8 +167,7 @@ module Mongoid
|
|
167
167
|
# @since 2.3.0
|
168
168
|
def scope(criteria, document, attribute)
|
169
169
|
Array.wrap(options[:scope]).each do |item|
|
170
|
-
|
171
|
-
name = document.aliased_fields[normalized] || normalized
|
170
|
+
name = document.database_field_name(item)
|
172
171
|
criteria = criteria.where(item => document.attributes[name])
|
173
172
|
end
|
174
173
|
criteria = criteria.where(deleted_at: nil) if document.paranoid?
|
data/lib/mongoid/version.rb
CHANGED
@@ -18,7 +18,15 @@ development:
|
|
18
18
|
# Change the default consistency model to :eventual or :strong.
|
19
19
|
# :eventual will send reads to secondaries, :strong sends everything
|
20
20
|
# to master. (default: :eventual)
|
21
|
-
consistency: :
|
21
|
+
# consistency: :eventual
|
22
|
+
|
23
|
+
# How many times Moped should attempt to retry an operation after
|
24
|
+
# failure. (default: 30)
|
25
|
+
# max_retries: 30
|
26
|
+
|
27
|
+
# The time in seconds that Moped should wait before retrying an
|
28
|
+
# operation on failure. (default: 1)
|
29
|
+
# retry_interval: 1
|
22
30
|
# Configure Mongoid specific options. (optional)
|
23
31
|
options:
|
24
32
|
# Configuration for whether or not to allow access to fields that do
|
@@ -66,3 +74,7 @@ test:
|
|
66
74
|
- localhost:27017
|
67
75
|
options:
|
68
76
|
consistency: :strong
|
77
|
+
# In the test environment we lower the retries and retry interval to
|
78
|
+
# low amounts for fast failures.
|
79
|
+
max_retries: 1
|
80
|
+
retry_interval: 0
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -352,7 +352,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
352
352
|
version: '0'
|
353
353
|
segments:
|
354
354
|
- 0
|
355
|
-
hash:
|
355
|
+
hash: 3436548235215749672
|
356
356
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
357
357
|
none: false
|
358
358
|
requirements:
|