mongoid-locomotive 2.0.0.beta9
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/MIT_LICENSE +20 -0
- data/README.rdoc +47 -0
- data/lib/mongoid.rb +141 -0
- data/lib/mongoid/associations.rb +306 -0
- data/lib/mongoid/associations/embedded_in.rb +74 -0
- data/lib/mongoid/associations/embeds_many.rb +280 -0
- data/lib/mongoid/associations/embeds_one.rb +97 -0
- data/lib/mongoid/associations/foreign_key.rb +35 -0
- data/lib/mongoid/associations/meta_data.rb +38 -0
- data/lib/mongoid/associations/options.rb +62 -0
- data/lib/mongoid/associations/proxy.rb +33 -0
- data/lib/mongoid/associations/referenced_in.rb +59 -0
- data/lib/mongoid/associations/references_many.rb +245 -0
- data/lib/mongoid/associations/references_many_as_array.rb +78 -0
- data/lib/mongoid/associations/references_one.rb +99 -0
- data/lib/mongoid/atomicity.rb +55 -0
- data/lib/mongoid/attributes.rb +242 -0
- data/lib/mongoid/callbacks.rb +21 -0
- data/lib/mongoid/collection.rb +120 -0
- data/lib/mongoid/collections.rb +71 -0
- data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
- data/lib/mongoid/collections/master.rb +29 -0
- data/lib/mongoid/collections/operations.rb +41 -0
- data/lib/mongoid/collections/slaves.rb +45 -0
- data/lib/mongoid/components.rb +34 -0
- data/lib/mongoid/config.rb +263 -0
- data/lib/mongoid/contexts.rb +24 -0
- data/lib/mongoid/contexts/enumerable.rb +156 -0
- data/lib/mongoid/contexts/ids.rb +25 -0
- data/lib/mongoid/contexts/mongo.rb +285 -0
- data/lib/mongoid/contexts/paging.rb +50 -0
- data/lib/mongoid/criteria.rb +248 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +110 -0
- data/lib/mongoid/criterion/optional.rb +189 -0
- data/lib/mongoid/cursor.rb +81 -0
- data/lib/mongoid/deprecation.rb +21 -0
- data/lib/mongoid/dirty.rb +252 -0
- data/lib/mongoid/document.rb +210 -0
- data/lib/mongoid/errors.rb +131 -0
- data/lib/mongoid/extensions.rb +115 -0
- data/lib/mongoid/extensions/array/accessors.rb +17 -0
- data/lib/mongoid/extensions/array/assimilation.rb +26 -0
- data/lib/mongoid/extensions/array/conversions.rb +23 -0
- data/lib/mongoid/extensions/array/parentization.rb +13 -0
- data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
- data/lib/mongoid/extensions/binary/conversions.rb +17 -0
- data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
- data/lib/mongoid/extensions/date/conversions.rb +24 -0
- data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
- data/lib/mongoid/extensions/false_class/equality.rb +13 -0
- data/lib/mongoid/extensions/float/conversions.rb +20 -0
- data/lib/mongoid/extensions/hash/accessors.rb +42 -0
- data/lib/mongoid/extensions/hash/assimilation.rb +40 -0
- data/lib/mongoid/extensions/hash/conversions.rb +42 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
- data/lib/mongoid/extensions/hash/scoping.rb +12 -0
- data/lib/mongoid/extensions/integer/conversions.rb +20 -0
- data/lib/mongoid/extensions/nil/assimilation.rb +17 -0
- data/lib/mongoid/extensions/object/conversions.rb +21 -0
- data/lib/mongoid/extensions/objectid/conversions.rb +15 -0
- data/lib/mongoid/extensions/proc/scoping.rb +12 -0
- data/lib/mongoid/extensions/set/conversions.rb +20 -0
- data/lib/mongoid/extensions/string/conversions.rb +15 -0
- data/lib/mongoid/extensions/string/inflections.rb +97 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
- data/lib/mongoid/extensions/time_conversions.rb +35 -0
- data/lib/mongoid/extensions/true_class/equality.rb +13 -0
- data/lib/mongoid/extras.rb +61 -0
- data/lib/mongoid/factory.rb +20 -0
- data/lib/mongoid/field.rb +83 -0
- data/lib/mongoid/fields.rb +62 -0
- data/lib/mongoid/finders.rb +145 -0
- data/lib/mongoid/hierarchy.rb +74 -0
- data/lib/mongoid/identity.rb +47 -0
- data/lib/mongoid/indexes.rb +27 -0
- data/lib/mongoid/javascript.rb +21 -0
- data/lib/mongoid/javascript/functions.yml +37 -0
- data/lib/mongoid/logger.rb +19 -0
- data/lib/mongoid/matchers.rb +35 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +26 -0
- data/lib/mongoid/matchers/exists.rb +13 -0
- data/lib/mongoid/matchers/gt.rb +11 -0
- data/lib/mongoid/matchers/gte.rb +11 -0
- data/lib/mongoid/matchers/in.rb +11 -0
- data/lib/mongoid/matchers/lt.rb +11 -0
- data/lib/mongoid/matchers/lte.rb +11 -0
- data/lib/mongoid/matchers/ne.rb +11 -0
- data/lib/mongoid/matchers/nin.rb +11 -0
- data/lib/mongoid/matchers/size.rb +11 -0
- data/lib/mongoid/memoization.rb +33 -0
- data/lib/mongoid/named_scope.rb +37 -0
- data/lib/mongoid/paranoia.rb +106 -0
- data/lib/mongoid/paths.rb +61 -0
- data/lib/mongoid/persistence.rb +216 -0
- data/lib/mongoid/persistence/command.rb +39 -0
- data/lib/mongoid/persistence/insert.rb +48 -0
- data/lib/mongoid/persistence/insert_embedded.rb +44 -0
- data/lib/mongoid/persistence/remove.rb +39 -0
- data/lib/mongoid/persistence/remove_all.rb +38 -0
- data/lib/mongoid/persistence/remove_embedded.rb +50 -0
- data/lib/mongoid/persistence/update.rb +71 -0
- data/lib/mongoid/railtie.rb +67 -0
- data/lib/mongoid/railties/database.rake +60 -0
- data/lib/mongoid/scope.rb +75 -0
- data/lib/mongoid/state.rb +32 -0
- data/lib/mongoid/timestamps.rb +27 -0
- data/lib/mongoid/validations.rb +51 -0
- data/lib/mongoid/validations/associated.rb +32 -0
- data/lib/mongoid/validations/locale/en.yml +5 -0
- data/lib/mongoid/validations/uniqueness.rb +56 -0
- data/lib/mongoid/version.rb +4 -0
- data/lib/mongoid/versioning.rb +26 -0
- data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +24 -0
- data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
- data/lib/rails/generators/mongoid/model/templates/model.rb +15 -0
- data/lib/rails/generators/mongoid_generator.rb +61 -0
- data/spec/integration/mongoid/association_attributes_spec.rb +71 -0
- data/spec/integration/mongoid/associations_spec.rb +768 -0
- data/spec/integration/mongoid/attributes_spec.rb +59 -0
- data/spec/integration/mongoid/callback_spec.rb +33 -0
- data/spec/integration/mongoid/contexts/enumerable_spec.rb +33 -0
- data/spec/integration/mongoid/criteria_spec.rb +281 -0
- data/spec/integration/mongoid/dirty_spec.rb +85 -0
- data/spec/integration/mongoid/document_spec.rb +741 -0
- data/spec/integration/mongoid/extensions_spec.rb +22 -0
- data/spec/integration/mongoid/finders_spec.rb +119 -0
- data/spec/integration/mongoid/inheritance_spec.rb +171 -0
- data/spec/integration/mongoid/named_scope_spec.rb +58 -0
- data/spec/integration/mongoid/paranoia_spec.rb +44 -0
- data/spec/integration/mongoid/persistence/update_spec.rb +46 -0
- data/spec/integration/mongoid/persistence_spec.rb +311 -0
- data/spec/integration/mongoid/validations/uniqueness_spec.rb +206 -0
- data/spec/models/account.rb +5 -0
- data/spec/models/address.rb +40 -0
- data/spec/models/agent.rb +7 -0
- data/spec/models/animal.rb +15 -0
- data/spec/models/answer.rb +4 -0
- data/spec/models/callbacks.rb +47 -0
- data/spec/models/category.rb +13 -0
- data/spec/models/comment.rb +10 -0
- data/spec/models/country_code.rb +6 -0
- data/spec/models/employer.rb +5 -0
- data/spec/models/favorite.rb +8 -0
- data/spec/models/game.rb +9 -0
- data/spec/models/inheritance.rb +72 -0
- data/spec/models/location.rb +5 -0
- data/spec/models/login.rb +6 -0
- data/spec/models/mixed_drink.rb +4 -0
- data/spec/models/name.rb +13 -0
- data/spec/models/namespacing.rb +11 -0
- data/spec/models/paranoid_post.rb +18 -0
- data/spec/models/parents.rb +32 -0
- data/spec/models/patient.rb +15 -0
- data/spec/models/person.rb +106 -0
- data/spec/models/pet.rb +7 -0
- data/spec/models/pet_owner.rb +6 -0
- data/spec/models/phone.rb +7 -0
- data/spec/models/post.rb +25 -0
- data/spec/models/preference.rb +7 -0
- data/spec/models/question.rb +8 -0
- data/spec/models/survey.rb +6 -0
- data/spec/models/translation.rb +5 -0
- data/spec/models/user.rb +6 -0
- data/spec/models/user_accout.rb +5 -0
- data/spec/models/vet_visit.rb +5 -0
- data/spec/models/video.rb +5 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/unit/mongoid/associations/embedded_in_spec.rb +193 -0
- data/spec/unit/mongoid/associations/embeds_many_spec.rb +626 -0
- data/spec/unit/mongoid/associations/embeds_one_spec.rb +287 -0
- data/spec/unit/mongoid/associations/foreign_key_spec.rb +90 -0
- data/spec/unit/mongoid/associations/meta_data_spec.rb +110 -0
- data/spec/unit/mongoid/associations/options_spec.rb +215 -0
- data/spec/unit/mongoid/associations/referenced_in_spec.rb +145 -0
- data/spec/unit/mongoid/associations/references_many_as_array_spec.rb +424 -0
- data/spec/unit/mongoid/associations/references_many_spec.rb +502 -0
- data/spec/unit/mongoid/associations/references_one_spec.rb +204 -0
- data/spec/unit/mongoid/associations_spec.rb +688 -0
- data/spec/unit/mongoid/atomicity_spec.rb +164 -0
- data/spec/unit/mongoid/attributes_spec.rb +646 -0
- data/spec/unit/mongoid/callbacks_spec.rb +85 -0
- data/spec/unit/mongoid/collection_spec.rb +187 -0
- data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
- data/spec/unit/mongoid/collections/master_spec.rb +41 -0
- data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
- data/spec/unit/mongoid/collections_spec.rb +98 -0
- data/spec/unit/mongoid/config_spec.rb +298 -0
- data/spec/unit/mongoid/contexts/enumerable_spec.rb +447 -0
- data/spec/unit/mongoid/contexts/mongo_spec.rb +703 -0
- data/spec/unit/mongoid/contexts_spec.rb +25 -0
- data/spec/unit/mongoid/criteria_spec.rb +873 -0
- data/spec/unit/mongoid/criterion/complex_spec.rb +17 -0
- data/spec/unit/mongoid/criterion/exclusion_spec.rb +121 -0
- data/spec/unit/mongoid/criterion/inclusion_spec.rb +274 -0
- data/spec/unit/mongoid/criterion/optional_spec.rb +483 -0
- data/spec/unit/mongoid/cursor_spec.rb +80 -0
- data/spec/unit/mongoid/deprecation_spec.rb +24 -0
- data/spec/unit/mongoid/dirty_spec.rb +430 -0
- data/spec/unit/mongoid/document_spec.rb +623 -0
- data/spec/unit/mongoid/errors_spec.rb +154 -0
- data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
- data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
- data/spec/unit/mongoid/extensions/array/conversions_spec.rb +52 -0
- data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
- data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +36 -0
- data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
- data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
- data/spec/unit/mongoid/extensions/date/conversions_spec.rb +145 -0
- data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +14 -0
- data/spec/unit/mongoid/extensions/false_class/equality_spec.rb +35 -0
- data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
- data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
- data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +59 -0
- data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +35 -0
- data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
- data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
- data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
- data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +29 -0
- data/spec/unit/mongoid/extensions/object/conversions_spec.rb +44 -0
- data/spec/unit/mongoid/extensions/objectid/conversions_spec.rb +22 -0
- data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
- data/spec/unit/mongoid/extensions/set/conversions_spec.rb +21 -0
- data/spec/unit/mongoid/extensions/string/conversions_spec.rb +28 -0
- data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
- data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +107 -0
- data/spec/unit/mongoid/extensions/time_conversions_spec.rb +186 -0
- data/spec/unit/mongoid/extensions/true_class/equality_spec.rb +35 -0
- data/spec/unit/mongoid/extras_spec.rb +102 -0
- data/spec/unit/mongoid/factory_spec.rb +31 -0
- data/spec/unit/mongoid/field_spec.rb +169 -0
- data/spec/unit/mongoid/fields_spec.rb +181 -0
- data/spec/unit/mongoid/finders_spec.rb +439 -0
- data/spec/unit/mongoid/hierarchy_spec.rb +68 -0
- data/spec/unit/mongoid/identity_spec.rb +109 -0
- data/spec/unit/mongoid/indexes_spec.rb +99 -0
- data/spec/unit/mongoid/javascript_spec.rb +48 -0
- data/spec/unit/mongoid/logger_spec.rb +38 -0
- data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
- data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
- data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
- data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
- data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
- data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
- data/spec/unit/mongoid/matchers_spec.rb +329 -0
- data/spec/unit/mongoid/memoization_spec.rb +75 -0
- data/spec/unit/mongoid/named_scope_spec.rb +123 -0
- data/spec/unit/mongoid/paranoia_spec.rb +108 -0
- data/spec/unit/mongoid/paths_spec.rb +272 -0
- data/spec/unit/mongoid/persistence/insert_embedded_spec.rb +154 -0
- data/spec/unit/mongoid/persistence/insert_spec.rb +144 -0
- data/spec/unit/mongoid/persistence/remove_all_spec.rb +82 -0
- data/spec/unit/mongoid/persistence/remove_embedded_spec.rb +152 -0
- data/spec/unit/mongoid/persistence/remove_spec.rb +89 -0
- data/spec/unit/mongoid/persistence/update_spec.rb +177 -0
- data/spec/unit/mongoid/persistence_spec.rb +452 -0
- data/spec/unit/mongoid/scope_spec.rb +240 -0
- data/spec/unit/mongoid/serialization_spec.rb +43 -0
- data/spec/unit/mongoid/state_spec.rb +94 -0
- data/spec/unit/mongoid/timestamps_spec.rb +30 -0
- data/spec/unit/mongoid/validations/associated_spec.rb +103 -0
- data/spec/unit/mongoid/validations/uniqueness_spec.rb +201 -0
- data/spec/unit/mongoid/validations_spec.rb +43 -0
- data/spec/unit/mongoid/versioning_spec.rb +41 -0
- data/spec/unit/mongoid_spec.rb +46 -0
- metadata +433 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Associations #:nodoc:
|
|
4
|
+
# Represents an association that is embedded within another document in the
|
|
5
|
+
# database, either as one or many.
|
|
6
|
+
class EmbeddedIn < Proxy
|
|
7
|
+
|
|
8
|
+
# Creates the new association by setting the internal
|
|
9
|
+
# target as the passed in Document. This should be the
|
|
10
|
+
# parent.
|
|
11
|
+
#
|
|
12
|
+
# All method calls on this object will then be delegated
|
|
13
|
+
# to the internal document itself.
|
|
14
|
+
#
|
|
15
|
+
# Options:
|
|
16
|
+
#
|
|
17
|
+
# target: The parent +Document+
|
|
18
|
+
# options: The association options
|
|
19
|
+
def initialize(target, options)
|
|
20
|
+
@target, @options = target, options
|
|
21
|
+
extends(options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Returns the parent document. The id param is present for
|
|
25
|
+
# compatibility with rails, however this could be overwritten
|
|
26
|
+
# in the future.
|
|
27
|
+
def find(id)
|
|
28
|
+
@target
|
|
29
|
+
end
|
|
30
|
+
|
|
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
|
|
44
|
+
|
|
45
|
+
# Returns the macro used to create the association.
|
|
46
|
+
def macro
|
|
47
|
+
:embedded_in
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Perform an update of the relationship of the parent and child. This
|
|
51
|
+
# is initialized by setting a parent object as the association on the
|
|
52
|
+
# +Document+. Will properly set an embeds_one or an embeds_many.
|
|
53
|
+
#
|
|
54
|
+
# Returns:
|
|
55
|
+
#
|
|
56
|
+
# A new +EmbeddedIn+ association proxy.
|
|
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) }
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Associations #:nodoc:
|
|
4
|
+
# Represents embedding many documents within a parent document, which will
|
|
5
|
+
# be an array as the underlying storage mechanism.
|
|
6
|
+
class EmbedsMany < Proxy
|
|
7
|
+
|
|
8
|
+
attr_accessor :association_name, :klass
|
|
9
|
+
|
|
10
|
+
# Appends the object to the +Array+, setting its parent in
|
|
11
|
+
# the process.
|
|
12
|
+
def <<(*documents)
|
|
13
|
+
documents.flatten.each do |doc|
|
|
14
|
+
doc.parentize(@parent, @association_name)
|
|
15
|
+
@target << doc
|
|
16
|
+
doc._index = @target.size - 1
|
|
17
|
+
doc.notify
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
alias :concat :<<
|
|
22
|
+
alias :push :<<
|
|
23
|
+
|
|
24
|
+
# Builds a new Document and adds it to the association collection. The
|
|
25
|
+
# document created will be of the same class as the others in the
|
|
26
|
+
# association, and the attributes will be passed into the constructor.
|
|
27
|
+
#
|
|
28
|
+
# Returns:
|
|
29
|
+
#
|
|
30
|
+
# The newly created Document.
|
|
31
|
+
def build(attrs = {}, type = nil)
|
|
32
|
+
document = type ? type.instantiate : @klass.instantiate
|
|
33
|
+
document.parentize(@parent, @association_name)
|
|
34
|
+
document.write_attributes(attrs)
|
|
35
|
+
@target << document
|
|
36
|
+
document._index = @target.size - 1
|
|
37
|
+
document
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Clears the association, and notifies the parents of the removal.
|
|
41
|
+
def clear
|
|
42
|
+
unless @target.empty?
|
|
43
|
+
document = @target.first
|
|
44
|
+
document._parent.update_child(document, true) if (document._parent)
|
|
45
|
+
@target.clear
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Returns a count of the number of documents in the association that have
|
|
50
|
+
# actually been persisted to the database.
|
|
51
|
+
#
|
|
52
|
+
# Use #size if you want the total number of documents.
|
|
53
|
+
#
|
|
54
|
+
# Returns:
|
|
55
|
+
#
|
|
56
|
+
# The total number of persisted embedded docs, as flagged by the
|
|
57
|
+
# #persisted? method.
|
|
58
|
+
def count
|
|
59
|
+
@target.select(&:persisted?).size
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Creates a new Document and adds it to the association collection. The
|
|
63
|
+
# document created will be of the same class as the others in the
|
|
64
|
+
# association, and the attributes will be passed into the constructor and
|
|
65
|
+
# the new object will then be saved.
|
|
66
|
+
#
|
|
67
|
+
# Returns:
|
|
68
|
+
#
|
|
69
|
+
# The newly created Document.
|
|
70
|
+
def create(attrs = {}, type = nil)
|
|
71
|
+
build(attrs, type).tap(&:save)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Creates a new Document and adds it to the association collection. The
|
|
75
|
+
# document created will be of the same class as the others in the
|
|
76
|
+
# association, and the attributes will be passed into the constructor and
|
|
77
|
+
# the new object will then be saved. If validation fails an error will
|
|
78
|
+
# get raised.
|
|
79
|
+
#
|
|
80
|
+
# Returns:
|
|
81
|
+
#
|
|
82
|
+
# The newly created Document.
|
|
83
|
+
def create!(attrs = {}, type = nil)
|
|
84
|
+
document = create(attrs, type)
|
|
85
|
+
raise Errors::Validations.new(document) unless document.errors.empty?
|
|
86
|
+
document
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Delete all the documents in the association without running callbacks.
|
|
90
|
+
#
|
|
91
|
+
# Example:
|
|
92
|
+
#
|
|
93
|
+
# <tt>addresses.delete_all</tt>
|
|
94
|
+
#
|
|
95
|
+
# Returns:
|
|
96
|
+
#
|
|
97
|
+
# The number of documents deleted.
|
|
98
|
+
def delete_all(conditions = {})
|
|
99
|
+
remove(:delete, conditions)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Delete all the documents in the association and run destroy callbacks.
|
|
103
|
+
#
|
|
104
|
+
# Example:
|
|
105
|
+
#
|
|
106
|
+
# <tt>addresses.destroy_all</tt>
|
|
107
|
+
#
|
|
108
|
+
# Returns:
|
|
109
|
+
#
|
|
110
|
+
# The number of documents destroyed.
|
|
111
|
+
def destroy_all(conditions = {})
|
|
112
|
+
remove(:destroy, conditions)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Finds a document in this association.
|
|
116
|
+
#
|
|
117
|
+
# If :all is passed, returns all the documents
|
|
118
|
+
#
|
|
119
|
+
# If an id is passed, will return the document for that id.
|
|
120
|
+
#
|
|
121
|
+
# Returns:
|
|
122
|
+
#
|
|
123
|
+
# Array or single Document.
|
|
124
|
+
def find(param)
|
|
125
|
+
return @target if param == :all
|
|
126
|
+
return detect { |document| document.id == param }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Creates the new association by finding the attributes in
|
|
130
|
+
# the parent document with its name, and instantiating a
|
|
131
|
+
# new document for each one found. These will then be put in an
|
|
132
|
+
# internal array.
|
|
133
|
+
#
|
|
134
|
+
# This then delegated all methods to the array class since this is
|
|
135
|
+
# essentially a proxy to an array itself.
|
|
136
|
+
#
|
|
137
|
+
# Options:
|
|
138
|
+
#
|
|
139
|
+
# parent: The parent document to the association.
|
|
140
|
+
# options: The association options.
|
|
141
|
+
def initialize(parent, options, target_array = nil)
|
|
142
|
+
@parent, @association_name = parent, options.name
|
|
143
|
+
@klass, @options = options.klass, options
|
|
144
|
+
if target_array
|
|
145
|
+
build_children_from_target_array(target_array)
|
|
146
|
+
else
|
|
147
|
+
build_children_from_attributes(parent.raw_attributes[@association_name])
|
|
148
|
+
end
|
|
149
|
+
extends(options)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# If the target array does not respond to the supplied method then try to
|
|
155
|
+
# find a named scope or criteria on the class and send the call there.
|
|
156
|
+
#
|
|
157
|
+
# If the method exists on the array, use the default proxy behavior.
|
|
158
|
+
def method_missing(name, *args, &block)
|
|
159
|
+
unless @target.respond_to?(name)
|
|
160
|
+
object = @klass.send(name, *args)
|
|
161
|
+
object.documents = @target
|
|
162
|
+
return object
|
|
163
|
+
end
|
|
164
|
+
super
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Used for setting associations via a nested attributes setter from the
|
|
168
|
+
# parent +Document+.
|
|
169
|
+
#
|
|
170
|
+
# Options:
|
|
171
|
+
#
|
|
172
|
+
# attributes: A +Hash+ of integer keys and +Hash+ values.
|
|
173
|
+
#
|
|
174
|
+
# Returns:
|
|
175
|
+
#
|
|
176
|
+
# The newly build target Document.
|
|
177
|
+
def nested_build(attributes, options = {})
|
|
178
|
+
@parent.instance_variable_set(:@building_nested, true)
|
|
179
|
+
deleted_indexes = []
|
|
180
|
+
attributes.each do |index, attrs|
|
|
181
|
+
if document = detect { |document| document._index == index.to_i }
|
|
182
|
+
if options && options[:allow_destroy] && attrs['_destroy']
|
|
183
|
+
deleted_indexes << document._index
|
|
184
|
+
@target.delete(document)
|
|
185
|
+
document.destroy
|
|
186
|
+
else
|
|
187
|
+
document.write_attributes(attrs)
|
|
188
|
+
document._index = index.to_i - deleted_indexes.collect { |i| i < index.to_i }.size
|
|
189
|
+
end
|
|
190
|
+
else
|
|
191
|
+
build(attrs)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
@parent.instance_variable_set(:@building_nested, false)
|
|
195
|
+
self
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Paginate the association. Will create a new criteria, set the documents
|
|
199
|
+
# on it and execute in an enumerable context.
|
|
200
|
+
#
|
|
201
|
+
# Options:
|
|
202
|
+
#
|
|
203
|
+
# options: A +Hash+ of pagination options.
|
|
204
|
+
#
|
|
205
|
+
# Returns:
|
|
206
|
+
#
|
|
207
|
+
# A +WillPaginate::Collection+.
|
|
208
|
+
def paginate(options)
|
|
209
|
+
criteria = Mongoid::Criteria.translate(@klass, options)
|
|
210
|
+
criteria.documents = @target
|
|
211
|
+
criteria.paginate(options)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
protected
|
|
215
|
+
# Initializes each of the attributes in the hash.
|
|
216
|
+
def build_children_from_attributes(attributes)
|
|
217
|
+
@target = []
|
|
218
|
+
if attributes
|
|
219
|
+
attributes.each_with_index do |attrs, index|
|
|
220
|
+
klass = attrs.klass
|
|
221
|
+
child = klass ? klass.instantiate(attrs) : @klass.instantiate(attrs)
|
|
222
|
+
child.parentize(@parent, @association_name)
|
|
223
|
+
child._index = index
|
|
224
|
+
@target << child
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Initializes the target array from an existing array of documents.
|
|
230
|
+
def build_children_from_target_array(target_array)
|
|
231
|
+
@target = target_array
|
|
232
|
+
@target.each_with_index do |child, index|
|
|
233
|
+
child._index = index
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Removes documents based on a method.
|
|
238
|
+
def remove(method, conditions)
|
|
239
|
+
criteria = @klass.find(conditions || {})
|
|
240
|
+
criteria.documents = @target
|
|
241
|
+
count = criteria.size
|
|
242
|
+
criteria.each do |doc|
|
|
243
|
+
@target.delete(doc); doc.send(method)
|
|
244
|
+
end; count
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
class << self
|
|
248
|
+
|
|
249
|
+
# Preferred method of creating a new +EmbedsMany+ association. It will
|
|
250
|
+
# delegate to new.
|
|
251
|
+
#
|
|
252
|
+
# Options:
|
|
253
|
+
#
|
|
254
|
+
# document: The parent +Document+
|
|
255
|
+
# options: The association options
|
|
256
|
+
def instantiate(document, options, target_array = nil)
|
|
257
|
+
new(document, options, target_array)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Returns the macro used to create the association.
|
|
261
|
+
def macro
|
|
262
|
+
:embeds_many
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Perform an update of the relationship of the parent and child. This
|
|
266
|
+
# is initialized by setting the has_many to the supplied +Enumerable+
|
|
267
|
+
# and setting up the parentization.
|
|
268
|
+
def update(children, parent, options)
|
|
269
|
+
parent.raw_attributes.delete(options.name)
|
|
270
|
+
children.assimilate(parent, options)
|
|
271
|
+
if children && children.first.is_a?(Mongoid::Document)
|
|
272
|
+
instantiate(parent, options, children)
|
|
273
|
+
else
|
|
274
|
+
instantiate(parent, options)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Associations #:nodoc:
|
|
4
|
+
# Represents an association that is embedded in a parent document as a
|
|
5
|
+
# one-to-one relationship.
|
|
6
|
+
class EmbedsOne < Proxy
|
|
7
|
+
|
|
8
|
+
# Build a new object for the association.
|
|
9
|
+
def build(attrs = {}, type = nil)
|
|
10
|
+
@target = attrs.assimilate(@parent, @options, type); self
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Creates the new association by finding the attributes in
|
|
14
|
+
# the parent document with its name, and instantiating a
|
|
15
|
+
# new document for it.
|
|
16
|
+
#
|
|
17
|
+
# All method calls on this object will then be delegated
|
|
18
|
+
# to the internal document itself.
|
|
19
|
+
#
|
|
20
|
+
# Options:
|
|
21
|
+
#
|
|
22
|
+
# document: The parent +Document+
|
|
23
|
+
# attributes: The attributes of the target object.
|
|
24
|
+
# options: The association options.
|
|
25
|
+
#
|
|
26
|
+
# Returns:
|
|
27
|
+
#
|
|
28
|
+
# A new +HashOne+ association proxy.
|
|
29
|
+
def initialize(document, attrs, options, target = nil)
|
|
30
|
+
@parent, @options = document, options
|
|
31
|
+
@target = target ? target : attrs.assimilate(@parent, @options, attrs.klass)
|
|
32
|
+
extends(options)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Used for setting the association via a nested attributes setter on the
|
|
36
|
+
# parent +Document+. Called when using accepts_nested_attributes_for.
|
|
37
|
+
#
|
|
38
|
+
# Options:
|
|
39
|
+
#
|
|
40
|
+
# attributes: The attributes for the new association
|
|
41
|
+
#
|
|
42
|
+
# Returns:
|
|
43
|
+
#
|
|
44
|
+
# A new target document.
|
|
45
|
+
def nested_build(attributes, options = nil)
|
|
46
|
+
unless @target.blank? && options[:update_only]
|
|
47
|
+
@target.write_attributes(attributes)
|
|
48
|
+
end; @target
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
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
|
+
# Returns the macro used to create the association.
|
|
70
|
+
def macro
|
|
71
|
+
:embeds_one
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Perform an update of the relationship of the parent and child. This
|
|
75
|
+
# will assimilate the child +Document+ into the parent's object graph.
|
|
76
|
+
#
|
|
77
|
+
# Options:
|
|
78
|
+
#
|
|
79
|
+
# child: The child +Document+ or +Hash+.
|
|
80
|
+
# parent: The parent +Document+ to update.
|
|
81
|
+
# options: The association +Options+
|
|
82
|
+
#
|
|
83
|
+
# Example:
|
|
84
|
+
#
|
|
85
|
+
# <tt>EmbedsOne.update({:first_name => "Hank"}, person, options)</tt>
|
|
86
|
+
#
|
|
87
|
+
# Returns:
|
|
88
|
+
#
|
|
89
|
+
# A new +EmbedsOne+ association proxy.
|
|
90
|
+
def update(child, parent, options)
|
|
91
|
+
child.assimilate(parent, options)
|
|
92
|
+
instantiate(parent, options, child.is_a?(Hash) ? nil : child)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|