mongoid 1.2.8 → 1.2.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.
Files changed (44) hide show
  1. data/Rakefile +1 -1
  2. data/VERSION +1 -1
  3. data/lib/mongoid.rb +2 -3
  4. data/lib/mongoid/associations.rb +5 -3
  5. data/lib/mongoid/associations/belongs_to_related.rb +6 -9
  6. data/lib/mongoid/associations/has_many.rb +2 -0
  7. data/lib/mongoid/associations/has_many_related.rb +10 -0
  8. data/lib/mongoid/attributes.rb +6 -1
  9. data/lib/mongoid/commands.rb +2 -10
  10. data/lib/mongoid/components.rb +11 -12
  11. data/lib/mongoid/contexts/enumerable.rb +21 -11
  12. data/lib/mongoid/contexts/mongo.rb +40 -1
  13. data/lib/mongoid/criteria.rb +3 -29
  14. data/lib/mongoid/criterion/inclusion.rb +2 -1
  15. data/lib/mongoid/document.rb +5 -6
  16. data/lib/mongoid/extensions.rb +10 -0
  17. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  18. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  19. data/lib/mongoid/{caching.rb → extras.rb} +26 -3
  20. data/lib/mongoid/field.rb +20 -7
  21. data/lib/mongoid/finders.rb +10 -80
  22. data/mongoid.gemspec +15 -13
  23. data/spec/integration/mongoid/document_spec.rb +1 -1
  24. data/spec/models/person.rb +1 -0
  25. data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +4 -0
  26. data/spec/unit/mongoid/associations/has_many_related_spec.rb +42 -13
  27. data/spec/unit/mongoid/associations/has_many_spec.rb +12 -7
  28. data/spec/unit/mongoid/associations_spec.rb +16 -0
  29. data/spec/unit/mongoid/attributes_spec.rb +23 -0
  30. data/spec/unit/mongoid/commands/destroy_spec.rb +3 -0
  31. data/spec/unit/mongoid/commands_spec.rb +4 -11
  32. data/spec/unit/mongoid/contexts/enumerable_spec.rb +16 -0
  33. data/spec/unit/mongoid/contexts/mongo_spec.rb +96 -0
  34. data/spec/unit/mongoid/criteria_spec.rb +11 -4
  35. data/spec/unit/mongoid/document_spec.rb +11 -0
  36. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +22 -0
  37. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
  38. data/spec/unit/mongoid/{enslavement_spec.rb → extras_spec.rb} +55 -2
  39. data/spec/unit/mongoid/field_spec.rb +62 -0
  40. data/spec/unit/mongoid/finders_spec.rb +36 -0
  41. metadata +69 -37
  42. data/HISTORY +0 -342
  43. data/lib/mongoid/enslavement.rb +0 -38
  44. data/spec/unit/mongoid/caching_spec.rb +0 -63
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ begin
15
15
  gem.add_dependency("activesupport", "<= 2.3.5")
16
16
  gem.add_dependency("mongo", ">= 0.18.3")
17
17
  gem.add_dependency("durran-validatable", ">= 2.0.1")
18
- gem.add_dependency("will_paginate", "< 3.0.pre")
18
+ gem.add_dependency("will_paginate", "< 2.9")
19
19
 
20
20
  gem.add_development_dependency("rspec", ">= 1.2.9")
21
21
  gem.add_development_dependency("mocha", ">= 0.9.8")
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.8
1
+ 1.2.9
@@ -24,7 +24,7 @@ require "rubygems"
24
24
  gem "activesupport", ">= 2.2.2", "<3.0.pre"
25
25
  gem "mongo", ">= 0.18.3"
26
26
  gem "durran-validatable", ">= 2.0.1"
27
- gem "will_paginate", ">= 2.3.11", "<3.0.pre"
27
+ gem "will_paginate", ">= 2.3.11", "< 2.9"
28
28
 
29
29
  require "delegate"
30
30
  require "observer"
