mongoid 2.0.0.beta.14 → 2.0.0.beta.15

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.
@@ -64,6 +64,7 @@ require "mongoid/hierarchy"
64
64
  require "mongoid/identity"
65
65
  require "mongoid/indexes"
66
66
  require "mongoid/javascript"
67
+ require "mongoid/json"
67
68
  require "mongoid/keys"
68
69
  require "mongoid/logger"
69
70
  require "mongoid/matchers"
@@ -20,8 +20,9 @@ module Mongoid # :nodoc:
20
20
  cattr_accessor :embedded
21
21
  self.embedded = false
22
22
 
23
- class_inheritable_accessor :associations
23
+ class_inheritable_accessor :associations, :cascades
24
24
  self.associations = {}
25
+ self.cascades = {}
25
26
 
26
27
  delegate :embedded, :embedded?, :to => "self.class"
27
28
  end
@@ -57,8 +58,8 @@ module Mongoid # :nodoc:
57
58
  next unless association.macro == :referenced_in
58
59
  foreign_key = association.options.foreign_key
59
60
  if send(foreign_key).nil?
60
- target = send(name)
61
- send("#{foreign_key}=", target ? target.id : nil)
61
+ proxy = send(name)
62
+ send("#{foreign_key}=", proxy && proxy.target ? proxy.id : nil)
62
63
  end
63
64
  end
64
65
  end
@@ -204,6 +205,7 @@ module Mongoid # :nodoc:
204
205
  set_callback :save, :before do |document|
205
206
  document.update_associations(name)
206
207
  end
208
+ add_cascade(name, options)
207
209
  end
208
210
 
209
211
  alias :has_many_related :references_many
@@ -223,10 +225,14 @@ module Mongoid # :nodoc:
223
225
  # end
224
226
  def references_one(name, options = {}, &block)
225
227
  opts = optionize(name, options, constraint(name, options, :one), &block)
226
- associate(Associations::ReferencesOne, opts)
228
+ type = Associations::ReferencesOne
229
+ associate(type, opts)
230
+ add_builder(type, opts)
231
+ add_creator(type, opts)
227
232
  set_callback :save, :before do |document|
228
233
  document.update_association(name)
229
234
  end
235
+ add_cascade(name, options)
230
236
  end
231
237
 
232
238
  alias :has_one_related :references_one
@@ -269,7 +275,20 @@ module Mongoid # :nodoc:
269
275
  def associate(type, options)
270
276
  name = options.name.to_s
271
277
  associations[name] = MetaData.new(type, options)
272
- define_method(name) { memoized(name) { type.instantiate(self, options) } }
278
+ define_method(name) do
279
+ memoized(name) do
280
+ proxy = type.new(self, options)
281
+ case proxy
282
+ when Associations::ReferencesOne,
283
+ Associations::EmbedsOne,
284
+ Associations::ReferencedIn,
285
+ Associations::EmbeddedIn
286
+ proxy.target ? proxy : nil
287
+ else
288
+ proxy
289
+ end
290
+ end
291
+ end
273
292
  define_method("#{name}=") do |object|
274
293
  unmemoize(name)
275
294
  memoized(name) { type.update(object, self, options) }
@@ -284,10 +303,10 @@ module Mongoid # :nodoc:
284
303
  attrs = params[0]
285
304
  attr_options = params[1] || {}
286
305
  reset(name) do
287
- unless type == Associations::EmbedsOne && attr_options[:update_only]
288
- type.new(self, (attrs || {}).stringify_keys, options)
289
- end
290
- end
306
+ proxy = type.new(self, options)
307
+ proxy.build((attrs || {}).stringify_keys)
308
+ proxy
309
+ end unless type == Associations::EmbedsOne && attr_options[:update_only]
291
310
  end
292
311
  end
293
312
 
@@ -304,6 +323,12 @@ module Mongoid # :nodoc:
304
323
  end
305
324
  end
306
325
 
326
+ # Create the callbacks for dependent deletes and destroys.
327
+ def add_cascade(name, options)
328
+ dependent = options[:dependent]
329
+ self.cascades[name] = dependent if dependent
330
+ end
331
+
307
332
  # build the options given the params.
308
333
  def optionize(name, options, foreign_key, &block)
