mongoid 6.4.2 → 7.0.3
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/config/locales/en.yml +17 -0
- data/lib/mongoid/association/accessors.rb +339 -0
- data/lib/mongoid/{relations/binding.rb → association/bindable.rb} +32 -52
- data/lib/mongoid/association/builders.rb +92 -0
- data/lib/mongoid/{relations/constraint.rb → association/constrainable.rb} +11 -22
- data/lib/mongoid/association/depending.rb +137 -0
- data/lib/mongoid/{relations/eager.rb → association/eager_loadable.rb} +11 -11
- data/lib/mongoid/{relations → association}/embedded/batchable.rb +19 -19
- data/lib/mongoid/association/embedded/cyclic.rb +109 -0
- data/lib/mongoid/association/embedded/embedded_in/binding.rb +56 -0
- data/lib/mongoid/{relations/builders/embedded/in.rb → association/embedded/embedded_in/buildable.rb} +12 -6
- data/lib/mongoid/association/embedded/embedded_in/proxy.rb +121 -0
- data/lib/mongoid/association/embedded/embedded_in.rb +154 -0
- data/lib/mongoid/{relations/bindings/embedded/many.rb → association/embedded/embeds_many/binding.rb} +11 -9
- data/lib/mongoid/{relations/builders/embedded/many.rb → association/embedded/embeds_many/buildable.rb} +13 -7
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +552 -0
- data/lib/mongoid/association/embedded/embeds_many.rb +210 -0
- data/lib/mongoid/{relations/bindings/embedded/one.rb → association/embedded/embeds_one/binding.rb} +12 -10
- data/lib/mongoid/{relations/builders/embedded/one.rb → association/embedded/embeds_one/buildable.rb} +13 -7
- data/lib/mongoid/association/embedded/embeds_one/proxy.rb +130 -0
- data/lib/mongoid/association/embedded/embeds_one.rb +173 -0
- data/lib/mongoid/association/embedded.rb +4 -0
- data/lib/mongoid/association/macros.rb +204 -0
- data/lib/mongoid/{relations → association}/many.rb +19 -49
- data/lib/mongoid/{relations → association}/marshalable.rb +6 -4
- data/lib/mongoid/association/nested/many.rb +200 -0
- data/lib/mongoid/association/nested/nested_buildable.rb +72 -0
- data/lib/mongoid/association/nested/one.rb +127 -0
- data/lib/mongoid/association/nested.rb +15 -0
- data/lib/mongoid/{relations → association}/one.rb +6 -6
- data/lib/mongoid/association/options.rb +152 -0
- data/lib/mongoid/{relations → association}/proxy.rb +31 -58
- data/lib/mongoid/association/referenced/auto_save.rb +79 -0
- data/lib/mongoid/association/referenced/belongs_to/binding.rb +87 -0
- data/lib/mongoid/association/referenced/belongs_to/buildable.rb +46 -0
- data/lib/mongoid/association/referenced/belongs_to/eager.rb +36 -0
- data/lib/mongoid/association/referenced/belongs_to/proxy.rb +136 -0
- data/lib/mongoid/association/referenced/belongs_to.rb +248 -0
- data/lib/mongoid/association/referenced/counter_cache.rb +163 -0
- data/lib/mongoid/association/referenced/eager.rb +162 -0
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +71 -0
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +40 -0
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +52 -0
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +312 -0
- data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +290 -0
- data/lib/mongoid/{relations/bindings/referenced/many.rb → association/referenced/has_many/binding.rb} +6 -5
- data/lib/mongoid/association/referenced/has_many/buildable.rb +38 -0
- data/lib/mongoid/association/referenced/has_many/eager.rb +43 -0
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +510 -0
- data/lib/mongoid/association/referenced/has_many/proxy.rb +578 -0
- data/lib/mongoid/association/referenced/has_many.rb +275 -0
- data/lib/mongoid/{relations/bindings/referenced/one.rb → association/referenced/has_one/binding.rb} +11 -8
- data/lib/mongoid/association/referenced/has_one/buildable.rb +60 -0
- data/lib/mongoid/association/referenced/has_one/eager.rb +35 -0
- data/lib/mongoid/{relations/builders/nested_attributes/one.rb → association/referenced/has_one/nested_builder.rb} +9 -9
- data/lib/mongoid/association/referenced/has_one/proxy.rb +113 -0
- data/lib/mongoid/association/referenced/has_one.rb +204 -0
- data/lib/mongoid/association/referenced/syncable.rb +170 -0
- data/lib/mongoid/association/referenced.rb +7 -0
- data/lib/mongoid/{relations → association}/reflections.rb +21 -17
- data/lib/mongoid/association/relatable.rb +509 -0
- data/lib/mongoid/{relations.rb → association.rb} +57 -56
- data/lib/mongoid/atomic/paths/embedded/many.rb +1 -1
- data/lib/mongoid/atomic/paths/embedded/one.rb +1 -1
- data/lib/mongoid/atomic.rb +4 -4
- data/lib/mongoid/attributes/dynamic.rb +2 -2
- data/lib/mongoid/attributes/nested.rb +22 -11
- data/lib/mongoid/attributes/processing.rb +2 -2
- data/lib/mongoid/attributes/readonly.rb +2 -4
- data/lib/mongoid/attributes.rb +22 -13
- data/lib/mongoid/changeable.rb +1 -1
- data/lib/mongoid/clients/options.rb +7 -5
- data/lib/mongoid/composable.rb +4 -4
- data/lib/mongoid/config.rb +1 -0
- data/lib/mongoid/contextual/atomic.rb +1 -1
- data/lib/mongoid/contextual/geo_near.rb +1 -1
- data/lib/mongoid/contextual/memory.rb +21 -3
- data/lib/mongoid/contextual/mongo.rb +10 -8
- data/lib/mongoid/copyable.rb +7 -6
- data/lib/mongoid/criteria/includable.rb +14 -14
- data/lib/mongoid/criteria/modifiable.rb +8 -14
- data/lib/mongoid/criteria/options.rb +2 -2
- data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -1
- data/lib/mongoid/criteria/queryable/pipeline.rb +10 -5
- data/lib/mongoid/criteria/queryable/selectable.rb +37 -7
- data/lib/mongoid/criteria.rb +2 -2
- data/lib/mongoid/document.rb +15 -6
- data/lib/mongoid/errors/invalid_dependent_strategy.rb +32 -0
- data/lib/mongoid/errors/invalid_relation_option.rb +29 -0
- data/lib/mongoid/errors/unknown_model.rb +25 -0
- data/lib/mongoid/errors.rb +3 -0
- data/lib/mongoid/extensions/array.rb +5 -5
- data/lib/mongoid/extensions/big_decimal.rb +1 -1
- data/lib/mongoid/extensions/hash.rb +5 -2
- data/lib/mongoid/extensions/object.rb +4 -4
- data/lib/mongoid/extensions/range.rb +1 -0
- data/lib/mongoid/extensions/regexp.rb +1 -0
- data/lib/mongoid/extensions.rb +0 -4
- data/lib/mongoid/factory.rb +13 -3
- data/lib/mongoid/fields/foreign_key.rb +5 -5
- data/lib/mongoid/fields/standard.rb +2 -14
- data/lib/mongoid/fields/validators/macro.rb +1 -1
- data/lib/mongoid/fields.rb +3 -3
- data/lib/mongoid/indexable.rb +4 -1
- data/lib/mongoid/interceptable.rb +5 -5
- data/lib/mongoid/matchable/and.rb +1 -1
- data/lib/mongoid/matchable/elem_match.rb +9 -3
- data/lib/mongoid/matchable/eq.rb +22 -0
- data/lib/mongoid/matchable/ne.rb +1 -1
- data/lib/mongoid/matchable.rb +3 -1
- data/lib/mongoid/persistable/deletable.rb +7 -6
- data/lib/mongoid/persistable/incrementable.rb +1 -1
- data/lib/mongoid/persistable/logical.rb +1 -1
- data/lib/mongoid/persistable/settable.rb +57 -12
- data/lib/mongoid/persistable.rb +4 -5
- data/lib/mongoid/persistence_context.rb +20 -5
- data/lib/mongoid/query_cache.rb +8 -4
- data/lib/mongoid/railtie.rb +17 -0
- data/lib/mongoid/railties/controller_runtime.rb +86 -0
- data/lib/mongoid/scopable.rb +3 -3
- data/lib/mongoid/serializable.rb +4 -4
- data/lib/mongoid/shardable.rb +1 -1
- data/lib/mongoid/threaded.rb +36 -0
- data/lib/mongoid/touchable.rb +102 -0
- data/lib/mongoid/traversable.rb +3 -3
- data/lib/mongoid/validatable/presence.rb +2 -2
- data/lib/mongoid/validatable/uniqueness.rb +4 -4
- data/lib/mongoid/validatable.rb +8 -8
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +3 -0
- data/spec/app/models/animal.rb +2 -1
- data/spec/app/models/bomb.rb +1 -1
- data/spec/app/models/message.rb +1 -1
- data/spec/app/models/minim.rb +7 -0
- data/spec/app/models/person.rb +5 -2
- data/spec/app/models/shipment_address.rb +1 -0
- data/spec/app/models/store_as_dup_test3.rb +7 -0
- data/spec/app/models/store_as_dup_test4.rb +7 -0
- data/spec/app/models/updatable.rb +7 -0
- data/spec/app/models/vertex.rb +6 -0
- data/spec/app/models/wiki_page.rb +1 -1
- data/spec/config/mongoid.yml +13 -3
- data/spec/integration/associations/belongs_to_spec.rb +13 -0
- data/spec/lite_spec_helper.rb +56 -0
- data/spec/mongoid/{relations → association}/accessors_spec.rb +40 -1
- data/spec/mongoid/{relations → association}/auto_save_spec.rb +60 -12
- data/spec/mongoid/{relations → association}/builders_spec.rb +1 -1
- data/spec/mongoid/association/constrainable_spec.rb +115 -0
- data/spec/mongoid/{relations → association}/counter_cache_spec.rb +1 -1
- data/spec/mongoid/association/depending_spec.rb +866 -0
- data/spec/mongoid/{relations → association}/eager_spec.rb +12 -12
- data/spec/mongoid/{relations → association/embedded}/cyclic_spec.rb +1 -1
- data/spec/mongoid/{relations/bindings/embedded/in_spec.rb → association/embedded/embedded_in/binding_spec.rb} +13 -13
- data/spec/mongoid/{relations/builders/embedded/in_spec.rb → association/embedded/embedded_in/buildable_spec.rb} +9 -9
- data/spec/mongoid/{relations/embedded/in_spec.rb → association/embedded/embedded_in/proxy_spec.rb} +5 -77
- data/spec/mongoid/association/embedded/embedded_in_spec.rb +843 -0
- data/spec/mongoid/{relations/bindings/embedded/many_spec.rb → association/embedded/embeds_many/binding_spec.rb} +3 -3
- data/spec/mongoid/{relations/builders/embedded/many_spec.rb → association/embedded/embeds_many/buildable_spec.rb} +17 -45
- data/spec/mongoid/{relations/embedded/many_spec.rb → association/embedded/embeds_many/proxy_spec.rb} +124 -182
- data/spec/mongoid/association/embedded/embeds_many_spec.rb +852 -0
- data/spec/mongoid/{relations/bindings/embedded/one_spec.rb → association/embedded/embeds_one/binding_spec.rb} +4 -4
- data/spec/mongoid/{relations/builders/embedded/one_spec.rb → association/embedded/embeds_one/buildable_spec.rb} +14 -34
- data/spec/mongoid/{relations/embedded/one_spec.rb → association/embedded/embeds_one/proxy_spec.rb} +39 -84
- data/spec/mongoid/association/embedded/embeds_one_spec.rb +908 -0
- data/spec/mongoid/{relations → association}/macros_spec.rb +148 -73
- data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/many_spec.rb +16 -19
- data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/one_spec.rb +17 -20
- data/spec/mongoid/association/options_spec.rb +1321 -0
- data/spec/mongoid/{relations → association}/polymorphic_spec.rb +66 -34
- data/spec/mongoid/{relations/bindings/referenced/in_spec.rb → association/referenced/belongs_to/binding_spec.rb} +7 -7
- data/spec/mongoid/{relations/builders/referenced/in_spec.rb → association/referenced/belongs_to/buildable_spec.rb} +46 -79
- data/spec/mongoid/{relations/eager/belongs_to_spec.rb → association/referenced/belongs_to/eager_spec.rb} +33 -14
- data/spec/mongoid/{relations/referenced/in_spec.rb → association/referenced/belongs_to/proxy_spec.rb} +57 -91
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +2006 -0
- data/spec/mongoid/{relations/bindings/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/binding_spec.rb} +5 -5
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +121 -0
- data/spec/mongoid/{relations/eager/has_and_belongs_to_many_spec.rb → association/referenced/has_and_belongs_to_many/eager_spec.rb} +26 -7
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +56 -0
- data/spec/mongoid/{relations/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/proxy_spec.rb} +107 -98
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +26 -0
- data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +1027 -0
- data/spec/mongoid/{relations/bindings/referenced/many_spec.rb → association/referenced/has_many/binding_spec.rb} +5 -5
- data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +119 -0
- data/spec/mongoid/{relations/eager/has_many_spec.rb → association/referenced/has_many/eager_spec.rb} +26 -11
- data/spec/mongoid/{relations/targets → association/referenced/has_many}/enumerable_spec.rb +122 -1
- data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +23 -0
- data/spec/mongoid/{relations/referenced/many_spec.rb → association/referenced/has_many/proxy_spec.rb} +28 -93
- data/spec/mongoid/association/referenced/has_many_models.rb +37 -0
- data/spec/mongoid/association/referenced/has_many_spec.rb +1225 -0
- data/spec/mongoid/{relations/bindings/referenced/one_spec.rb → association/referenced/has_one/binding_spec.rb} +4 -4
- data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +113 -0
- data/spec/mongoid/{relations/eager/has_one_spec.rb → association/referenced/has_one/eager_spec.rb} +10 -10
- data/spec/mongoid/{relations/referenced/one_spec.rb → association/referenced/has_one/proxy_spec.rb} +9 -109
- data/spec/mongoid/association/referenced/has_one_models.rb +48 -0
- data/spec/mongoid/association/referenced/has_one_spec.rb +1350 -0
- data/spec/mongoid/{relations → association}/reflections_spec.rb +1 -12
- data/spec/mongoid/{relations/synchronization_spec.rb → association/syncable_spec.rb} +4 -2
- data/spec/mongoid/{relations_spec.rb → association_spec.rb} +1 -1
- data/spec/mongoid/atomic/modifiers_spec.rb +2 -2
- data/spec/mongoid/atomic_spec.rb +4 -4
- data/spec/mongoid/attributes/nested_spec.rb +29 -11
- data/spec/mongoid/attributes/readonly_spec.rb +80 -125
- data/spec/mongoid/attributes_spec.rb +38 -2
- data/spec/mongoid/clients/factory_spec.rb +24 -18
- data/spec/mongoid/clients/options_spec.rb +58 -44
- data/spec/mongoid/clients/sessions_spec.rb +1 -1
- data/spec/mongoid/clients/transactions_spec.rb +369 -0
- data/spec/mongoid/clients_spec.rb +68 -8
- data/spec/mongoid/config_spec.rb +27 -1
- data/spec/mongoid/contextual/memory_spec.rb +19 -0
- data/spec/mongoid/contextual/mongo_spec.rb +33 -5
- data/spec/mongoid/copyable_spec.rb +90 -6
- data/spec/mongoid/copyable_spec_models.rb +17 -0
- data/spec/mongoid/criteria/modifiable_spec.rb +183 -60
- data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +3 -3
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +43 -0
- data/spec/mongoid/criteria/queryable/pipeline_spec.rb +12 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +42 -3
- data/spec/mongoid/criteria/queryable/selector_spec.rb +2 -2
- data/spec/mongoid/criteria/scopable_spec.rb +81 -0
- data/spec/mongoid/criteria_spec.rb +33 -18
- data/spec/mongoid/document_spec.rb +83 -4
- data/spec/mongoid/extensions/array_spec.rb +11 -15
- data/spec/mongoid/extensions/big_decimal_spec.rb +9 -9
- data/spec/mongoid/extensions/hash_spec.rb +18 -1
- data/spec/mongoid/extensions/object_spec.rb +7 -11
- data/spec/mongoid/extensions/range_spec.rb +7 -0
- data/spec/mongoid/extensions/regexp_spec.rb +23 -0
- data/spec/mongoid/factory_spec.rb +19 -1
- data/spec/mongoid/fields/foreign_key_spec.rb +24 -32
- data/spec/mongoid/fields_spec.rb +2 -2
- data/spec/mongoid/findable_spec.rb +1 -1
- data/spec/mongoid/indexable_spec.rb +18 -8
- data/spec/mongoid/interceptable_spec.rb +22 -1
- data/spec/mongoid/matchable/elem_match_spec.rb +20 -0
- data/spec/mongoid/matchable/eq_spec.rb +48 -0
- data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
- data/spec/mongoid/persistable/savable_spec.rb +2 -2
- data/spec/mongoid/persistable/settable_spec.rb +95 -10
- data/spec/mongoid/persistable_spec.rb +21 -6
- data/spec/mongoid/persistence_context_spec.rb +1 -1
- data/spec/mongoid/query_cache_spec.rb +61 -22
- data/spec/mongoid/relations/proxy_spec.rb +124 -124
- data/spec/mongoid/scopable_spec.rb +13 -0
- data/spec/mongoid/shardable_spec.rb +32 -12
- data/spec/mongoid/threaded_spec.rb +68 -0
- data/spec/mongoid/{relations/touchable_spec.rb → touchable_spec.rb} +40 -1
- data/spec/mongoid/validatable/associated_spec.rb +1 -1
- data/spec/mongoid/validatable/presence_spec.rb +7 -6
- data/spec/mongoid/validatable_spec.rb +1 -1
- data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
- data/spec/spec_helper.rb +51 -25
- data/spec/support/constraints.rb +101 -0
- data/spec/support/macros.rb +20 -0
- data/spec/support/spec_config.rb +39 -0
- metadata +602 -582
- checksums.yaml.gz.sig +0 -2
- data/lib/mongoid/relations/accessors.rb +0 -267
- data/lib/mongoid/relations/auto_save.rb +0 -94
- data/lib/mongoid/relations/bindings/embedded/in.rb +0 -59
- data/lib/mongoid/relations/bindings/referenced/in.rb +0 -65
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +0 -70
- data/lib/mongoid/relations/bindings.rb +0 -9
- data/lib/mongoid/relations/builder.rb +0 -57
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +0 -199
- data/lib/mongoid/relations/builders/referenced/in.rb +0 -26
- data/lib/mongoid/relations/builders/referenced/many.rb +0 -26
- data/lib/mongoid/relations/builders/referenced/many_to_many.rb +0 -39
- data/lib/mongoid/relations/builders/referenced/one.rb +0 -26
- data/lib/mongoid/relations/builders.rb +0 -106
- data/lib/mongoid/relations/cascading/delete.rb +0 -44
- data/lib/mongoid/relations/cascading/destroy.rb +0 -43
- data/lib/mongoid/relations/cascading/nullify.rb +0 -35
- data/lib/mongoid/relations/cascading/restrict.rb +0 -39
- data/lib/mongoid/relations/cascading.rb +0 -56
- data/lib/mongoid/relations/conversions.rb +0 -34
- data/lib/mongoid/relations/counter_cache.rb +0 -160
- data/lib/mongoid/relations/cyclic.rb +0 -107
- data/lib/mongoid/relations/eager/base.rb +0 -153
- data/lib/mongoid/relations/eager/belongs_to.rb +0 -31
- data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +0 -47
- data/lib/mongoid/relations/eager/has_many.rb +0 -38
- data/lib/mongoid/relations/eager/has_one.rb +0 -30
- data/lib/mongoid/relations/embedded/in.rb +0 -241
- data/lib/mongoid/relations/embedded/many.rb +0 -683
- data/lib/mongoid/relations/embedded/one.rb +0 -235
- data/lib/mongoid/relations/macros.rb +0 -367
- data/lib/mongoid/relations/metadata.rb +0 -1179
- data/lib/mongoid/relations/nested_builder.rb +0 -74
- data/lib/mongoid/relations/options.rb +0 -49
- data/lib/mongoid/relations/polymorphic.rb +0 -39
- data/lib/mongoid/relations/referenced/in.rb +0 -304
- data/lib/mongoid/relations/referenced/many.rb +0 -812
- data/lib/mongoid/relations/referenced/many_to_many.rb +0 -479
- data/lib/mongoid/relations/referenced/one.rb +0 -290
- data/lib/mongoid/relations/synchronization.rb +0 -169
- data/lib/mongoid/relations/targets/enumerable.rb +0 -493
- data/lib/mongoid/relations/targets.rb +0 -2
- data/lib/mongoid/relations/touchable.rb +0 -97
- data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +0 -184
- data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +0 -201
- data/spec/mongoid/relations/builders/referenced/many_spec.rb +0 -137
- data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +0 -178
- data/spec/mongoid/relations/builders/referenced/one_spec.rb +0 -111
- data/spec/mongoid/relations/cascading/delete_spec.rb +0 -101
- data/spec/mongoid/relations/cascading/destroy_spec.rb +0 -47
- data/spec/mongoid/relations/cascading/nullify_spec.rb +0 -32
- data/spec/mongoid/relations/cascading/restrict_spec.rb +0 -68
- data/spec/mongoid/relations/cascading_spec.rb +0 -355
- data/spec/mongoid/relations/constraint_spec.rb +0 -75
- data/spec/mongoid/relations/conversions_spec.rb +0 -128
- data/spec/mongoid/relations/metadata_spec.rb +0 -1985
- data/spec/mongoid/relations/options_spec.rb +0 -35
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
- /data/spec/mongoid/{relations → association}/embedded/dirty_spec.rb +0 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid
|
|
3
|
+
module Association
|
|
4
|
+
module Referenced
|
|
5
|
+
class HasAndBelongsToMany
|
|
6
|
+
|
|
7
|
+
# This class defines the behaviour for all relations that are a
|
|
8
|
+
# many-to-many between documents in different collections.
|
|
9
|
+
class Proxy < Referenced::HasMany::Proxy
|
|
10
|
+
|
|
11
|
+
# Appends a document or array of documents to the relation. Will set
|
|
12
|
+
# the parent and update the index in the process.
|
|
13
|
+
#
|
|
14
|
+
# @example Append a document.
|
|
15
|
+
# person.posts << post
|
|
16
|
+
#
|
|
17
|
+
# @example Push a document.
|
|
18
|
+
# person.posts.push(post)
|
|
19
|
+
#
|
|
20
|
+
# @example Concat with other documents.
|
|
21
|
+
# person.posts.concat([ post_one, post_two ])
|
|
22
|
+
#
|
|
23
|
+
# @param [ Document, Array<Document> ] args Any number of documents.
|
|
24
|
+
#
|
|
25
|
+
# @return [ Array<Document> ] The loaded docs.
|
|
26
|
+
#
|
|
27
|
+
# @since 2.0.0.beta.1
|
|
28
|
+
def <<(*args)
|
|
29
|
+
docs = args.flatten
|
|
30
|
+
return concat(docs) if docs.size > 1
|
|
31
|
+
if doc = docs.first
|
|
32
|
+
append(doc)
|
|
33
|
+
_base.add_to_set(foreign_key => doc.send(_association.primary_key))
|
|
34
|
+
if child_persistable?(doc)
|
|
35
|
+
doc.save
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
unsynced(_base, foreign_key) and self
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
alias :push :<<
|
|
42
|
+
|
|
43
|
+
# Appends an array of documents to the relation. Performs a batch
|
|
44
|
+
# insert of the documents instead of persisting one at a time.
|
|
45
|
+
#
|
|
46
|
+
# @example Concat with other documents.
|
|
47
|
+
# person.posts.concat([ post_one, post_two ])
|
|
48
|
+
#
|
|
49
|
+
# @param [ Array<Document> ] documents The docs to add.
|
|
50
|
+
#
|
|
51
|
+
# @return [ Array<Document> ] The documents.
|
|
52
|
+
#
|
|
53
|
+
# @since 2.4.0
|
|
54
|
+
def concat(documents)
|
|
55
|
+
ids, docs, inserts = {}, [], []
|
|
56
|
+
documents.each do |doc|
|
|
57
|
+
next unless doc
|
|
58
|
+
append(doc)
|
|
59
|
+
if persistable? || _creating?
|
|
60
|
+
ids[doc._id] = true
|
|
61
|
+
save_or_delay(doc, docs, inserts)
|
|
62
|
+
else
|
|
63
|
+
existing = _base.send(foreign_key)
|
|
64
|
+
unless existing.include?(doc._id)
|
|
65
|
+
existing.push(doc._id) and unsynced(_base, foreign_key)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
if persistable? || _creating?
|
|
70
|
+
_base.push(foreign_key => ids.keys)
|
|
71
|
+
end
|
|
72
|
+
persist_delayed(docs, inserts)
|
|
73
|
+
self
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Build a new document from the attributes and append it to this
|
|
77
|
+
# relation without saving.
|
|
78
|
+
#
|
|
79
|
+
# @example Build a new document on the relation.
|
|
80
|
+
# person.posts.build(:title => "A new post")
|
|
81
|
+
#
|
|
82
|
+
# @param [ Hash ] attributes The attributes of the new document.
|
|
83
|
+
# @param [ Class ] type The optional subclass to build.
|
|
84
|
+
#
|
|
85
|
+
# @return [ Document ] The new document.
|
|
86
|
+
#
|
|
87
|
+
# @since 2.0.0.beta.1
|
|
88
|
+
def build(attributes = {}, type = nil)
|
|
89
|
+
doc = Factory.build(type || klass, attributes)
|
|
90
|
+
_base.send(foreign_key).push(doc._id)
|
|
91
|
+
append(doc)
|
|
92
|
+
doc.apply_post_processed_defaults
|
|
93
|
+
unsynced(doc, inverse_foreign_key)
|
|
94
|
+
yield(doc) if block_given?
|
|
95
|
+
doc
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
alias :new :build
|
|
99
|
+
|
|
100
|
+
# Delete the document from the relation. This will set the foreign key
|
|
101
|
+
# on the document to nil. If the dependent options on the relation are
|
|
102
|
+
# :delete or :destroy the appropriate removal will occur.
|
|
103
|
+
#
|
|
104
|
+
# @example Delete the document.
|
|
105
|
+
# person.posts.delete(post)
|
|
106
|
+
#
|
|
107
|
+
# @param [ Document ] document The document to remove.
|
|
108
|
+
#
|
|
109
|
+
# @return [ Document ] The matching document.
|
|
110
|
+
#
|
|
111
|
+
# @since 2.1.0
|
|
112
|
+
def delete(document)
|
|
113
|
+
doc = super
|
|
114
|
+
if doc && persistable?
|
|
115
|
+
_base.pull(foreign_key => doc.send(_association.primary_key))
|
|
116
|
+
_target._unloaded = criteria
|
|
117
|
+
unsynced(_base, foreign_key)
|
|
118
|
+
end
|
|
119
|
+
doc
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Removes all associations between the base document and the target
|
|
123
|
+
# documents by deleting the foreign keys and the references, orphaning
|
|
124
|
+
# the target documents in the process.
|
|
125
|
+
#
|
|
126
|
+
# @example Nullify the relation.
|
|
127
|
+
# person.preferences.nullify
|
|
128
|
+
#
|
|
129
|
+
# @param [ Array<Document> ] replacement The replacement documents.
|
|
130
|
+
#
|
|
131
|
+
# @since 2.0.0.rc.1
|
|
132
|
+
def nullify(replacement = [])
|
|
133
|
+
_target.each do |doc|
|
|
134
|
+
execute_callback :before_remove, doc
|
|
135
|
+
end
|
|
136
|
+
unless _association.forced_nil_inverse?
|
|
137
|
+
if replacement
|
|
138
|
+
objects_to_clear = _base.send(foreign_key) - replacement.collect do |object|
|
|
139
|
+
object.send(_association.primary_key)
|
|
140
|
+
end
|
|
141
|
+
criteria(objects_to_clear).pull(inverse_foreign_key => _base._id)
|
|
142
|
+
else
|
|
143
|
+
criteria.pull(inverse_foreign_key => _base._id)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
if persistable?
|
|
147
|
+
_base.set(foreign_key => _base.send(foreign_key).clear)
|
|
148
|
+
end
|
|
149
|
+
after_remove_error = nil
|
|
150
|
+
many_to_many = _target.clear do |doc|
|
|
151
|
+
unbind_one(doc)
|
|
152
|
+
unless _association.forced_nil_inverse?
|
|
153
|
+
doc.changed_attributes.delete(inverse_foreign_key)
|
|
154
|
+
end
|
|
155
|
+
begin
|
|
156
|
+
execute_callback :after_remove, doc
|
|
157
|
+
rescue => e
|
|
158
|
+
after_remove_error = e
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
raise after_remove_error if after_remove_error
|
|
162
|
+
many_to_many
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
alias :nullify_all :nullify
|
|
166
|
+
alias :clear :nullify
|
|
167
|
+
alias :purge :nullify
|
|
168
|
+
|
|
169
|
+
# Substitutes the supplied target documents for the existing documents
|
|
170
|
+
# in the relation. If the new target is nil, perform the necessary
|
|
171
|
+
# deletion.
|
|
172
|
+
#
|
|
173
|
+
# @example Replace the relation.
|
|
174
|
+
# person.preferences.substitute([ new_post ])
|
|
175
|
+
#
|
|
176
|
+
# @param [ Array<Document> ] replacement The replacement target.
|
|
177
|
+
#
|
|
178
|
+
# @return [ Many ] The relation.
|
|
179
|
+
#
|
|
180
|
+
# @since 2.0.0.rc.1
|
|
181
|
+
def substitute(replacement)
|
|
182
|
+
purge(replacement)
|
|
183
|
+
unless replacement.blank?
|
|
184
|
+
push(replacement.compact.uniq)
|
|
185
|
+
else
|
|
186
|
+
reset_unloaded
|
|
187
|
+
end
|
|
188
|
+
self
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Get a criteria for the documents without the default scoping
|
|
192
|
+
# applied.
|
|
193
|
+
#
|
|
194
|
+
# @example Get the unscoped criteria.
|
|
195
|
+
# person.preferences.unscoped
|
|
196
|
+
#
|
|
197
|
+
# @return [ Criteria ] The unscoped criteria.
|
|
198
|
+
#
|
|
199
|
+
# @since 2.4.0
|
|
200
|
+
def unscoped
|
|
201
|
+
klass.unscoped.any_in(_id: _base.send(foreign_key))
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
private
|
|
205
|
+
|
|
206
|
+
# Appends the document to the target array, updating the index on the
|
|
207
|
+
# document at the same time.
|
|
208
|
+
#
|
|
209
|
+
# @example Append the document to the relation.
|
|
210
|
+
# relation.append(document)
|
|
211
|
+
#
|
|
212
|
+
# @param [ Document ] document The document to append to the target.
|
|
213
|
+
#
|
|
214
|
+
# @since 2.0.0.rc.1
|
|
215
|
+
def append(document)
|
|
216
|
+
execute_callback :before_add, document
|
|
217
|
+
_target.push(document)
|
|
218
|
+
characterize_one(document)
|
|
219
|
+
bind_one(document)
|
|
220
|
+
execute_callback :after_add, document
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Instantiate the binding associated with this relation.
|
|
224
|
+
#
|
|
225
|
+
# @example Get the binding.
|
|
226
|
+
# relation.binding([ address ])
|
|
227
|
+
#
|
|
228
|
+
# @return [ Binding ] The binding.
|
|
229
|
+
#
|
|
230
|
+
# @since 2.0.0.rc.1
|
|
231
|
+
def binding
|
|
232
|
+
HasAndBelongsToMany::Binding.new(_base, _target, _association)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Determine if the child document should be persisted.
|
|
236
|
+
#
|
|
237
|
+
# @api private
|
|
238
|
+
#
|
|
239
|
+
# @example Is the child persistable?
|
|
240
|
+
# relation.child_persistable?(doc)
|
|
241
|
+
#
|
|
242
|
+
# @param [ Document ] doc The document.
|
|
243
|
+
#
|
|
244
|
+
# @return [ true, false ] If the document can be persisted.
|
|
245
|
+
#
|
|
246
|
+
# @since 3.0.20
|
|
247
|
+
def child_persistable?(doc)
|
|
248
|
+
(persistable? || _creating?) &&
|
|
249
|
+
!(doc.persisted? && _association.forced_nil_inverse?)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Returns the criteria object for the target class with its documents set
|
|
253
|
+
# to target.
|
|
254
|
+
#
|
|
255
|
+
# @example Get a criteria for the relation.
|
|
256
|
+
# relation.criteria
|
|
257
|
+
#
|
|
258
|
+
# @return [ Criteria ] A new criteria.
|
|
259
|
+
def criteria(id_list = nil)
|
|
260
|
+
_association.criteria(_base, id_list)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# Flag the base as unsynced with respect to the foreign key.
|
|
264
|
+
#
|
|
265
|
+
# @api private
|
|
266
|
+
#
|
|
267
|
+
# @example Flag as unsynced.
|
|
268
|
+
# relation.unsynced(doc, :preference_ids)
|
|
269
|
+
#
|
|
270
|
+
# @param [ Document ] doc The document to flag.
|
|
271
|
+
# @param [ Symbol ] key The key to flag on the document.
|
|
272
|
+
#
|
|
273
|
+
# @return [ true ] true.
|
|
274
|
+
#
|
|
275
|
+
# @since 3.0.0
|
|
276
|
+
def unsynced(doc, key)
|
|
277
|
+
doc._synced[key] = false
|
|
278
|
+
true
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
class << self
|
|
282
|
+
|
|
283
|
+
# Get the Eager object for this type of association.
|
|
284
|
+
#
|
|
285
|
+
# @example Get the eager loader object
|
|
286
|
+
#
|
|
287
|
+
# @param [ Association ] association The association object.
|
|
288
|
+
# @param [ Array<Document> ] docs The array of documents.
|
|
289
|
+
#
|
|
290
|
+
# @since 7.0
|
|
291
|
+
def eager_loader(association, docs)
|
|
292
|
+
Eager.new(association, docs)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Returns true if the relation is an embedded one. In this case
|
|
296
|
+
# always false.
|
|
297
|
+
#
|
|
298
|
+
# @example Is this relation embedded?
|
|
299
|
+
# Referenced::ManyToMany.embedded?
|
|
300
|
+
#
|
|
301
|
+
# @return [ false ] Always false.
|
|
302
|
+
#
|
|
303
|
+
# @since 2.0.0.rc.1
|
|
304
|
+
def embedded?
|
|
305
|
+
false
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
require 'mongoid/association/referenced/has_and_belongs_to_many/binding'
|
|
2
|
+
require 'mongoid/association/referenced/has_and_belongs_to_many/buildable'
|
|
3
|
+
require 'mongoid/association/referenced/has_and_belongs_to_many/proxy'
|
|
4
|
+
require 'mongoid/association/referenced/has_and_belongs_to_many/eager'
|
|
5
|
+
|
|
6
|
+
module Mongoid
|
|
7
|
+
module Association
|
|
8
|
+
module Referenced
|
|
9
|
+
|
|
10
|
+
# The HasAndBelongsToMany type association.
|
|
11
|
+
#
|
|
12
|
+
# @since 7.0
|
|
13
|
+
class HasAndBelongsToMany
|
|
14
|
+
include Relatable
|
|
15
|
+
include Buildable
|
|
16
|
+
|
|
17
|
+
# The options available for this type of association, in addition to the
|
|
18
|
+
# common ones.
|
|
19
|
+
#
|
|
20
|
+
# @return [ Array<Symbol> ] The extra valid options.
|
|
21
|
+
#
|
|
22
|
+
# @since 7.0
|
|
23
|
+
ASSOCIATION_OPTIONS = [
|
|
24
|
+
:after_add,
|
|
25
|
+
:after_remove,
|
|
26
|
+
:autosave,
|
|
27
|
+
:before_add,
|
|
28
|
+
:before_remove,
|
|
29
|
+
:counter_cache,
|
|
30
|
+
:dependent,
|
|
31
|
+
:foreign_key,
|
|
32
|
+
:index,
|
|
33
|
+
:order,
|
|
34
|
+
:primary_key
|
|
35
|
+
].freeze
|
|
36
|
+
|
|
37
|
+
# The complete list of valid options for this association, including
|
|
38
|
+
# the shared ones.
|
|
39
|
+
#
|
|
40
|
+
# @return [ Array<Symbol> ] The valid options.
|
|
41
|
+
#
|
|
42
|
+
# @since 7.0
|
|
43
|
+
VALID_OPTIONS = (ASSOCIATION_OPTIONS + SHARED_OPTIONS).freeze
|
|
44
|
+
|
|
45
|
+
# The type of the field holding the foreign key.
|
|
46
|
+
#
|
|
47
|
+
# @return [ Array ]
|
|
48
|
+
#
|
|
49
|
+
# @since 7.0
|
|
50
|
+
FOREIGN_KEY_FIELD_TYPE = Array
|
|
51
|
+
|
|
52
|
+
# The default foreign key suffix.
|
|
53
|
+
#
|
|
54
|
+
# @return [ String ] '_ids'
|
|
55
|
+
#
|
|
56
|
+
# @since 7.0
|
|
57
|
+
FOREIGN_KEY_SUFFIX = '_ids'.freeze
|
|
58
|
+
|
|
59
|
+
# The list of association complements.
|
|
60
|
+
#
|
|
61
|
+
# @return [ Array<Association> ] The association complements.
|
|
62
|
+
#
|
|
63
|
+
# @since 7.0
|
|
64
|
+
def relation_complements
|
|
65
|
+
@relation_complements ||= [ self.class ].freeze
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Setup the instance methods, fields, etc. on the association owning class.
|
|
69
|
+
#
|
|
70
|
+
# @return [ self ]
|
|
71
|
+
#
|
|
72
|
+
# @since 7.0
|
|
73
|
+
def setup!
|
|
74
|
+
setup_instance_methods!
|
|
75
|
+
self
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Is this association type embedded?
|
|
79
|
+
#
|
|
80
|
+
# @return [ false ] Always false.
|
|
81
|
+
#
|
|
82
|
+
# @since 7.0
|
|
83
|
+
def embedded?; false; end
|
|
84
|
+
|
|
85
|
+
# The default for validation the association object.
|
|
86
|
+
#
|
|
87
|
+
# @return [ false ] Always false.
|
|
88
|
+
#
|
|
89
|
+
# @since 7.0
|
|
90
|
+
def validation_default; true; end
|
|
91
|
+
|
|
92
|
+
# Are ids only saved on this side of the relation?
|
|
93
|
+
#
|
|
94
|
+
# @return [ true, false ] Whether this association has a forced nil inverse.
|
|
95
|
+
#
|
|
96
|
+
# @since 7.0
|
|
97
|
+
def forced_nil_inverse?
|
|
98
|
+
@forced_nil_inverse ||= @options.key?(:inverse_of) && !@options[:inverse_of]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Does this association type store the foreign key?
|
|
102
|
+
#
|
|
103
|
+
# @return [ true ] Always true.
|
|
104
|
+
#
|
|
105
|
+
# @since 7.0
|
|
106
|
+
def stores_foreign_key?; true; end
|
|
107
|
+
|
|
108
|
+
# Get the relation proxy class for this association type.
|
|
109
|
+
#
|
|
110
|
+
# @return [ Association::HasAndBelongsToMany::Proxy ] The proxy class.
|
|
111
|
+
#
|
|
112
|
+
# @since 7.0
|
|
113
|
+
def relation
|
|
114
|
+
Proxy
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Get the foreign key field for saving the association reference.
|
|
118
|
+
#
|
|
119
|
+
# @return [ String ] The foreign key field for saving the association reference.
|
|
120
|
+
#
|
|
121
|
+
# @since 7.0
|
|
122
|
+
def foreign_key
|
|
123
|
+
@foreign_key ||= @options[:foreign_key] ? @options[:foreign_key].to_s :
|
|
124
|
+
default_foreign_key_field
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# The criteria used for querying this relation.
|
|
128
|
+
#
|
|
129
|
+
# @return [ Mongoid::Criteria ] The criteria used for querying this relation.
|
|
130
|
+
#
|
|
131
|
+
# @since 7.0
|
|
132
|
+
def criteria(base, id_list = nil)
|
|
133
|
+
query_criteria(id_list || base.send(foreign_key))
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Get the foreign key field on the inverse.
|
|
137
|
+
#
|
|
138
|
+
# @return [ String ] The foreign key field for saving the association reference
|
|
139
|
+
# on the inverse side.
|
|
140
|
+
#
|
|
141
|
+
# @since 7.0
|
|
142
|
+
def inverse_foreign_key
|
|
143
|
+
if @options.key?(:inverse_of)
|
|
144
|
+
inverse_of ? "#{inverse_of.to_s.singularize}#{FOREIGN_KEY_SUFFIX}" : nil
|
|
145
|
+
else
|
|
146
|
+
"#{inverse_class_name.demodulize.underscore}#{FOREIGN_KEY_SUFFIX}"
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Whether trying to bind an object using this association should raise
|
|
151
|
+
# an error.
|
|
152
|
+
#
|
|
153
|
+
# @param [ Document ] doc The document to be bound.
|
|
154
|
+
#
|
|
155
|
+
# @return [ true, false ] Whether the document can be bound.
|
|
156
|
+
def bindable?(doc)
|
|
157
|
+
forced_nil_inverse? || (!!inverse && doc.fields.keys.include?(foreign_key))
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Get the foreign key setter on the inverse.
|
|
161
|
+
#
|
|
162
|
+
# @return [ String ] The foreign key setter for saving the association reference
|
|
163
|
+
# on the inverse side.
|
|
164
|
+
#
|
|
165
|
+
# @since 7.0
|
|
166
|
+
def inverse_foreign_key_setter
|
|
167
|
+
@inverse_foreign_key_setter ||= "#{inverse_foreign_key}=" if inverse_foreign_key
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# The nested builder object.
|
|
171
|
+
#
|
|
172
|
+
# @param [ Hash ] attributes The attributes to use to build the association object.
|
|
173
|
+
# @param [ Hash ] options The options for the association.
|
|
174
|
+
#
|
|
175
|
+
# @return [ Association::Nested::One ] The Nested Builder object.
|
|
176
|
+
#
|
|
177
|
+
# @since 7.0
|
|
178
|
+
def nested_builder(attributes, options)
|
|
179
|
+
Nested::Many.new(self, attributes, options)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Get the path calculator for the supplied document.
|
|
183
|
+
#
|
|
184
|
+
# @example Get the path calculator.
|
|
185
|
+
# association.path(document)
|
|
186
|
+
#
|
|
187
|
+
# @param [ Document ] document The document to calculate on.
|
|
188
|
+
#
|
|
189
|
+
# @return [ Root ] The root atomic path calculator.
|
|
190
|
+
#
|
|
191
|
+
# @since 2.1.0
|
|
192
|
+
def path(document)
|
|
193
|
+
Mongoid::Atomic::Paths::Root.new(document)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
private
|
|
197
|
+
|
|
198
|
+
def setup_instance_methods!
|
|
199
|
+
define_getter!
|
|
200
|
+
define_setter!
|
|
201
|
+
define_dependency!
|
|
202
|
+
define_existence_check!
|
|
203
|
+
define_autosaver!
|
|
204
|
+
define_counter_cache_callbacks!
|
|
205
|
+
create_foreign_key_field!
|
|
206
|
+
setup_index!
|
|
207
|
+
setup_syncing!
|
|
208
|
+
@owner_class.validates_associated(name) if validate?
|
|
209
|
+
self
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def index_spec
|
|
213
|
+
{ key => 1 }
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def default_primary_key
|
|
217
|
+
PRIMARY_KEY_DEFAULT
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def default_foreign_key_field
|
|
221
|
+
@default_foreign_key_field ||= "#{name.to_s.singularize}#{FOREIGN_KEY_SUFFIX}"
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def setup_syncing!
|
|
225
|
+
unless forced_nil_inverse?
|
|
226
|
+
synced_save
|
|
227
|
+
synced_destroy
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def synced_destroy
|
|
232
|
+
assoc = self
|
|
233
|
+
inverse_class.set_callback(
|
|
234
|
+
:destroy,
|
|
235
|
+
:after
|
|
236
|
+
) do |doc|
|
|
237
|
+
doc.remove_inverse_keys(assoc)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def synced_save
|
|
242
|
+
assoc = self
|
|
243
|
+
inverse_class.set_callback(
|
|
244
|
+
:save,
|
|
245
|
+
:after,
|
|
246
|
+
if: ->(doc){ doc._syncable?(assoc) }
|
|
247
|
+
) do |doc|
|
|
248
|
+
doc.update_inverse_keys(assoc)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def create_foreign_key_field!
|
|
253
|
+
@owner_class.field(
|
|
254
|
+
foreign_key,
|
|
255
|
+
type: FOREIGN_KEY_FIELD_TYPE,
|
|
256
|
+
identity: true,
|
|
257
|
+
overwrite: true,
|
|
258
|
+
association: self,
|
|
259
|
+
default: nil
|
|
260
|
+
)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def determine_inverses(other)
|
|
264
|
+
matches = (other || relation_class).relations.values.select do |rel|
|
|
265
|
+
relation_complements.include?(rel.class) &&
|
|
266
|
+
rel.relation_class_name == inverse_class_name
|
|
267
|
+
|
|
268
|
+
end
|
|
269
|
+
if matches.size > 1
|
|
270
|
+
raise Errors::AmbiguousRelationship.new(relation_class, @owner_class, name, matches)
|
|
271
|
+
end
|
|
272
|
+
matches.collect { |m| m.name } unless matches.blank?
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def with_ordering(criteria)
|
|
276
|
+
if order
|
|
277
|
+
criteria.order_by(order)
|
|
278
|
+
else
|
|
279
|
+
criteria
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def query_criteria(id_list)
|
|
284
|
+
crit = relation_class.all_of(primary_key => {"$in" => id_list || []})
|
|
285
|
+
with_ordering(crit)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
module Mongoid
|
|
3
|
-
module
|
|
4
|
-
module
|
|
5
|
-
|
|
3
|
+
module Association
|
|
4
|
+
module Referenced
|
|
5
|
+
class HasMany
|
|
6
6
|
|
|
7
|
-
# Binding class for
|
|
8
|
-
class
|
|
7
|
+
# Binding class for has_many associations.
|
|
8
|
+
class Binding
|
|
9
|
+
include Bindable
|
|
9
10
|
|
|
10
11
|
# Binds a single document with the inverse relation. Used
|
|
11
12
|
# specifically when appending to the proxy.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid
|
|
3
|
+
module Association
|
|
4
|
+
module Referenced
|
|
5
|
+
class HasMany
|
|
6
|
+
|
|
7
|
+
# The Builder behavior for has_many associations.
|
|
8
|
+
#
|
|
9
|
+
# @since 7.0
|
|
10
|
+
module Buildable
|
|
11
|
+
|
|
12
|
+
# This method either takes an _id or an object and queries for the
|
|
13
|
+
# inverse side using the id or sets the object.
|
|
14
|
+
#
|
|
15
|
+
# @example Build the document.
|
|
16
|
+
# relation.build(meta, attrs)
|
|
17
|
+
#
|
|
18
|
+
# @param [ Object ] base The base object.
|
|
19
|
+
# @param [ Object ] object The object to use to build the relation.
|
|
20
|
+
# @param [ String ] type The type of document to query for.
|
|
21
|
+
#
|
|
22
|
+
# @return [ Document ] A single document.
|
|
23
|
+
def build(base, object, type = nil)
|
|
24
|
+
return (object || []) unless query?(object)
|
|
25
|
+
return [] if object.is_a?(Array)
|
|
26
|
+
query_criteria(object, base)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def query?(object)
|
|
32
|
+
object && Array(object).all? { |d| !d.is_a?(Mongoid::Document) }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid
|
|
3
|
+
module Association
|
|
4
|
+
module Referenced
|
|
5
|
+
class HasMany
|
|
6
|
+
|
|
7
|
+
# Eager class for has_many associations.
|
|
8
|
+
class Eager < Association::Referenced::Eager::Base
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def preload
|
|
13
|
+
@docs.each do |d|
|
|
14
|
+
set_relation(d, [])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
entries = Hash.new { |hash, key| hash[key] = [] }
|
|
18
|
+
each_loaded_document do |doc|
|
|
19
|
+
fk = doc.send(key)
|
|
20
|
+
entries[fk] << doc
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
entries.each do |id, docs|
|
|
24
|
+
set_on_parent(id, docs)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def set_relation(doc, element)
|
|
29
|
+
doc.__build__(@association.name, element, @association) unless doc.blank?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def group_by_key
|
|
33
|
+
@association.primary_key
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def key
|
|
37
|
+
@association.foreign_key
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|