@@ -39,7 +39,6 @@ require "will_paginate/collection"
39
39
  require "mongo"
40
40
  require "mongoid/associations"
41
41
  require "mongoid/attributes"
42
- require "mongoid/caching"
43
42
  require "mongoid/callbacks"
44
43
  require "mongoid/collection"
45
44
  require "mongoid/commands"
@@ -47,8 +46,8 @@ require "mongoid/config"
47
46
  require "mongoid/contexts"
48
47
  require "mongoid/criteria"
49
48
  require "mongoid/cursor"
50
- require "mongoid/enslavement"
51
49
  require "mongoid/extensions"
50
+ require "mongoid/extras"
52
51
  require "mongoid/errors"
53
52
  require "mongoid/factory"
54
53
  require "mongoid/field"
@@ -93,8 +93,8 @@ module Mongoid # :nodoc:
93
93
  options.merge(:name => name, :extend => block, :foreign_key => foreign_key(name, options))
94
94
  )
95
95
  add_association(Associations::BelongsToRelated, opts)
96
- field opts.foreign_key
97
- index opts.foreign_key unless self.embedded
96
+ field(opts.foreign_key, :type => Mongoid.use_object_ids ? Mongo::ObjectID : String)
97
+ index(opts.foreign_key) unless self.embedded
98
98
  end
99
99
 
100
100
  # Adds the association from a parent document to its children. The name
@@ -249,7 +249,9 @@ module Mongoid # :nodoc:
249
249
  name = options.name.to_s
250
250
  define_method("create_#{name}") do |attrs|
251
251
  document = send("build_#{name}", attrs)
252
- document.save; document
252
+ document.run_callbacks(:before_create)
253
+ document.save
254
+ document.run_callbacks(:after_create); document
253
255
  end
254
256
  end
255
257
 
@@ -41,19 +41,16 @@ module Mongoid #:nodoc:
41
41
  #
42
42
  # Options:
43
43
  #
44
- # related: The related object
45
- # parent: The parent +Document+ to update.
44
+ # target: The target(parent) object
45
+ # document: The +Document+ to update.
46
46
  # options: The association +Options+
47
47
  #
48
48
  # Example:
49
49
  #
50
- # <tt>BelongsToRelated.update(game, person, options)</tt>
51
- def update(target, parent, options)
52
- if target
53
- parent.send("#{options.foreign_key}=", target.id)
54
- return instantiate(parent, options, target)
55
- end
56
- target
50
+ # <tt>BelongsToRelated.update(person, game, options)</tt>
51
+ def update(target, document, options)
52
+ document.send("#{options.foreign_key}=", target ? target.id : nil)
53
+ instantiate(document, options, target)
57
54
  end
58
55
  end
59
56
 
@@ -54,7 +54,9 @@ module Mongoid #:nodoc:
54
54
  # Rhe newly created Document.
55
55
  def create(attrs = {}, type = nil)
56
56
  object = build(attrs, type)
57
+ object.run_callbacks(:before_create)
57
58
  object.save
59
+ object.run_callbacks(:after_create)
58
60
  object
59
61
  end
60
62
 
@@ -7,6 +7,7 @@ module Mongoid #:nodoc:
7
7
  # Appends the object to the +Array+, setting its parent in
8
8
  # the process.
9
9
  def <<(*objects)
10
+ load_target
10
11
  objects.flatten.each do |object|
11
12
  object.send("#{@foreign_key}=", @parent.id)
12
13
  @target << object
@@ -20,6 +21,7 @@ module Mongoid #:nodoc:
20
21
  #
21
22
  # Returns the newly created object.
22
23
  def build(attributes = {})
24
+ load_target
23
25
  name = @parent.class.to_s.underscore
24
26
  object = @klass.instantiate(attributes.merge(name => @parent))
25
27
  @target << object
@@ -39,7 +41,9 @@ module Mongoid #:nodoc:
39
41
  # Returns the newly created object.