309
334
  Associations::Options.new(
@@ -14,10 +14,16 @@ module Mongoid #:nodoc:
14
14
  #
15
15
  # Options:
16
16
  #
17
- # target: The parent +Document+
17
+ # document: The child +Document+
18
18
  # options: The association options
19
- def initialize(target, options)
20
- @target, @options = target, options
19
+ def initialize(document, options, target = nil)
20
+ if target
21
+ inverse = determine_name(target, options)
22
+ document.parentize(target, inverse)
23
+ document.notify
24
+ target.unmemoize(inverse)
25
+ end
26
+ @target, @options = document._parent, options
21
27
  extends(options)
22
28
  end
23
29
 
@@ -28,20 +34,14 @@ module Mongoid #:nodoc:
28
34
  @target
29
35
  end
30
36
 
31
- class << self
32
- # Creates the new association by setting the internal
33
- # document as the passed in Document. This should be the
34
- # parent.
35
- #
36
- # Options:
37
- #
38
- # document: The parent +Document+
39
- # options: The association options
40
- def instantiate(document, options)
41
- target = document._parent
42
- target.nil? ? nil : new(target, options)
43
- end
37
+ protected
38
+ def determine_name(target, options)
39
+ inverse = options.inverse_of
40
+ return inverse unless inverse.is_a?(Array)
41
+ inverse.detect { |name| target.respond_to?(name) }
42
+ end
44
43
 
44
+ class << self
45
45
  # Returns the macro used to create the association.
46
46
  def macro
47
47
  :embedded_in
@@ -55,18 +55,7 @@ module Mongoid #:nodoc:
55
55
  #
56
56
  # A new +EmbeddedIn+ association proxy.
57
57
  def update(target, child, options)
58
- inverse = determine_name(target, options)
59
- child.parentize(target, inverse)
60
- child.notify
61
- target.unmemoize(inverse)
62
- instantiate(child, options)
63
- end
64
-
65
- protected
66
- def determine_name(target, options)
67
- inverse = options.inverse_of
68
- return inverse unless inverse.is_a?(Array)
69
- inverse.detect { |name| target.respond_to?(name) }
58
+ new(child, options, target)
70
59
  end
71
60
  end
72
61
  end
@@ -250,18 +250,6 @@ module Mongoid #:nodoc:
250
250
  end
251
251
 
252
252
  class << self
253
-
254
- # Preferred method of creating a new +EmbedsMany+ association. It will
255
- # delegate to new.
256
- #
257
- # Options:
258
- #
259
- # document: The parent +Document+
260
- # options: The association options
261
- def instantiate(document, options, target_array = nil)
262
- new(document, options, target_array)
263
- end
264
-
265
253
  # Returns the macro used to create the association.
266
254
  def macro
267
255
  :embeds_many
@@ -274,9 +262,9 @@ module Mongoid #:nodoc:
274
262
  parent.raw_attributes.delete(options.name)
275
263
  children.assimilate(parent, options)
276
264
  if children && children.first.is_a?(Mongoid::Document)
277
- instantiate(parent, options, children)
265
+ new(parent, options, children)
278
266
  else
279
- instantiate(parent, options)
267
+ new(parent, options)
280
268
  end
281
269
  end
282
270
  end
@@ -10,6 +10,14 @@ module Mongoid #:nodoc:
10
10
  @target = attrs.assimilate(@parent, @options, type); self
11
11
  end
12
12
 
13
+ # Replaces the target with a new object
14
+ #
15
+ # Returns the association proxy
16
+ def replace(obj)
17
+ @target = obj
18
+ self
19
+ end
20
+
13
21
  # Creates the new association by finding the attributes in
14
22
  # the parent document with its name, and instantiating a
15
23
  # new document for it.
@@ -26,9 +34,16 @@ module Mongoid #:nodoc:
26
34
  # Returns:
27
35
  #
28
36
  # A new +HashOne+ association proxy.
29
- def initialize(document, attrs, options, target = nil)
37
+ def initialize(document, options, target = nil)
30
38
  @parent, @options = document, options
31
- @target = target ? target : attrs.assimilate(@parent, @options, attrs.klass)
39
+
40
+ if target
41
+ replace(target)
42
+ else
43
+ attributes = document.raw_attributes[options.name]
44
+ build(attributes) unless attributes.blank?
45
+ end
46
+
32
47
  extends(options)
33
48
  end
34
49
 
@@ -49,23 +64,6 @@ module Mongoid #:nodoc:
49
64
  end
50
65
 
51
66
  class << self
52
- # Preferred method of instantiating a new +EmbedsOne+, since nil values
53
- # will be handled properly.
54
- #
55
- # Options:
56
- #
57
- # document: The parent +Document+
58
- # options: The association options.
59
- #
60
- # Returns:
61
- #
62
- # A new +EmbedsOne+ association proxy.
63
- def instantiate(document, options, target = nil)
64
- attributes = document.raw_attributes[options.name]
65
- return nil if attributes.blank? && target.nil?
66
- new(document, attributes, options, target)
67
- end
68
-
69
67
  # Returns the macro used to create the association.
70
68
  def macro
71
69
  :embeds_one
@@ -89,7 +87,7 @@ module Mongoid #:nodoc:
89
87
  # A new +EmbedsOne+ association proxy.
90
88
  def update(child, parent, options)
91
89
  child.assimilate(parent, options)
92
- instantiate(parent, options, child.is_a?(Hash) ? nil : child)
90
+ new(parent, options, child.is_a?(Hash) ? nil : child)
93
91
  end
94
92
  end
95
93
  end
@@ -9,6 +9,12 @@ module Mongoid #:nodoc:
9
9
  self.merge!(attributes)
10
10
  end
11
11
 
12
+ # For relational associations we want to know if we cascade deletes or
13
+ # destroys to associations.
14
+ def dependent
15
+ self[:dependent]
16
+ end
17
+
12
18
  # Returns the extension if it exists, nil if not.
13
19
  def extension
14
20
  self[:extend]
@@ -11,27 +11,28 @@ module Mongoid #:nodoc:
11
11
  #
12
12
  # document: The +Document+ that contains the relationship.
13
13
  # options: The association +Options+.
14
- def initialize(document, foreign_key, options, target = nil)
14
+ def initialize(document, options, target = nil)
15
15
  @options = options
16
- @target = target || options.klass.find(foreign_key)
17
- extends(options)
18
- end
19
16
 
20
- class << self
21
- # Instantiate a new +ReferencedIn+ or return nil if the foreign key is
22
- # nil. It is preferrable to use this method over the traditional call
23
- # to new.
24
- #
25
- # Options:
26
- #
27
- # document: The +Document+ that contains the relationship.
28
- # options: The association +Options+.
29
- def instantiate(document, options, target = nil)
17
+ if target
18
+ replace(target)
19
+ else
30
20
  foreign_key = document.send(options.foreign_key)
31
- return nil if foreign_key.blank? && target.nil?
32
- new(document, foreign_key, options, target)
21
+ replace(options.klass.find(foreign_key)) unless foreign_key.blank?
33
22
  end
34
23
 
24
+ extends(options)
25
+ end
26
+
27
+ # Replaces the target with a new object
28
+ #
29
+ # Returns the association proxy
30
+ def replace(obj)
31
+ @target = obj
32
+ self
33
+ end
34
+
35
+ class << self
35
36
  # Returns the macro used to create the association.
36
37
  def macro
37
38
  :referenced_in
@@ -51,7 +52,7 @@ module Mongoid #:nodoc:
51
52
  # <tt>ReferencedIn.update(person, game, options)</tt>
52
53
  def update(target, document, options)
53
54
  document.send("#{options.foreign_key}=", target ? target.id : nil)
54
- instantiate(document, options, target)
55
+ new(document, options, target)
55
56
  end
56
57
  end
57
58
  end
@@ -86,7 +86,7 @@ module Mongoid #:nodoc:
86
86
  #
87
87
  # Example:
88
88
  #
89
- # <tt>RelatesToManyAsArray.update(preferences, person, options)</tt>
89
+ # <tt>ReferencesManyAsArray.update(preferences, person, options)</tt>
90
90
  def update(target, document, options)
91
91
  target.each do |child|
92
92
  document.send(options.name) << child
@@ -5,19 +5,13 @@ module Mongoid #:nodoc:
5
5
  # separate collection or database.
6
6
  class ReferencesOne < Proxy
7
7
 
8
- delegate :nil?, :to => :target
9
-
10
8
  # Builds a new Document and sets it as the association.
11
9
  #
12
10
  # Returns the newly created object.
13
11
  def build(attributes = {})
14
- @target = @klass.instantiate(attributes)
15
- inverse = @target.associations.values.detect do |metadata|
16
- metadata.options.klass == @parent.class
17
- end
18
- name = inverse.name
19
- @target.send("#{name}=", @parent)
20
- @target
12
+ target = @klass.instantiate(attributes)
13
+ replace(target)
14
+ target
21
15
  end
22
16
 
23
17
  # Builds a new Document and sets it as the association, then saves the
@@ -28,6 +22,20 @@ module Mongoid #:nodoc:
28
22
  build(attributes).tap(&:save)
29
23
  end
30
24
 
25
+ # Replaces the target with a new object
26
+ #
27
+ # Returns the association proxy
28
+ def replace(obj)
29
+ @target = obj
30
+ inverse = @target.associations.values.detect do |metadata|
31
+ metadata.options.klass == @parent.class
32
+ end
33
+ name = inverse.name
34
+ @target.send("#{name}=", @parent)
35
+
36
+ self
37
+ end
38
+
31
39
  # Initializing a related association only requires looking up the objects
32
40
  # by their ids.
33
41
  #
@@ -35,10 +43,10 @@ module Mongoid #:nodoc:
35
43
  #
36
44
  # document: The +Document+ that contains the relationship.
37
45
  # options: The association +Options+.
38
- def initialize(document, options, target = nil)
46
+ def initialize(document, options)
39
47
  @parent, @klass = document, options.klass
40
48
  @foreign_key = options.foreign_key
41
- @target = target || @klass.first(:conditions => { @foreign_key => @parent.id })
49
+ @target = @klass.first(:conditions => { @foreign_key => @parent.id })
42
50
  extends(options)
43
51
  end
44
52
 
@@ -57,16 +65,6 @@ module Mongoid #:nodoc:
57
65
  end
58
66
 
59
67
  class << self
60
- # Preferred method for creating the new +RelatesToMany+ association.
61
- #
62
- # Options:
63
- #
64
- # document: The +Document+ that contains the relationship.
65
- # options: The association +Options+.
66
- def instantiate(document, options, target = nil)
67
- new(document, options, target)
68
- end
69
-
70
68
  # Returns the macro used to create the association.
71
69
  def macro
72
70
  :references_one
@@ -87,10 +85,10 @@ module Mongoid #:nodoc:
87
85
  def update(target, document, options)
88
86
  if target
89
87
  name = document.class.to_s.underscore
90
- target.send("#{name}=", document)
91
- return instantiate(document, options, target)
88
+ proxy = new(document, options)
89
+ proxy.replace(target)
92
90
  end
93
- target
91
+ proxy
94
92
  end
95
93
  end
96
94
  end
@@ -20,6 +20,7 @@ module Mongoid #:nodoc
20
20
  include Mongoid::Fields
21
21
  include Mongoid::Hierarchy
22
22
  include Mongoid::Indexes
23
+ include Mongoid::JSON
23
24
  include Mongoid::Keys
24
25
  include Mongoid::Matchers
25
26
  include Mongoid::Memoization
@@ -7,6 +7,7 @@ module Mongoid #:nodoc
7
7
 
8
8
  attr_accessor \
9
9
  :allow_dynamic_fields,
10
+ :include_root_in_json,
10
11
  :reconnect_time,
11
12
  :parameterize_keys,
12
13
  :persist_in_safe_mode,
@@ -74,12 +75,10 @@ module Mongoid #:nodoc
74
75
  # The master +Mongo::DB+
75
76
  def master
76
77
  raise Errors::InvalidDatabase.new(nil) unless @master
77
-
78
78
  if @reconnect
79
79
  @reconnect = false
80
80
  reconnect!
81
81
  end
82
-
83
82
  @master
84
83
  end
85
84
 
@@ -193,6 +192,7 @@ module Mongoid #:nodoc
193
192
  # <tt>config.reset</tt>
194
193
  def reset
195
194
  @allow_dynamic_fields = true
195
+ @include_root_in_json = false
196
196
  @parameterize_keys = true
197
197
  @persist_in_safe_mode = false
198
198
  @raise_not_found_error = true
@@ -7,21 +7,6 @@ module Mongoid #:nodoc:
7
7
 
8
8
  attr_accessor :association_name
9
9
  attr_reader :new_record
10
-
11
- unless self.instance_of?(Class) and self.name == ""
12
- (@@descendants ||= {})[self] = :seen
13
- end
14
- end
15
-
16
- class << self
17
-
18
- # Returns all classes that have included Mongoid::Document.
19
- #
20
- # This will not get subclasses of the top level models, for those we will
21
- # use Class.descendents in the rake task for indexes.
22
- def descendants
23
- (@@descendants ||= {}).keys
24
- end
25
10
  end
26
11
 
27
12
  module ClassMethods #:nodoc:
@@ -31,8 +16,8 @@ module Mongoid #:nodoc:
31
16
  # This method must remain in the +Document+ module, even though its
32
17
  # behavior affects items in the Hierarchy module.
33
18
  def inherited(subclass)
34
- super(subclass)
35
19
  self.hereditary = true
20
+ super
36
21
  end
37
22
 
38
23
  # Instantiate a new object, only when loaded from the database or when
@@ -114,4 +114,8 @@ end
114
114
 
115
115
  class BSON::ObjectID #:nodoc
116
116
  extend Mongoid::Extensions::ObjectID::Conversions
117
+
118
+ def as_json(options = nil)
119
+ to_s
120
+ end
117
121
  end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ # This module is for hooking in to +ActiveModel+s serialization to let
4
+ # configuring the ability to include the root in JSON happen from the Mongoid
5
+ # config.
6
+ module JSON
7
+ extend ActiveSupport::Concern
8
+
9
+ # We need to redefine where the JSON configuration is getting defined,
10
+ # similar to +ActiveRecord+.
11
+ included do
12
+ undef_method :include_root_in_json
13
+ delegate :include_root_in_json, :to => ::Mongoid
14
+ end
15
+ end
16
+ end
@@ -26,7 +26,7 @@ module Mongoid #:nodoc:
26
26
  #
27
27
  # <tt>document.destroy</tt>
28
28
  def destroy(options = {})
29
- run_callbacks(:destroy) { self.destroyed = true if _remove(options) }
29
+ run_callbacks(:destroy) { _remove(options) }
30
30
  end
31
31
 
32
32
  # Insert a new +Document+ into the database. Will return the document
@@ -47,7 +47,10 @@ module Mongoid #:nodoc:
47
47
  #
48
48
  # TODO: Will get rid of other #remove once observable pattern killed.
49
49
  def _remove(options = {})
50
- Remove.new(self, options).persist
50
+ if Remove.new(self, options).persist
51
+ self.destroyed = true
52
+ cascading_remove!
53
+ end; true
51
54
  end
52
55
 
53
56
  alias :delete :_remove
@@ -131,6 +134,19 @@ module Mongoid #:nodoc:
131
134
  # <tt>document.save</tt>
132
135
  alias :save :upsert
133
136
 
137
+ protected
138
+
139
+ # Perform all cascading deletes or destroys.
140
+ def cascading_remove!
141
+ cascades.each do |name, option|
142
+ association = send(name)
143
+ if association
144
+ documents = association.target.to_a
145
+ documents.each { |doc| doc.send(option) }
146
+ end
147
+ end
148
+ end
149
+
134
150
  module ClassMethods #:nodoc:
135
151
 
136
152
  # Create a new +Document+. This will instantiate a new document and
@@ -35,7 +35,7 @@ module Mongoid #:nodoc:
35
35
  ).persist
