mongoid-multi-db 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +615 -0
- data/LICENSE +20 -0
- data/README.md +62 -0
- data/Rakefile +49 -0
- data/lib/config/locales/bg.yml +54 -0
- data/lib/config/locales/de.yml +54 -0
- data/lib/config/locales/en-GB.yml +55 -0
- data/lib/config/locales/en.yml +55 -0
- data/lib/config/locales/es.yml +52 -0
- data/lib/config/locales/fr.yml +55 -0
- data/lib/config/locales/hi.yml +46 -0
- data/lib/config/locales/hu.yml +57 -0
- data/lib/config/locales/id.yml +55 -0
- data/lib/config/locales/it.yml +52 -0
- data/lib/config/locales/ja.yml +50 -0
- data/lib/config/locales/kr.yml +47 -0
- data/lib/config/locales/nl.yml +52 -0
- data/lib/config/locales/pl.yml +52 -0
- data/lib/config/locales/pt-BR.yml +53 -0
- data/lib/config/locales/pt.yml +53 -0
- data/lib/config/locales/ro.yml +59 -0
- data/lib/config/locales/ru.yml +54 -0
- data/lib/config/locales/sv.yml +53 -0
- data/lib/config/locales/vi.yml +55 -0
- data/lib/config/locales/zh-CN.yml +46 -0
- data/lib/mongoid.rb +148 -0
- data/lib/mongoid/atomic.rb +230 -0
- data/lib/mongoid/atomic/modifiers.rb +243 -0
- data/lib/mongoid/atomic/paths.rb +3 -0
- data/lib/mongoid/atomic/paths/embedded.rb +43 -0
- data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
- data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
- data/lib/mongoid/atomic/paths/root.rb +40 -0
- data/lib/mongoid/attributes.rb +234 -0
- data/lib/mongoid/attributes/processing.rb +146 -0
- data/lib/mongoid/callbacks.rb +135 -0
- data/lib/mongoid/collection.rb +153 -0
- data/lib/mongoid/collection_proxy.rb +59 -0
- data/lib/mongoid/collections.rb +120 -0
- data/lib/mongoid/collections/master.rb +45 -0
- data/lib/mongoid/collections/operations.rb +44 -0
- data/lib/mongoid/collections/retry.rb +46 -0
- data/lib/mongoid/components.rb +96 -0
- data/lib/mongoid/config.rb +347 -0
- data/lib/mongoid/config/database.rb +186 -0
- data/lib/mongoid/config/replset_database.rb +82 -0
- data/lib/mongoid/connection_proxy.rb +30 -0
- data/lib/mongoid/contexts.rb +25 -0
- data/lib/mongoid/contexts/enumerable.rb +288 -0
- data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
- data/lib/mongoid/contexts/mongo.rb +409 -0
- data/lib/mongoid/copyable.rb +48 -0
- data/lib/mongoid/criteria.rb +418 -0
- data/lib/mongoid/criterion/builder.rb +34 -0
- data/lib/mongoid/criterion/complex.rb +84 -0
- data/lib/mongoid/criterion/creational.rb +34 -0
- data/lib/mongoid/criterion/exclusion.rb +108 -0
- data/lib/mongoid/criterion/inclusion.rb +305 -0
- data/lib/mongoid/criterion/inspection.rb +22 -0
- data/lib/mongoid/criterion/optional.rb +232 -0
- data/lib/mongoid/criterion/selector.rb +153 -0
- data/lib/mongoid/cursor.rb +86 -0
- data/lib/mongoid/database_proxy.rb +97 -0
- data/lib/mongoid/default_scope.rb +36 -0
- data/lib/mongoid/dirty.rb +110 -0
- data/lib/mongoid/document.rb +280 -0
- data/lib/mongoid/errors.rb +17 -0
- data/lib/mongoid/errors/callback.rb +26 -0
- data/lib/mongoid/errors/document_not_found.rb +28 -0
- data/lib/mongoid/errors/eager_load.rb +25 -0
- data/lib/mongoid/errors/invalid_collection.rb +18 -0
- data/lib/mongoid/errors/invalid_database.rb +19 -0
- data/lib/mongoid/errors/invalid_field.rb +18 -0
- data/lib/mongoid/errors/invalid_find.rb +19 -0
- data/lib/mongoid/errors/invalid_options.rb +28 -0
- data/lib/mongoid/errors/invalid_time.rb +25 -0
- data/lib/mongoid/errors/invalid_type.rb +25 -0
- data/lib/mongoid/errors/mixed_relations.rb +37 -0
- data/lib/mongoid/errors/mongoid_error.rb +26 -0
- data/lib/mongoid/errors/too_many_nested_attribute_records.rb +20 -0
- data/lib/mongoid/errors/unsaved_document.rb +23 -0
- data/lib/mongoid/errors/unsupported_version.rb +20 -0
- data/lib/mongoid/errors/validations.rb +23 -0
- data/lib/mongoid/extensions.rb +82 -0
- data/lib/mongoid/extensions/array/deletion.rb +29 -0
- data/lib/mongoid/extensions/false_class/equality.rb +26 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +45 -0
- data/lib/mongoid/extensions/hash/scoping.rb +25 -0
- data/lib/mongoid/extensions/integer/checks.rb +23 -0
- data/lib/mongoid/extensions/nil/collectionization.rb +23 -0
- data/lib/mongoid/extensions/object/checks.rb +29 -0
- data/lib/mongoid/extensions/object/reflections.rb +48 -0
- data/lib/mongoid/extensions/object/substitutable.rb +15 -0
- data/lib/mongoid/extensions/object/yoda.rb +44 -0
- data/lib/mongoid/extensions/object_id/conversions.rb +60 -0
- data/lib/mongoid/extensions/proc/scoping.rb +25 -0
- data/lib/mongoid/extensions/string/checks.rb +36 -0
- data/lib/mongoid/extensions/string/conversions.rb +22 -0
- data/lib/mongoid/extensions/string/inflections.rb +118 -0
- data/lib/mongoid/extensions/symbol/checks.rb +23 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +66 -0
- data/lib/mongoid/extensions/true_class/equality.rb +26 -0
- data/lib/mongoid/extras.rb +31 -0
- data/lib/mongoid/factory.rb +46 -0
- data/lib/mongoid/fields.rb +332 -0
- data/lib/mongoid/fields/mappings.rb +41 -0
- data/lib/mongoid/fields/serializable.rb +201 -0
- data/lib/mongoid/fields/serializable/array.rb +49 -0
- data/lib/mongoid/fields/serializable/big_decimal.rb +42 -0
- data/lib/mongoid/fields/serializable/bignum.rb +10 -0
- data/lib/mongoid/fields/serializable/binary.rb +11 -0
- data/lib/mongoid/fields/serializable/boolean.rb +43 -0
- data/lib/mongoid/fields/serializable/date.rb +51 -0
- data/lib/mongoid/fields/serializable/date_time.rb +28 -0
- data/lib/mongoid/fields/serializable/fixnum.rb +10 -0
- data/lib/mongoid/fields/serializable/float.rb +32 -0
- data/lib/mongoid/fields/serializable/foreign_keys/array.rb +42 -0
- data/lib/mongoid/fields/serializable/foreign_keys/object.rb +47 -0
- data/lib/mongoid/fields/serializable/hash.rb +11 -0
- data/lib/mongoid/fields/serializable/integer.rb +44 -0
- data/lib/mongoid/fields/serializable/localized.rb +41 -0
- data/lib/mongoid/fields/serializable/nil_class.rb +38 -0
- data/lib/mongoid/fields/serializable/object.rb +11 -0
- data/lib/mongoid/fields/serializable/object_id.rb +31 -0
- data/lib/mongoid/fields/serializable/range.rb +42 -0
- data/lib/mongoid/fields/serializable/set.rb +42 -0
- data/lib/mongoid/fields/serializable/string.rb +27 -0
- data/lib/mongoid/fields/serializable/symbol.rb +27 -0
- data/lib/mongoid/fields/serializable/time.rb +23 -0
- data/lib/mongoid/fields/serializable/time_with_zone.rb +23 -0
- data/lib/mongoid/fields/serializable/timekeeping.rb +106 -0
- data/lib/mongoid/finders.rb +152 -0
- data/lib/mongoid/hierarchy.rb +120 -0
- data/lib/mongoid/identity.rb +92 -0
- data/lib/mongoid/identity_map.rb +119 -0
- data/lib/mongoid/indexes.rb +54 -0
- data/lib/mongoid/inspection.rb +54 -0
- data/lib/mongoid/javascript.rb +20 -0
- data/lib/mongoid/javascript/functions.yml +63 -0
- data/lib/mongoid/json.rb +16 -0
- data/lib/mongoid/keys.rb +144 -0
- data/lib/mongoid/logger.rb +39 -0
- data/lib/mongoid/matchers.rb +32 -0
- data/lib/mongoid/matchers/all.rb +21 -0
- data/lib/mongoid/matchers/and.rb +30 -0
- data/lib/mongoid/matchers/default.rb +70 -0
- data/lib/mongoid/matchers/exists.rb +23 -0
- data/lib/mongoid/matchers/gt.rb +21 -0
- data/lib/mongoid/matchers/gte.rb +21 -0
- data/lib/mongoid/matchers/in.rb +21 -0
- data/lib/mongoid/matchers/lt.rb +21 -0
- data/lib/mongoid/matchers/lte.rb +21 -0
- data/lib/mongoid/matchers/ne.rb +21 -0
- data/lib/mongoid/matchers/nin.rb +21 -0
- data/lib/mongoid/matchers/or.rb +33 -0
- data/lib/mongoid/matchers/size.rb +21 -0
- data/lib/mongoid/matchers/strategies.rb +93 -0
- data/lib/mongoid/multi_database.rb +31 -0
- data/lib/mongoid/multi_parameter_attributes.rb +106 -0
- data/lib/mongoid/named_scope.rb +146 -0
- data/lib/mongoid/nested_attributes.rb +54 -0
- data/lib/mongoid/observer.rb +170 -0
- data/lib/mongoid/paranoia.rb +158 -0
- data/lib/mongoid/persistence.rb +264 -0
- data/lib/mongoid/persistence/atomic.rb +223 -0
- data/lib/mongoid/persistence/atomic/add_to_set.rb +35 -0
- data/lib/mongoid/persistence/atomic/bit.rb +37 -0
- data/lib/mongoid/persistence/atomic/inc.rb +31 -0
- data/lib/mongoid/persistence/atomic/operation.rb +85 -0
- data/lib/mongoid/persistence/atomic/pop.rb +34 -0
- data/lib/mongoid/persistence/atomic/pull.rb +34 -0
- data/lib/mongoid/persistence/atomic/pull_all.rb +34 -0
- data/lib/mongoid/persistence/atomic/push.rb +31 -0
- data/lib/mongoid/persistence/atomic/push_all.rb +31 -0
- data/lib/mongoid/persistence/atomic/rename.rb +31 -0
- data/lib/mongoid/persistence/atomic/sets.rb +30 -0
- data/lib/mongoid/persistence/atomic/unset.rb +28 -0
- data/lib/mongoid/persistence/deletion.rb +32 -0
- data/lib/mongoid/persistence/insertion.rb +41 -0
- data/lib/mongoid/persistence/modification.rb +37 -0
- data/lib/mongoid/persistence/operations.rb +211 -0
- data/lib/mongoid/persistence/operations/embedded/insert.rb +42 -0
- data/lib/mongoid/persistence/operations/embedded/remove.rb +40 -0
- data/lib/mongoid/persistence/operations/insert.rb +34 -0
- data/lib/mongoid/persistence/operations/remove.rb +33 -0
- data/lib/mongoid/persistence/operations/update.rb +64 -0
- data/lib/mongoid/railtie.rb +126 -0
- data/lib/mongoid/railties/database.rake +182 -0
- data/lib/mongoid/railties/document.rb +12 -0
- data/lib/mongoid/relations.rb +144 -0
- data/lib/mongoid/relations/accessors.rb +138 -0
- data/lib/mongoid/relations/auto_save.rb +38 -0
- data/lib/mongoid/relations/binding.rb +26 -0
- data/lib/mongoid/relations/bindings.rb +9 -0
- data/lib/mongoid/relations/bindings/embedded/in.rb +69 -0
- data/lib/mongoid/relations/bindings/embedded/many.rb +93 -0
- data/lib/mongoid/relations/bindings/embedded/one.rb +61 -0
- data/lib/mongoid/relations/bindings/referenced/in.rb +76 -0
- data/lib/mongoid/relations/bindings/referenced/many.rb +54 -0
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +51 -0
- data/lib/mongoid/relations/bindings/referenced/one.rb +58 -0
- data/lib/mongoid/relations/builder.rb +57 -0
- data/lib/mongoid/relations/builders.rb +83 -0
- data/lib/mongoid/relations/builders/embedded/in.rb +29 -0
- data/lib/mongoid/relations/builders/embedded/many.rb +40 -0
- data/lib/mongoid/relations/builders/embedded/one.rb +30 -0
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +110 -0
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
- data/lib/mongoid/relations/builders/referenced/in.rb +26 -0
- data/lib/mongoid/relations/builders/referenced/many.rb +27 -0
- data/lib/mongoid/relations/builders/referenced/many_to_many.rb +38 -0
- data/lib/mongoid/relations/builders/referenced/one.rb +26 -0
- data/lib/mongoid/relations/cascading.rb +56 -0
- data/lib/mongoid/relations/cascading/delete.rb +19 -0
- data/lib/mongoid/relations/cascading/destroy.rb +26 -0
- data/lib/mongoid/relations/cascading/nullify.rb +18 -0
- data/lib/mongoid/relations/cascading/strategy.rb +26 -0
- data/lib/mongoid/relations/constraint.rb +42 -0
- data/lib/mongoid/relations/conversions.rb +35 -0
- data/lib/mongoid/relations/cyclic.rb +103 -0
- data/lib/mongoid/relations/embedded/atomic.rb +89 -0
- data/lib/mongoid/relations/embedded/atomic/operation.rb +63 -0
- data/lib/mongoid/relations/embedded/atomic/pull.rb +65 -0
- data/lib/mongoid/relations/embedded/atomic/push_all.rb +59 -0
- data/lib/mongoid/relations/embedded/atomic/set.rb +61 -0
- data/lib/mongoid/relations/embedded/atomic/unset.rb +41 -0
- data/lib/mongoid/relations/embedded/in.rb +220 -0
- data/lib/mongoid/relations/embedded/many.rb +560 -0
- data/lib/mongoid/relations/embedded/one.rb +206 -0
- data/lib/mongoid/relations/embedded/sort.rb +31 -0
- data/lib/mongoid/relations/macros.rb +310 -0
- data/lib/mongoid/relations/many.rb +135 -0
- data/lib/mongoid/relations/metadata.rb +919 -0
- data/lib/mongoid/relations/nested_builder.rb +75 -0
- data/lib/mongoid/relations/one.rb +36 -0
- data/lib/mongoid/relations/options.rb +47 -0
- data/lib/mongoid/relations/polymorphic.rb +40 -0
- data/lib/mongoid/relations/proxy.rb +145 -0
- data/lib/mongoid/relations/referenced/batch.rb +72 -0
- data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
- data/lib/mongoid/relations/referenced/in.rb +262 -0
- data/lib/mongoid/relations/referenced/many.rb +623 -0
- data/lib/mongoid/relations/referenced/many_to_many.rb +396 -0
- data/lib/mongoid/relations/referenced/one.rb +272 -0
- data/lib/mongoid/relations/reflections.rb +62 -0
- data/lib/mongoid/relations/synchronization.rb +153 -0
- data/lib/mongoid/relations/targets.rb +2 -0
- data/lib/mongoid/relations/targets/enumerable.rb +372 -0
- data/lib/mongoid/reloading.rb +91 -0
- data/lib/mongoid/safety.rb +105 -0
- data/lib/mongoid/scope.rb +31 -0
- data/lib/mongoid/serialization.rb +134 -0
- data/lib/mongoid/sharding.rb +61 -0
- data/lib/mongoid/state.rb +97 -0
- data/lib/mongoid/threaded.rb +530 -0
- data/lib/mongoid/threaded/lifecycle.rb +192 -0
- data/lib/mongoid/timestamps.rb +15 -0
- data/lib/mongoid/timestamps/created.rb +24 -0
- data/lib/mongoid/timestamps/timeless.rb +50 -0
- data/lib/mongoid/timestamps/updated.rb +26 -0
- data/lib/mongoid/validations.rb +140 -0
- data/lib/mongoid/validations/associated.rb +46 -0
- data/lib/mongoid/validations/uniqueness.rb +145 -0
- data/lib/mongoid/version.rb +4 -0
- data/lib/mongoid/versioning.rb +185 -0
- data/lib/rack/mongoid.rb +2 -0
- data/lib/rack/mongoid/middleware/identity_map.rb +38 -0
- data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +20 -0
- data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
- data/lib/rails/generators/mongoid/model/templates/model.rb.tt +19 -0
- data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
- data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +4 -0
- data/lib/rails/generators/mongoid_generator.rb +70 -0
- data/lib/rails/mongoid.rb +91 -0
- metadata +465 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid # :nodoc:
|
3
|
+
module Relations #:nodoc:
|
4
|
+
|
5
|
+
# The reflections module provides convenience methods that can retrieve
|
6
|
+
# useful information about associations.
|
7
|
+
module Reflections
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
# Returns the relation metadata for the supplied name.
|
11
|
+
#
|
12
|
+
# @example Find relation metadata by name.
|
13
|
+
# person.reflect_on_association(:addresses)
|
14
|
+
#
|
15
|
+
# @param [ String, Symbol ] name The name of the relation to find.
|
16
|
+
#
|
17
|
+
# @return [ Metadata ] The matching relation metadata.
|
18
|
+
def reflect_on_association(name)
|
19
|
+
self.class.reflect_on_association(name)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns all relation metadata for the supplied macros.
|
23
|
+
#
|
24
|
+
# @example Find multiple relation metadata by macro.
|
25
|
+
# person.reflect_on_all_associations(:embeds_many)
|
26
|
+
#
|
27
|
+
# @param [ Array<String, Symbol> ] *macros The relation macros.
|
28
|
+
#
|
29
|
+
# @return [ Array<Metadata> ] The matching relation metadata.
|
30
|
+
def reflect_on_all_associations(*macros)
|
31
|
+
self.class.reflect_on_all_associations(*macros)
|
32
|
+
end
|
33
|
+
|
34
|
+
module ClassMethods #:nodoc
|
35
|
+
|
36
|
+
# Returns the relation metadata for the supplied name.
|
37
|
+
#
|
38
|
+
# @example Find relation metadata by name.
|
39
|
+
# Person.reflect_on_association(:addresses)
|
40
|
+
#
|
41
|
+
# @param [ String, Symbol ] name The name of the relation to find.
|
42
|
+
#
|
43
|
+
# @return [ Metadata ] The matching relation metadata.
|
44
|
+
def reflect_on_association(name)
|
45
|
+
relations[name.to_s]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns all relation metadata for the supplied macros.
|
49
|
+
#
|
50
|
+
# @example Find multiple relation metadata by macro.
|
51
|
+
# Person.reflect_on_all_associations(:embeds_many)
|
52
|
+
#
|
53
|
+
# @param [ Array<String, Symbol> ] *macros The relation macros.
|
54
|
+
#
|
55
|
+
# @return [ Array<Metadata> ] The matching relation metadata.
|
56
|
+
def reflect_on_all_associations(*macros)
|
57
|
+
relations.values.select { |meta| macros.include?(meta.macro) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid # :nodoc:
|
3
|
+
module Relations #:nodoc:
|
4
|
+
|
5
|
+
# This module handles the behaviour for synchronizing foreign keys between
|
6
|
+
# both sides of a many to many relations.
|
7
|
+
module Synchronization
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
# Is the document able to be synced on the inverse side? This is only if
|
11
|
+
# the key has changed and the relation bindings have not been run.
|
12
|
+
#
|
13
|
+
# @example Are the foreign keys syncable?
|
14
|
+
# document.syncable?(metadata)
|
15
|
+
#
|
16
|
+
# @param [ Metadata ] metadata The relation metadata.
|
17
|
+
#
|
18
|
+
# @return [ true, false ] If we can sync.
|
19
|
+
#
|
20
|
+
# @since 2.1.0
|
21
|
+
def syncable?(metadata)
|
22
|
+
!synced?(metadata.foreign_key) && send(metadata.foreign_key_check)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get the synced foreign keys.
|
26
|
+
#
|
27
|
+
# @example Get the synced foreign keys.
|
28
|
+
# document.synced
|
29
|
+
#
|
30
|
+
# @return [ Hash ] The synced foreign keys.
|
31
|
+
#
|
32
|
+
# @since 2.1.0
|
33
|
+
def synced
|
34
|
+
@synced ||= {}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Has the document been synced for the foreign key?
|
38
|
+
#
|
39
|
+
# @todo Change the sync to be key based.
|
40
|
+
#
|
41
|
+
# @example Has the document been synced?
|
42
|
+
# document.synced?
|
43
|
+
#
|
44
|
+
# @param [ String ] foreign_key The foreign key.
|
45
|
+
#
|
46
|
+
# @return [ true, false ] If we can sync.
|
47
|
+
#
|
48
|
+
# @since 2.1.0
|
49
|
+
def synced?(foreign_key)
|
50
|
+
!!synced[foreign_key]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Update the inverse keys on destroy.
|
54
|
+
#
|
55
|
+
# @example Update the inverse keys.
|
56
|
+
# document.remove_inverse_keys(metadata)
|
57
|
+
#
|
58
|
+
# @param [ Metadata ] meta The document metadata.
|
59
|
+
#
|
60
|
+
# @return [ Object ] The updated values.
|
61
|
+
#
|
62
|
+
# @since 2.2.1
|
63
|
+
def remove_inverse_keys(meta)
|
64
|
+
meta.criteria(send(meta.foreign_key)).pull(meta.inverse_foreign_key, id)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Update the inverse keys for the relation.
|
68
|
+
#
|
69
|
+
# @example Update the inverse keys
|
70
|
+
# document.update_inverse_keys(metadata)
|
71
|
+
#
|
72
|
+
# @param [ Metadata ] meta The document metadata.
|
73
|
+
#
|
74
|
+
# @return [ Object ] The updated values.
|
75
|
+
#
|
76
|
+
# @since 2.1.0
|
77
|
+
def update_inverse_keys(meta)
|
78
|
+
return unless changes.has_key?(meta.foreign_key)
|
79
|
+
old, new = changes[meta.foreign_key]
|
80
|
+
adds, subs = new - (old || []), (old || []) - new
|
81
|
+
meta.criteria(adds).add_to_set(meta.inverse_foreign_key, id) unless adds.empty?
|
82
|
+
meta.criteria(subs).pull(meta.inverse_foreign_key, id) unless subs.empty?
|
83
|
+
end
|
84
|
+
|
85
|
+
module ClassMethods #:nodoc:
|
86
|
+
|
87
|
+
# Set up the syncing of many to many foreign keys.
|
88
|
+
#
|
89
|
+
# @example Set up the syncing.
|
90
|
+
# Person.synced(metadata)
|
91
|
+
#
|
92
|
+
# @param [ Metadata ] metadata The relation metadata.
|
93
|
+
#
|
94
|
+
# @since 2.1.0
|
95
|
+
def synced(metadata)
|
96
|
+
unless metadata.forced_nil_inverse?
|
97
|
+
synced_save(metadata)
|
98
|
+
synced_destroy(metadata)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
# Set up the sync of inverse keys that needs to happen on a save.
|
105
|
+
#
|
106
|
+
# If the foreign key field has changed and the document is not
|
107
|
+
# synced, $addToSet the new ids, $pull the ones no longer in the
|
108
|
+
# array from the inverse side.
|
109
|
+
#
|
110
|
+
# @example Set up the save syncing.
|
111
|
+
# Person.synced_save(metadata)
|
112
|
+
#
|
113
|
+
# @param [ Metadata ] metadata The relation metadata.
|
114
|
+
#
|
115
|
+
# @return [ Class ] The class getting set up.
|
116
|
+
#
|
117
|
+
# @since 2.1.0
|
118
|
+
def synced_save(metadata)
|
119
|
+
tap do
|
120
|
+
set_callback(
|
121
|
+
:save,
|
122
|
+
:after,
|
123
|
+
:if => lambda { |doc| doc.syncable?(metadata) }
|
124
|
+
) do |doc|
|
125
|
+
doc.update_inverse_keys(metadata)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Set up the sync of inverse keys that needs to happen on a destroy.
|
131
|
+
#
|
132
|
+
# @example Set up the destroy syncing.
|
133
|
+
# Person.synced_destroy(metadata)
|
134
|
+
#
|
135
|
+
# @param [ Metadata ] metadata The relation metadata.
|
136
|
+
#
|
137
|
+
# @return [ Class ] The class getting set up.
|
138
|
+
#
|
139
|
+
# @since 2.2.1
|
140
|
+
def synced_destroy(metadata)
|
141
|
+
tap do
|
142
|
+
set_callback(
|
143
|
+
:destroy,
|
144
|
+
:after
|
145
|
+
) do |doc|
|
146
|
+
doc.remove_inverse_keys(metadata)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,372 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid #:nodoc:
|
3
|
+
module Relations #:nodoc:
|
4
|
+
module Targets #:nodoc:
|
5
|
+
|
6
|
+
# This class is the wrapper for all relational associations that have a
|
7
|
+
# target that can be a criteria or array of loaded documents. This
|
8
|
+
# handles both cases or a combination of the two.
|
9
|
+
class Enumerable
|
10
|
+
include ::Enumerable
|
11
|
+
|
12
|
+
# The three main instance variables are collections of documents.
|
13
|
+
#
|
14
|
+
# @attribute [rw] added Documents that have been appended.
|
15
|
+
# @attribute [rw] loaded Persisted documents that have been loaded.
|
16
|
+
# @attribute [rw] unloaded A criteria representing persisted docs.
|
17
|
+
attr_accessor :added, :loaded, :unloaded
|
18
|
+
|
19
|
+
delegate :===, :is_a?, :kind_of?, :to => :added
|
20
|
+
|
21
|
+
# Check if the enumerable is equal to the other object.
|
22
|
+
#
|
23
|
+
# @example Check equality.
|
24
|
+
# enumerable == []
|
25
|
+
#
|
26
|
+
# @param [ Enumerable ] other The other enumerable.
|
27
|
+
#
|
28
|
+
# @return [ true, false ] If the objects are equal.
|
29
|
+
#
|
30
|
+
# @since 2.1.0
|
31
|
+
def ==(other)
|
32
|
+
return false unless other.respond_to?(:entries)
|
33
|
+
entries == other.entries
|
34
|
+
end
|
35
|
+
|
36
|
+
# Append a document to the enumerable.
|
37
|
+
#
|
38
|
+
# @example Append the document.
|
39
|
+
# enumerable << document
|
40
|
+
#
|
41
|
+
# @param [ Document ] document The document to append.
|
42
|
+
#
|
43
|
+
# @return [ Document ] The document.
|
44
|
+
#
|
45
|
+
# @since 2.1.0
|
46
|
+
def <<(document)
|
47
|
+
added.push(document)
|
48
|
+
end
|
49
|
+
alias :push :<<
|
50
|
+
|
51
|
+
# Clears out all the documents in this enumerable. If passed a block it
|
52
|
+
# will yield to each document that is in memory.
|
53
|
+
#
|
54
|
+
# @example Clear out the enumerable.
|
55
|
+
# enumerable.clear
|
56
|
+
#
|
57
|
+
# @example Clear out the enumerable with a block.
|
58
|
+
# enumerable.clear do |doc|
|
59
|
+
# doc.unbind
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# @return [ Array<Document> ] The cleared out added docs.
|
63
|
+
#
|
64
|
+
# @since 2.1.0
|
65
|
+
def clear
|
66
|
+
if block_given?
|
67
|
+
in_memory { |doc| yield(doc) }
|
68
|
+
end
|
69
|
+
loaded.clear and added.clear
|
70
|
+
end
|
71
|
+
|
72
|
+
# Clones each document in the enumerable.
|
73
|
+
#
|
74
|
+
# @note This loads all documents into memory.
|
75
|
+
#
|
76
|
+
# @example Clone the enumerable.
|
77
|
+
# enumerable.clone
|
78
|
+
#
|
79
|
+
# @return [ Array<Document> ] An array clone of the enumerable.
|
80
|
+
#
|
81
|
+
# @since 2.1.6
|
82
|
+
def clone
|
83
|
+
collect { |doc| doc.clone }
|
84
|
+
end
|
85
|
+
|
86
|
+
# Delete the supplied document from the enumerable.
|
87
|
+
#
|
88
|
+
# @example Delete the document.
|
89
|
+
# enumerable.delete(document)
|
90
|
+
#
|
91
|
+
# @param [ Document ] document The document to delete.
|
92
|
+
#
|
93
|
+
# @return [ Document ] The deleted document.
|
94
|
+
#
|
95
|
+
# @since 2.1.0
|
96
|
+
def delete(document)
|
97
|
+
(loaded.delete(document) || added.delete(document)).tap do |doc|
|
98
|
+
unless doc
|
99
|
+
if unloaded && unloaded.where(:_id => document.id).exists?
|
100
|
+
yield(document) if block_given?
|
101
|
+
return document
|
102
|
+
end
|
103
|
+
end
|
104
|
+
yield(doc) if block_given?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Deletes every document in the enumerable for where the block returns
|
109
|
+
# true.
|
110
|
+
#
|
111
|
+
# @note This operation loads all documents from the database.
|
112
|
+
#
|
113
|
+
# @example Delete all matching documents.
|
114
|
+
# enumerable.delete_if do |doc|
|
115
|
+
# dod.id == id
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
# @return [ Array<Document> ] The remaining docs.
|
119
|
+
#
|
120
|
+
# @since 2.1.0
|
121
|
+
def delete_if(&block)
|
122
|
+
load_all!
|
123
|
+
tap do
|
124
|
+
loaded.delete_if(&block)
|
125
|
+
added.delete_if(&block)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Iterating over this enumerable has to handle a few different
|
130
|
+
# scenarios.
|
131
|
+
#
|
132
|
+
# If the enumerable has its criteria loaded into memory then it yields
|
133
|
+
# to all the loaded docs and all the added docs.
|
134
|
+
#
|
135
|
+
# If the enumerable has not loaded the criteria then it iterates over
|
136
|
+
# the cursor while loading the documents and then iterates over the
|
137
|
+
# added docs.
|
138
|
+
#
|
139
|
+
# @example Iterate over the enumerable.
|
140
|
+
# enumerable.each do |doc|
|
141
|
+
# puts doc
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# @return [ true ] That the enumerable is now loaded.
|
145
|
+
#
|
146
|
+
# @since 2.1.0
|
147
|
+
def each
|
148
|
+
if loaded?
|
149
|
+
loaded.each do |doc|
|
150
|
+
yield(doc)
|
151
|
+
end
|
152
|
+
else
|
153
|
+
unloaded.each do |doc|
|
154
|
+
yield(doc)
|
155
|
+
loaded.push(added.delete_one(doc) || doc)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
added.each do |doc|
|
159
|
+
yield(doc)
|
160
|
+
end
|
161
|
+
@executed = true
|
162
|
+
end
|
163
|
+
|
164
|
+
# Is the enumerable empty? Will determine if the count is zero based on
|
165
|
+
# whether or not it is loaded.
|
166
|
+
#
|
167
|
+
# @example Is the enumerable empty?
|
168
|
+
# enumerable.empty?
|
169
|
+
#
|
170
|
+
# @return [ true, false ] If the enumerable is empty.
|
171
|
+
#
|
172
|
+
# @since 2.1.0
|
173
|
+
def empty?
|
174
|
+
if loaded?
|
175
|
+
in_memory.count == 0
|
176
|
+
else
|
177
|
+
unloaded.count + added.count == 0
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Get the first document in the enumerable. Will check the persisted
|
182
|
+
# documents first. Does not load the entire enumerable.
|
183
|
+
#
|
184
|
+
# @example Get the first document.
|
185
|
+
# enumerable.first
|
186
|
+
#
|
187
|
+
# @return [ Document ] The first document found.
|
188
|
+
#
|
189
|
+
# @since 2.1.0
|
190
|
+
def first
|
191
|
+
added.first || (loaded? ? loaded.first : unloaded.first)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Initialize the new enumerable either with a criteria or an array.
|
195
|
+
#
|
196
|
+
# @example Initialize the enumerable with a criteria.
|
197
|
+
# Enumberable.new(Post.where(:person_id => id))
|
198
|
+
#
|
199
|
+
# @example Initialize the enumerable with an array.
|
200
|
+
# Enumerable.new([ post ])
|
201
|
+
#
|
202
|
+
# @param [ Criteria, Array<Document> ] target The wrapped object.
|
203
|
+
#
|
204
|
+
# @since 2.1.0
|
205
|
+
def initialize(target)
|
206
|
+
if target.is_a?(Criteria)
|
207
|
+
@added, @loaded, @unloaded = [], [], target
|
208
|
+
else
|
209
|
+
@added, @executed, @loaded = [], true, target
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# Inspection will just inspect the entries for nice array-style
|
214
|
+
# printing.
|
215
|
+
#
|
216
|
+
# @example Inspect the enumerable.
|
217
|
+
# enumerable.inspect
|
218
|
+
#
|
219
|
+
# @return [ String ] The inspected enum.
|
220
|
+
#
|
221
|
+
# @since 2.1.0
|
222
|
+
def inspect
|
223
|
+
entries.inspect
|
224
|
+
end
|
225
|
+
|
226
|
+
# Return all the documents in the enumerable that have been loaded or
|
227
|
+
# added.
|
228
|
+
#
|
229
|
+
# @note When passed a block it yields to each document.
|
230
|
+
#
|
231
|
+
# @example Get the in memory docs.
|
232
|
+
# enumerable.in_memory
|
233
|
+
#
|
234
|
+
# @return [ Array<Document> ] The in memory docs.
|
235
|
+
#
|
236
|
+
# @since 2.1.0
|
237
|
+
def in_memory
|
238
|
+
(loaded + added).tap do |docs|
|
239
|
+
docs.each { |doc| yield(doc) } if block_given?
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# Get the last document in the enumerable. Will check the new
|
244
|
+
# documents first. Does not load the entire enumerable.
|
245
|
+
#
|
246
|
+
# @example Get the last document.
|
247
|
+
# enumerable.last
|
248
|
+
#
|
249
|
+
# @return [ Document ] The last document found.
|
250
|
+
#
|
251
|
+
# @since 2.1.0
|
252
|
+
def last
|
253
|
+
added.last || (loaded? ? loaded.last : unloaded.last)
|
254
|
+
end
|
255
|
+
|
256
|
+
# Loads all the documents in the enumerable from the database.
|
257
|
+
#
|
258
|
+
# @example Load all the documents.
|
259
|
+
# enumerable.load_all!
|
260
|
+
#
|
261
|
+
# @return [ true ] That the enumerable is loaded.
|
262
|
+
#
|
263
|
+
# @since 2.1.0
|
264
|
+
alias :load_all! :entries
|
265
|
+
|
266
|
+
# Has the enumerable been loaded? This will be true if the criteria has
|
267
|
+
# been executed or we manually load the entire thing.
|
268
|
+
#
|
269
|
+
# @example Is the enumerable loaded?
|
270
|
+
# enumerable.loaded?
|
271
|
+
#
|
272
|
+
# @return [ true, false ] If the enumerable has been loaded.
|
273
|
+
#
|
274
|
+
# @since 2.1.0
|
275
|
+
def loaded?
|
276
|
+
!!@executed
|
277
|
+
end
|
278
|
+
|
279
|
+
# Reset the enumerable back to it's persisted state.
|
280
|
+
#
|
281
|
+
# @example Reset the enumerable.
|
282
|
+
# enumerable.reset
|
283
|
+
#
|
284
|
+
# @return [ false ] Always false.
|
285
|
+
#
|
286
|
+
# @since 2.1.0
|
287
|
+
def reset
|
288
|
+
loaded.clear and added.clear
|
289
|
+
@executed = false
|
290
|
+
end
|
291
|
+
|
292
|
+
# Does this enumerable respond to the provided method?
|
293
|
+
#
|
294
|
+
# @example Does the enumerable respond to the method?
|
295
|
+
# enumerable.respond_to?(:sum)
|
296
|
+
#
|
297
|
+
# @param [ String, Symbol ] name The name of the method.
|
298
|
+
# @param [ true, false ] include_private Whether to include private
|
299
|
+
# methods.
|
300
|
+
#
|
301
|
+
# @return [ true, false ] Whether the enumerable responds.
|
302
|
+
#
|
303
|
+
# @since 2.1.0
|
304
|
+
def respond_to?(name, include_private = false)
|
305
|
+
[].respond_to?(name, include_private) || super
|
306
|
+
end
|
307
|
+
|
308
|
+
# Gets the total size of this enumerable. This is a combination of all
|
309
|
+
# the persisted and unpersisted documents.
|
310
|
+
#
|
311
|
+
# @example Get the size.
|
312
|
+
# enumerable.size
|
313
|
+
#
|
314
|
+
# @return [ Integer ] The size of the enumerable.
|
315
|
+
#
|
316
|
+
# @since 2.1.0
|
317
|
+
def size
|
318
|
+
(unloaded ? unloaded.count : loaded.count) + added.count{ |d| d.new? }
|
319
|
+
end
|
320
|
+
alias :length :size
|
321
|
+
|
322
|
+
# Send #to_json to the entries.
|
323
|
+
#
|
324
|
+
# @example Get the enumerable as json.
|
325
|
+
# enumerable.to_json
|
326
|
+
#
|
327
|
+
# @param [ Hash ] options Optional parameters.
|
328
|
+
#
|
329
|
+
# @return [ String ] The entries all loaded as a string.
|
330
|
+
#
|
331
|
+
# @since 2.2.0
|
332
|
+
def to_json(options = {})
|
333
|
+
entries.to_json(options)
|
334
|
+
end
|
335
|
+
|
336
|
+
# Send #as_json to the entries, without encoding.
|
337
|
+
#
|
338
|
+
# @example Get the enumerable as json.
|
339
|
+
# enumerable.as_json
|
340
|
+
#
|
341
|
+
# @param [ Hash ] options Optional parameters.
|
342
|
+
#
|
343
|
+
# @return [ Hash ] The entries all loaded as a hash.
|
344
|
+
#
|
345
|
+
# @since 2.2.0
|
346
|
+
def as_json(options = {})
|
347
|
+
entries.as_json(options)
|
348
|
+
end
|
349
|
+
|
350
|
+
# Return all the unique documents in the enumerable.
|
351
|
+
#
|
352
|
+
# @note This operation loads all documents from the database.
|
353
|
+
#
|
354
|
+
# @example Get all the unique documents.
|
355
|
+
# enumerable.uniq
|
356
|
+
#
|
357
|
+
# @return [ Array<Document> ] The unique documents.
|
358
|
+
#
|
359
|
+
# @since 2.1.0
|
360
|
+
def uniq
|
361
|
+
entries.uniq
|
362
|
+
end
|
363
|
+
|
364
|
+
private
|
365
|
+
|
366
|
+
def method_missing(name, *args, &block)
|
367
|
+
entries.send(name, *args, &block)
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|