40
42
  def create(attributes)
41
43
  object = build(attributes)
44
+ object.run_callbacks(:before_create)
42
45
  object.save
46
+ object.run_callbacks(:after_create)
43
47
  object
44
48
  end
45
49
 
@@ -69,6 +73,12 @@ module Mongoid #:nodoc:
69
73
  self << objects
70
74
  end
71
75
 
76
+ protected
77
+ # Load the target entries if the document is new.
78
+ def load_target
79
+ @target = @target.entries if @parent.new_record?
80
+ end
81
+
72
82
  class << self
73
83
  # Preferred method for creating the new +HasManyRelated+ association.
74
84
  #
@@ -42,7 +42,7 @@ module Mongoid #:nodoc:
42
42
  (attrs || {}).each_pair do |key, value|
43
43
  if set_allowed?(key)
44
44
  @attributes[key.to_s] = value
45
- else
45
+ elsif write_allowed?(key)
46
46
  send("#{key}=", value)
47
47
  end
48
48
  end
@@ -148,6 +148,11 @@ module Mongoid #:nodoc:
148
148
  end
149
149
  end
150
150
 
151
+ # Return true if writing to the given field is allowed
152
+ def write_allowed?(key)
153
+ return true unless fields[key.to_s]
154
+ fields[key.to_s].accessible?
155
+ end
151
156
  end
152
157
 
153
158
  module ClassMethods
@@ -62,11 +62,7 @@ module Mongoid #:nodoc:
62
62
  def save(validate = true)
63
63
  new = new_record?
64
64
  run_callbacks(:before_create) if new
65
- begin
66
- saved = Save.execute(self, validate)
67
- rescue Mongo::OperationFailure => e
68
- errors.add(:mongoid, e.message)
69
- end
65
+ saved = Save.execute(self, validate)
70
66
  run_callbacks(:after_create) if new && saved
71
67
  saved
72
68
  end
@@ -125,11 +121,7 @@ module Mongoid #:nodoc:
125
121
  # Returns: the +Document+.
126
122
  def create(attributes = {})
127
123
  document = new(attributes)
128
- begin
129
- Create.execute(document)
130
- rescue Mongo::OperationFailure => e
131
- document.errors.add(:mongoid, e.message)
132
- end
124
+ Create.execute(document)
133
125
  document
134
126
  end
135
127
 
@@ -5,20 +5,19 @@ module Mongoid #:nodoc
5
5
  base.class_eval do
6
6
  # All modules that a +Document+ is composed of are defined in this
7
7
  # module, to keep the document class from getting too cluttered.
8
- include Associations
9
- include Attributes
10
- include Caching
11
- include Callbacks
12
- include Commands
13
- include Enslavement
14
- include Fields
15
- include Indexes
16
- include Matchers
17
- include Memoization
8
+ include Mongoid::Associations
9
+ include Mongoid::Attributes
10
+ include Mongoid::Callbacks
11
+ include Mongoid::Commands
12
+ include Mongoid::Extras
13
+ include Mongoid::Fields
14
+ include Mongoid::Indexes
15
+ include Mongoid::Matchers
16
+ include Mongoid::Memoization
18
17
  include Observable
19
18
  include Validatable
20
- extend Finders
21
- extend NamedScope
19
+ extend Mongoid::Finders
20
+ extend Mongoid::NamedScope
22
21
  end
23
22
  end
24
23
  end
@@ -5,7 +5,7 @@ module Mongoid #:nodoc:
5
5
  include Ids, Paging
6
6
  attr_reader :criteria
7
7
 
8
- delegate :first, :last, :to => :execute
8
+ delegate :blank?, :empty?, :first, :last, :to => :execute
9
9
  delegate :documents, :options, :selector, :to => :criteria
10
10
 
11
11
  # Return aggregation counts of the grouped documents. This will count by
@@ -25,16 +25,6 @@ module Mongoid #:nodoc:
25
25
  @count ||= documents.size