36
36
  else
37
37
  @collection.remove({ :_id => @document.id }, @options)
38
- end
38
+ end; true
39
39
  end
40
40
  end
41
41
  end
@@ -57,7 +57,18 @@ namespace :db do
57
57
  if not Rake::Task.task_defined?("db:create_indexes")
58
58
  desc 'Create the indexes defined on your mongoid models'
59
59
  task :create_indexes => :environment do
60
- ::Rails::Mongoid.index_children(Mongoid::Document.descendants)
60
+ documents = []
61
+ Dir.glob("app/models/**/*.rb").sort.each do |file|
62
+ model = file.match(/\/(\w+).rb$/)[1]
63
+ klass = model.classify.constantize
64
+ begin
65
+ documents << klass unless klass.embedded
66
+ rescue => e
67
+ # Just for non-mongoid objects that dont have the embedded
68
+ # attribute at the class level.
69
+ end
70
+ end
71
+ ::Rails::Mongoid.index_children(documents)
61
72
  end
62
73
  end
63
74
 
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
- VERSION = "2.0.0.beta.14"
3
+ VERSION = "2.0.0.beta.15"
4
4
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid
3
3
  version: !ruby/object:Gem::Version
4
- hash: 62196479
4
+ hash: 62196477
5
5
  prerelease: true
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
9
  - 0
10
10
  - beta
11
- - 14
12
- version: 2.0.0.beta.14
11
+ - 15
12
+ version: 2.0.0.beta.15
13
13
  platform: ruby
14
14
  authors:
15
15
  - Durran Jordan
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2010-07-27 00:00:00 -04:00
20
+ date: 2010-07-29 00:00:00 -04:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
@@ -253,6 +253,7 @@ files:
253
253
  - lib/mongoid/indexes.rb
254
254
  - lib/mongoid/javascript/functions.yml
255
255
  - lib/mongoid/javascript.rb
256
+ - lib/mongoid/json.rb
256
257
  - lib/mongoid/keys.rb
257
258
  - lib/mongoid/logger.rb
258
259
  - lib/mongoid/matchers/all.rb