26
26
  end
27
27
 
28
- # Groups the documents by the first field supplied in the field options.
29
- #
30
- # Returns:
31
- #
32
- # A +Hash+ with field values as keys, arrays of documents as values.
33
- def group
34
- field = options[:fields].first
35
- documents.group_by { |doc| doc.send(field) }
36
- end
37
-
38
28
  # Enumerable implementation of execute. Returns matching documents for
39
29
  # the selector, and adds options if supplied.
40
30
  #
@@ -45,6 +35,16 @@ module Mongoid #:nodoc:
45
35
  limit(documents.select { |document| document.matches?(selector) })
46
36
  end
47
37
 
38
+ # Groups the documents by the first field supplied in the field options.
39
+ #
40
+ # Returns:
41
+ #
42
+ # A +Hash+ with field values as keys, arrays of documents as values.
43
+ def group
44
+ field = options[:fields].first
45
+ documents.group_by { |doc| doc.send(field) }
46
+ end
47
+
48
48
  # Create the new enumerable context. This will need the selector and
49
49
  # options from a +Criteria+ and a documents array that is the underlying
50
50
  # array of embedded documents from a has many association.
@@ -56,6 +56,16 @@ module Mongoid #:nodoc:
56
56
  @criteria = criteria
57
57
  end
58
58
 
59
+ # Iterate over each +Document+ in the results. This can take an optional
60
+ # block to pass to each argument in the results.
61
+ #
62
+ # Example:
63
+ #
64
+ # <tt>context.iterate { |doc| p doc }</tt>
65
+ def iterate(&block)
66
+ execute.each(&block)
67
+ end
68
+
59
69
  # Get the largest value for the field in all the documents.
60
70
  #
61
71
  # Returns:
@@ -23,6 +23,18 @@ module Mongoid #:nodoc:
23
23
  klass.collection.group(options[:fields], selector, { :count => 0 }, Javascript.aggregate, true)
24
24
  end
25
25
 
26
+ # Determine if the context is empty or blank given the criteria. Will
27
+ # perform a quick has_one asking only for the id.
28
+ #
29
+ # Example:
30
+ #
31
+ # <tt>context.blank?</tt>
32
+ def blank?
33
+ klass.collection.find_one(selector, { :fields => [ :_id ] }).nil?
34
+ end
35
+
36
+ alias :empty? :blank?
37
+
26
38
  # Get the count of matching documents in the database for the context.
27
39
  #
28
40
  # Example:
@@ -43,7 +55,7 @@ module Mongoid #:nodoc:
43
55
  #
44
56
  # Example:
45
57
  #
46
- # <tt>mongo.execute</tt>
58
+ # <tt>context.execute</tt>
47
59
  #
48
60
  # Returns:
49
61
  #
@@ -100,6 +112,19 @@ module Mongoid #:nodoc:
100
112
  criteria.cache if klass.cached?
101
113
  end
102
114
 
115
+ # Iterate over each +Document+ in the results. This can take an optional
116
+ # block to pass to each argument in the results.
117
+ #
118
+ # Example:
119
+ #
120
+ # <tt>context.iterate { |doc| p doc }</tt>
121
+ def iterate(&block)
122
+ return caching(&block) if criteria.cached?
123
+ if block_given?
124
+ execute.each { |doc| yield doc }
125
+ end
126
+ end
127
+
103
128
  # Return the last result for the +Context+. Essentially does a find_one on
104
129
  # the collection with the sorting reversed. If no sorting parameters have
105
130
  # been provided it will default to ids.
@@ -214,6 +239,20 @@ module Mongoid #:nodoc:
214
239
  options.dup
215
240
  end
216
241
 
242
+ protected
243
+
244
+ # Iterate over each +Document+ in the results and cache the collection.
245
+ def caching(&block)
246
+ if defined? @collection
247
+ @collection.each(&block)
248
+ else
249
+ @collection = []
250
+ execute.each do |doc|
251
+ @collection << doc
252
+ yield doc if block_given?
253
+ end
254
+ end
255
+ end
217
256
  end
218
257
  end
219
258
  end
@@ -31,7 +31,9 @@ module Mongoid #:nodoc:
31
31
 
32
32
  delegate \
33
33
  :aggregate,
34
+ :blank?,
34
35
  :count,
36
+ :empty?,
35
37
  :execute,
36
38
  :first,
37
39
  :group,
@@ -76,17 +78,6 @@ module Mongoid #:nodoc:
76
78
  end
77
79
  end
78
80
 
79
- # Returns true if the criteria is empty.
80
- #
81
- # Example:
82
- #
83
- # <tt>criteria.blank?</tt>
84
- def blank?
85
- count < 1
86
- end
87
-
88
- alias :empty? :blank?
89
-
90
81
  # Return or create the context in which this criteria should be executed.
91
82
  #
92
83
  # This will return an Enumerable context if the class is embedded,
@@ -102,10 +93,7 @@ module Mongoid #:nodoc:
102
93
  #
103
94
  # <tt>criteria.each { |doc| p doc }</tt>
104
95
  def each(&block)
105
- return caching(&block) if cached?
106
- if block_given?
107
- execute.each { |doc| yield doc }
108
- end
96
+ context.iterate(&block)
109
97
  self
110
98
  end
111
99
 
@@ -213,20 +201,6 @@ module Mongoid #:nodoc:
213
201
 
214
202
  protected
215
203
 
216
- # Iterate over each +Document+ in the results and cache the collection.
217
- def caching(&block)
218
- @collection ||= execute
219
- if block_given?
220
- docs = []
221
- @collection.each do |doc|
222
- docs << doc
223
- yield doc
224
- end
225
- @collection = docs
226
- end
227
- self
228
- end
229
-
230
204
  # Filters the unused options out of the options +Hash+. Currently this
231
205
  # takes into account the "page" and "per_page" options that would be passed
232
206
  # in if using will_paginate.
@@ -22,6 +22,7 @@ module Mongoid #:nodoc:
22
22
  def all(attributes = {})
23
23
  update_selector(attributes, "$all")
24
24
  end
25
+ alias :all_in :all
25
26
 
26
27
  # Adds a criterion to the +Criteria+ that specifies values that must
27
28
  # be matched in order to return results. This is similar to a SQL "WHERE"
@@ -61,7 +62,7 @@ module Mongoid #:nodoc:
61
62
  def in(attributes = {})
62
63
  update_selector(attributes, "$in")
63
64
  end
64
- alias any_in in
65
+ alias :any_in :in
65
66
 
66
67
  # Adds a criterion to the +Criteria+ that specifies values that must
67
68
  # be matched in order to return results. This is similar to a SQL "WHERE"
@@ -78,8 +78,6 @@ module Mongoid #:nodoc:
78
78
  #
79
79
  # class Person
80
80
  # include Mongoid::Document
81
- # field :first_name
82
- # field :last_name
83
81
  # key :first_name, :last_name
84
82
  # end
85
83
  def key(*fields)
@@ -132,10 +130,6 @@ module Mongoid #:nodoc:
132
130
  #
133
131
  # parent: The +Document+ to assimilate with.
134
132
  # options: The association +Options+ for the child.
135
- #
136
- # Example:
137
- #
138
- # <tt>name.assimilate(person, options)</tt>
139
133
  def assimilate(parent, options)
140
134
  parentize(parent, options.name); notify; self
141
135
  end
@@ -193,6 +187,11 @@ module Mongoid #:nodoc:
193
187
  @new_record = saved
194
188
  end
195
189
 
190
+ # Checks if the document has been saved to the database.
191
+ def persisted?
192
+ !new_record?
193
+ end
194
+
196
195
  # Set the changed state of the +Document+ then notify observers that it has changed.
197
196
  #
198
197
  # Example: