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,2006 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require_relative './has_one_models'
|
|
3
|
+
|
|
4
|
+
describe Mongoid::Association::Referenced::BelongsTo do
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
class OwnerObject; include Mongoid::Document; end
|
|
8
|
+
class BelongingObject; include Mongoid::Document; end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
after do
|
|
12
|
+
Object.send(:remove_const, :BelongingObject)
|
|
13
|
+
Object.send(:remove_const, :OwnerObject)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
let(:belonging_class) do
|
|
17
|
+
BelongingObject
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
let(:name) do
|
|
21
|
+
:owner_object
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
let(:association) do
|
|
25
|
+
belonging_class.belongs_to name, options
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
let(:options) do
|
|
29
|
+
{ }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe '#relation_complements' do
|
|
33
|
+
|
|
34
|
+
let(:expected_complements) do
|
|
35
|
+
[
|
|
36
|
+
Mongoid::Association::Referenced::HasMany,
|
|
37
|
+
Mongoid::Association::Referenced::HasOne
|
|
38
|
+
]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'returns the relation complements' do
|
|
42
|
+
expect(association.relation_complements).to eq(expected_complements)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe '#setup!' do
|
|
47
|
+
|
|
48
|
+
it 'sets up a getter for the relation' do
|
|
49
|
+
expect(Mongoid::Association::Accessors).to receive(:define_getter!).with(association)
|
|
50
|
+
association.setup!
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'sets up a setter for the relation' do
|
|
54
|
+
expect(Mongoid::Association::Accessors).to receive(:define_setter!).with(association)
|
|
55
|
+
association.setup!
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'sets up an existence check for the relation' do
|
|
59
|
+
expect(Mongoid::Association::Accessors).to receive(:define_existence_check!).with(association)
|
|
60
|
+
association.setup!
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'sets up the builder for the relation' do
|
|
64
|
+
expect(Mongoid::Association::Builders).to receive(:define_builder!).with(association)
|
|
65
|
+
association.setup!
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'sets up the creator for the relation' do
|
|
69
|
+
expect(Mongoid::Association::Builders).to receive(:define_creator!).with(association)
|
|
70
|
+
association.setup!
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context 'autosave' do
|
|
74
|
+
|
|
75
|
+
context 'when the :autosave option is true' do
|
|
76
|
+
|
|
77
|
+
let(:options) do
|
|
78
|
+
{
|
|
79
|
+
autosave: true
|
|
80
|
+
}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
let(:association) do
|
|
84
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
85
|
+
# setup!! method will be called by the :belongs_to macro
|
|
86
|
+
described_class.new(belonging_class, name, options)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'sets up autosave' do
|
|
90
|
+
expect(Mongoid::Association::Referenced::AutoSave).to receive(:define_autosave!).with(association)
|
|
91
|
+
association.setup!
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context 'when the :autosave option is false' do
|
|
96
|
+
|
|
97
|
+
let(:options) do
|
|
98
|
+
{
|
|
99
|
+
autosave: false
|
|
100
|
+
}
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'does not set up autosave' do
|
|
104
|
+
expect(Mongoid::Association::Referenced::AutoSave).not_to receive(:define_autosave!)
|
|
105
|
+
association.setup!
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context 'when the :autosave option is not provided' do
|
|
110
|
+
|
|
111
|
+
let(:association) do
|
|
112
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
113
|
+
# setup!! method will be called by the :embeds_many macro
|
|
114
|
+
described_class.new(belonging_class, name, options)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'does not set up autosave' do
|
|
118
|
+
expect(Mongoid::Association::Referenced::AutoSave).not_to receive(:define_autosave!)
|
|
119
|
+
association.setup!
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context 'counter cache callbacks' do
|
|
125
|
+
|
|
126
|
+
context 'when the :counter_cache option is true' do
|
|
127
|
+
|
|
128
|
+
let(:options) do
|
|
129
|
+
{
|
|
130
|
+
counter_cache: true
|
|
131
|
+
}
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
let(:association) do
|
|
135
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
136
|
+
# setup! method will be called by the :belongs_to macro
|
|
137
|
+
described_class.new(belonging_class, name, options)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'sets up counter cache callbacks' do
|
|
141
|
+
expect(Mongoid::Association::Referenced::CounterCache).to receive(:define_callbacks!).with(association)
|
|
142
|
+
association.setup!
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
context 'when the :counter_cache option is a String' do
|
|
147
|
+
|
|
148
|
+
let(:options) do
|
|
149
|
+
{
|
|
150
|
+
counter_cache: 'counts_field'
|
|
151
|
+
}
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
let(:association) do
|
|
155
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
156
|
+
# setup! method will be called by the :belongs_to macro
|
|
157
|
+
described_class.new(belonging_class, name, options)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'sets up counter cache callbacks' do
|
|
161
|
+
expect(Mongoid::Association::Referenced::CounterCache).to receive(:define_callbacks!).with(association)
|
|
162
|
+
association.setup!
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context 'when the :counter_cache option is false' do
|
|
167
|
+
|
|
168
|
+
let(:options) do
|
|
169
|
+
{
|
|
170
|
+
counter_cache: false
|
|
171
|
+
}
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'does not set up counter cache callbacks' do
|
|
175
|
+
expect(Mongoid::Association::Referenced::CounterCache).not_to receive(:define_callbacks!)
|
|
176
|
+
association.setup!
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
context 'when the :counter_cache option is not provided' do
|
|
181
|
+
|
|
182
|
+
let(:association) do
|
|
183
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
184
|
+
# setup! method will be called by the :embeds_many macro
|
|
185
|
+
described_class.new(belonging_class, name, options)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it 'does not set up counter cache callbacks' do
|
|
189
|
+
expect(Mongoid::Association::Referenced::CounterCache).not_to receive(:define_callbacks!)
|
|
190
|
+
association.setup!
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
context 'polymorphic' do
|
|
196
|
+
|
|
197
|
+
context 'when the polymorphic option is provided' do
|
|
198
|
+
|
|
199
|
+
context 'when the polymorphic option is true' do
|
|
200
|
+
|
|
201
|
+
let(:options) do
|
|
202
|
+
{
|
|
203
|
+
polymorphic: true
|
|
204
|
+
}
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
before do
|
|
208
|
+
association
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'set the polymorphic attribute on the owner class' do
|
|
212
|
+
expect(belonging_class.polymorphic).to be(true)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it 'sets up a field for the inverse type' do
|
|
216
|
+
expect(belonging_class.fields.keys).to include(association.inverse_type)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
context 'when the polymorphic option is false' do
|
|
221
|
+
|
|
222
|
+
let(:options) do
|
|
223
|
+
{
|
|
224
|
+
polymorphic: false
|
|
225
|
+
}
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it 'does not set the polymorphic attribute on the owner class' do
|
|
229
|
+
expect(belonging_class.polymorphic).to be(false)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it 'does not set up a field for the inverse type' do
|
|
233
|
+
expect(belonging_class.fields.keys).not_to include(association.inverse_type)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
context 'when the polymorphic option is not provided' do
|
|
239
|
+
|
|
240
|
+
it 'does not set the polymorphic attribute on the owner class' do
|
|
241
|
+
expect(belonging_class.polymorphic).to be(false)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it 'does not set up a field for the inverse type' do
|
|
245
|
+
expect(belonging_class.fields.keys).not_to include(association.inverse_type)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
context 'dependent' do
|
|
251
|
+
|
|
252
|
+
context 'when the dependent option is provided' do
|
|
253
|
+
|
|
254
|
+
context 'when the dependent option is :delete_all' do
|
|
255
|
+
|
|
256
|
+
let(:options) do
|
|
257
|
+
{
|
|
258
|
+
dependent: :delete_all
|
|
259
|
+
}
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
let(:association) do
|
|
263
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
264
|
+
# setup! method will be called by the :belongs_to macro
|
|
265
|
+
described_class.new(belonging_class, name, options)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
it 'sets up the dependency' do
|
|
269
|
+
expect(Mongoid::Association::Depending).to receive(:define_dependency!)
|
|
270
|
+
association.setup!
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
context 'when the dependent option is :destroy' do
|
|
275
|
+
|
|
276
|
+
let(:options) do
|
|
277
|
+
{
|
|
278
|
+
dependent: :destroy
|
|
279
|
+
}
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
let(:association) do
|
|
283
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
284
|
+
# setup! method will be called by the :belongs_to macro
|
|
285
|
+
described_class.new(belonging_class, name, options)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it 'sets up the dependency' do
|
|
289
|
+
expect(Mongoid::Association::Depending).to receive(:define_dependency!)
|
|
290
|
+
association.setup!
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
context 'when the dependent option is :nullify' do
|
|
295
|
+
|
|
296
|
+
let(:options) do
|
|
297
|
+
{
|
|
298
|
+
dependent: :nullify
|
|
299
|
+
}
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
let(:association) do
|
|
303
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
304
|
+
# setup! method will be called by the :belongs_to macro
|
|
305
|
+
described_class.new(belonging_class, name, options)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it 'sets up the dependency' do
|
|
309
|
+
expect(Mongoid::Association::Depending).to receive(:define_dependency!)
|
|
310
|
+
association.setup!
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
context 'when the dependent option is :restrict_with_exception' do
|
|
315
|
+
|
|
316
|
+
let(:options) do
|
|
317
|
+
{
|
|
318
|
+
dependent: :restrict_with_exception
|
|
319
|
+
}
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
let(:association) do
|
|
323
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
324
|
+
# setup! method will be called by the :belongs_to macro
|
|
325
|
+
described_class.new(belonging_class, name, options)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it 'sets up the dependency' do
|
|
329
|
+
expect(Mongoid::Association::Depending).to receive(:define_dependency!)
|
|
330
|
+
association.setup!
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
context 'when the dependent option is :restrict_with_error' do
|
|
335
|
+
|
|
336
|
+
let(:options) do
|
|
337
|
+
{
|
|
338
|
+
dependent: :restrict_with_error
|
|
339
|
+
}
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
let(:association) do
|
|
343
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
344
|
+
# setup! method will be called by the :belongs_to macro
|
|
345
|
+
described_class.new(belonging_class, name, options)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it 'sets up the dependency' do
|
|
349
|
+
expect(Mongoid::Association::Depending).to receive(:define_dependency!)
|
|
350
|
+
association.setup!
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
context 'when the dependent option is not provided' do
|
|
356
|
+
|
|
357
|
+
it 'does not set up the dependency' do
|
|
358
|
+
expect(Mongoid::Association::Depending).not_to receive(:define_dependency!)
|
|
359
|
+
association.setup!
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
context 'foreign key field' do
|
|
365
|
+
|
|
366
|
+
before do
|
|
367
|
+
association
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
it 'sets up the foreign key field' do
|
|
371
|
+
expect(belonging_class.fields.keys).to include(association.foreign_key)
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
context 'index' do
|
|
376
|
+
|
|
377
|
+
before do
|
|
378
|
+
association
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
context 'when index is true' do
|
|
382
|
+
|
|
383
|
+
context 'when polymorphic' do
|
|
384
|
+
|
|
385
|
+
let(:options) do
|
|
386
|
+
{
|
|
387
|
+
polymorphic: true,
|
|
388
|
+
index: true
|
|
389
|
+
}
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
it 'sets up the index with the key and inverse type' do
|
|
393
|
+
expect(belonging_class.index_specifications.first.fields).to match_array([ association.key.to_sym,
|
|
394
|
+
association.inverse_type.to_sym])
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
context 'when not polymorphic' do
|
|
399
|
+
|
|
400
|
+
let(:options) do
|
|
401
|
+
{
|
|
402
|
+
index: true
|
|
403
|
+
}
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
it 'sets up the index with the key' do
|
|
407
|
+
expect(belonging_class.index_specifications.first.fields).to match_array([ association.key.to_sym ])
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
context 'when index is false' do
|
|
413
|
+
|
|
414
|
+
context 'when polymorphic' do
|
|
415
|
+
|
|
416
|
+
let(:options) do
|
|
417
|
+
{
|
|
418
|
+
polymorphic: true
|
|
419
|
+
}
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
it 'does not set up an index' do
|
|
423
|
+
expect(belonging_class.index_specifications).to eq([ ])
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
context 'when not polymorphic' do
|
|
428
|
+
|
|
429
|
+
it 'does not set up an index' do
|
|
430
|
+
expect(belonging_class.index_specifications).to eq([ ])
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
context 'touchable' do
|
|
437
|
+
|
|
438
|
+
context 'when the :touch option is true' do
|
|
439
|
+
|
|
440
|
+
let(:options) do
|
|
441
|
+
{
|
|
442
|
+
touch: true
|
|
443
|
+
}
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
let(:association) do
|
|
447
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
448
|
+
# setup! method will be called by the :belongs_to macro
|
|
449
|
+
described_class.new(belonging_class, name, options)
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
it 'sets up touch' do
|
|
453
|
+
expect(Mongoid::Touchable).to receive(:define_touchable!).with(association)
|
|
454
|
+
association.setup!
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
context 'when the :touch option is false' do
|
|
459
|
+
|
|
460
|
+
let(:options) do
|
|
461
|
+
{
|
|
462
|
+
touch: false
|
|
463
|
+
}
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
it 'does not set up touch' do
|
|
467
|
+
expect(Mongoid::Touchable).not_to receive(:define_touchable!).with(association)
|
|
468
|
+
association.setup!
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
context 'when the :touch option is not provided' do
|
|
473
|
+
|
|
474
|
+
let(:association) do
|
|
475
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
476
|
+
# setup! method will be called by the :embeds_many macro
|
|
477
|
+
described_class.new(belonging_class, name, options)
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
it 'does not set up touch' do
|
|
481
|
+
expect(Mongoid::Touchable).not_to receive(:define_touchable!).with(association)
|
|
482
|
+
association.setup!
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
context 'validate' do
|
|
488
|
+
|
|
489
|
+
context 'when the :validate option is true' do
|
|
490
|
+
|
|
491
|
+
let(:options) do
|
|
492
|
+
{
|
|
493
|
+
validate: true
|
|
494
|
+
}
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
let(:association) do
|
|
498
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
499
|
+
# setup! method will be called by the :belongs_to macro
|
|
500
|
+
described_class.new(belonging_class, name, options)
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
it 'sets up validation' do
|
|
504
|
+
expect(belonging_class).to receive(:validates_associated).with(name).and_call_original
|
|
505
|
+
association.setup!
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
context 'when the :validate option is false' do
|
|
510
|
+
|
|
511
|
+
let(:options) do
|
|
512
|
+
{
|
|
513
|
+
validate: false
|
|
514
|
+
}
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
it 'does not set up validation' do
|
|
518
|
+
expect(belonging_class).not_to receive(:validates_associated)
|
|
519
|
+
association.setup!
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
context 'when the :validate option is not provided' do
|
|
524
|
+
|
|
525
|
+
let(:association) do
|
|
526
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
527
|
+
# setup! method will be called by the :belongs_to macro
|
|
528
|
+
described_class.new(belonging_class, name, options)
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
it 'does not set up the validation because it uses the validation default (false)' do
|
|
532
|
+
expect(belonging_class).not_to receive(:validates_associated)
|
|
533
|
+
association.setup!
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
context 'presence of validation' do
|
|
539
|
+
|
|
540
|
+
let(:association) do
|
|
541
|
+
# Note that it is necessary to create the association directly, otherwise the
|
|
542
|
+
# setup! method will be called by the :belongs_to macro
|
|
543
|
+
described_class.new(belonging_class, name, options)
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
context 'when the global config option is true' do
|
|
547
|
+
|
|
548
|
+
around(:example) do |example|
|
|
549
|
+
original_config = Mongoid.belongs_to_required_by_default
|
|
550
|
+
Mongoid.belongs_to_required_by_default = true
|
|
551
|
+
example.run
|
|
552
|
+
Mongoid.belongs_to_required_by_default = original_config
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
let!(:original_required_config) do
|
|
556
|
+
Mongoid.belongs_to_required_by_default
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
context 'when the required option is true' do
|
|
560
|
+
|
|
561
|
+
let(:options) do
|
|
562
|
+
{
|
|
563
|
+
required: true
|
|
564
|
+
}
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
it 'sets up the presence of validation' do
|
|
568
|
+
expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
|
|
569
|
+
association.setup!
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
context 'when the optional option is true' do
|
|
573
|
+
|
|
574
|
+
let(:options) do
|
|
575
|
+
{
|
|
576
|
+
required: true,
|
|
577
|
+
optional: true
|
|
578
|
+
}
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
it 'sets up the presence of validation' do
|
|
582
|
+
expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
|
|
583
|
+
association.setup!
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
context 'when the optional option is false' do
|
|
588
|
+
|
|
589
|
+
let(:options) do
|
|
590
|
+
{
|
|
591
|
+
required: true,
|
|
592
|
+
optional: false
|
|
593
|
+
}
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
it 'sets up the presence of validation' do
|
|
597
|
+
expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
|
|
598
|
+
association.setup!
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
context 'when the required option is false' do
|
|
604
|
+
|
|
605
|
+
let(:options) do
|
|
606
|
+
{
|
|
607
|
+
required: false
|
|
608
|
+
}
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
it 'does not set up the presence of validation' do
|
|
612
|
+
expect(belonging_class).not_to receive(:validates)
|
|
613
|
+
association.setup!
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
context 'when the optional option is true' do
|
|
617
|
+
|
|
618
|
+
let(:options) do
|
|
619
|
+
{
|
|
620
|
+
required: false,
|
|
621
|
+
optional: true
|
|
622
|
+
}
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
it 'does not set up the presence of validation' do
|
|
626
|
+
expect(belonging_class).not_to receive(:validates)
|
|
627
|
+
association.setup!
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
context 'when the optional option is false' do
|
|
632
|
+
|
|
633
|
+
let(:options) do
|
|
634
|
+
{
|
|
635
|
+
required: false,
|
|
636
|
+
optional: false
|
|
637
|
+
}
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
it 'does not set up the presence of validation' do
|
|
641
|
+
expect(belonging_class).not_to receive(:validates)
|
|
642
|
+
association.setup!
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
context 'when the required option is not provided' do
|
|
648
|
+
|
|
649
|
+
it 'uses the default and sets up the presence of validation' do
|
|
650
|
+
expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
|
|
651
|
+
association.setup!
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
context 'when the optional option is true' do
|
|
655
|
+
|
|
656
|
+
let(:options) do
|
|
657
|
+
{
|
|
658
|
+
optional: true
|
|
659
|
+
}
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
it 'does not set up the presence of validation' do
|
|
663
|
+
expect(belonging_class).not_to receive(:validates)
|
|
664
|
+
association.setup!
|
|
665
|
+
end
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
context 'when the optional option is false' do
|
|
669
|
+
|
|
670
|
+
let(:options) do
|
|
671
|
+
{
|
|
672
|
+
optional: false
|
|
673
|
+
}
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
it 'sets up the presence of validation' do
|
|
677
|
+
expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
|
|
678
|
+
association.setup!
|
|
679
|
+
end
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
context 'when the global config option is false' do
|
|
685
|
+
|
|
686
|
+
around(:example) do |example|
|
|
687
|
+
original_config = Mongoid.belongs_to_required_by_default
|
|
688
|
+
Mongoid.belongs_to_required_by_default = false
|
|
689
|
+
example.run
|
|
690
|
+
Mongoid.belongs_to_required_by_default = original_config
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
context 'when the required option is true' do
|
|
694
|
+
|
|
695
|
+
let(:options) do
|
|
696
|
+
{
|
|
697
|
+
required: true
|
|
698
|
+
}
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
it 'sets up the presence of validation' do
|
|
702
|
+
expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
|
|
703
|
+
association.setup!
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
context 'when the optional option is true' do
|
|
707
|
+
|
|
708
|
+
let(:options) do
|
|
709
|
+
{
|
|
710
|
+
required: true,
|
|
711
|
+
optional: true
|
|
712
|
+
}
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
it 'sets up the presence of validation' do
|
|
716
|
+
expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
|
|
717
|
+
association.setup!
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
context 'when the optional option is false' do
|
|
722
|
+
|
|
723
|
+
let(:options) do
|
|
724
|
+
{
|
|
725
|
+
required: true,
|
|
726
|
+
optional: false
|
|
727
|
+
}
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
it 'sets up the presence of validation' do
|
|
731
|
+
expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
|
|
732
|
+
association.setup!
|
|
733
|
+
end
|
|
734
|
+
end
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
context 'when the required option is false' do
|
|
738
|
+
|
|
739
|
+
let(:options) do
|
|
740
|
+
{
|
|
741
|
+
required: false
|
|
742
|
+
}
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
it 'does not set up the presence of validation' do
|
|
746
|
+
expect(belonging_class).not_to receive(:validates)
|
|
747
|
+
association.setup!
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
context 'when the optional option is true' do
|
|
751
|
+
|
|
752
|
+
let(:options) do
|
|
753
|
+
{
|
|
754
|
+
required: false,
|
|
755
|
+
optional: true
|
|
756
|
+
}
|
|
757
|
+
end
|
|
758
|
+
|
|
759
|
+
it 'does not set up the presence of validation' do
|
|
760
|
+
expect(belonging_class).not_to receive(:validates)
|
|
761
|
+
association.setup!
|
|
762
|
+
end
|
|
763
|
+
end
|
|
764
|
+
|
|
765
|
+
context 'when the optional option is false' do
|
|
766
|
+
|
|
767
|
+
let(:options) do
|
|
768
|
+
{
|
|
769
|
+
required: false,
|
|
770
|
+
optional: false
|
|
771
|
+
}
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
it 'does not set up the presence of validation' do
|
|
775
|
+
expect(belonging_class).not_to receive(:validates)
|
|
776
|
+
association.setup!
|
|
777
|
+
end
|
|
778
|
+
end
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
context 'when the required option is not provided' do
|
|
782
|
+
|
|
783
|
+
it 'uses the default and does not set up the presence of validation' do
|
|
784
|
+
expect(belonging_class).not_to receive(:validates)
|
|
785
|
+
association.setup!
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
context 'when the optional option is true' do
|
|
789
|
+
|
|
790
|
+
let(:options) do
|
|
791
|
+
{
|
|
792
|
+
optional: true
|
|
793
|
+
}
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
it 'does not set up the presence of validation' do
|
|
797
|
+
expect(belonging_class).not_to receive(:validates)
|
|
798
|
+
association.setup!
|
|
799
|
+
end
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
context 'when the optional option is false' do
|
|
803
|
+
|
|
804
|
+
let(:options) do
|
|
805
|
+
{
|
|
806
|
+
optional: false
|
|
807
|
+
}
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
it 'sets up the presence of validation' do
|
|
811
|
+
expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
|
|
812
|
+
association.setup!
|
|
813
|
+
end
|
|
814
|
+
end
|
|
815
|
+
end
|
|
816
|
+
end
|
|
817
|
+
end
|
|
818
|
+
end
|
|
819
|
+
|
|
820
|
+
describe '#type' do
|
|
821
|
+
|
|
822
|
+
context 'when polymorphic' do
|
|
823
|
+
|
|
824
|
+
let(:options) do
|
|
825
|
+
{ polymorphic: true }
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
it 'returns nil' do
|
|
829
|
+
expect(association.type).to be_nil
|
|
830
|
+
end
|
|
831
|
+
end
|
|
832
|
+
|
|
833
|
+
context 'when not polymorphic' do
|
|
834
|
+
|
|
835
|
+
it 'returns nil' do
|
|
836
|
+
expect(association.type).to be_nil
|
|
837
|
+
end
|
|
838
|
+
end
|
|
839
|
+
end
|
|
840
|
+
|
|
841
|
+
describe '#inverse_type' do
|
|
842
|
+
|
|
843
|
+
context 'when polymorphic' do
|
|
844
|
+
|
|
845
|
+
let(:options) do
|
|
846
|
+
{ polymorphic: true }
|
|
847
|
+
end
|
|
848
|
+
|
|
849
|
+
it 'returns the name followed by "_type"' do
|
|
850
|
+
expect(association.inverse_type).to eq("#{name}_type")
|
|
851
|
+
end
|
|
852
|
+
end
|
|
853
|
+
|
|
854
|
+
context 'when not polymorphic' do
|
|
855
|
+
|
|
856
|
+
it 'returns nil' do
|
|
857
|
+
expect(association.inverse_type).to be_nil
|
|
858
|
+
end
|
|
859
|
+
end
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
describe '#inverse_type_setter' do
|
|
863
|
+
|
|
864
|
+
context 'when polymorphic' do
|
|
865
|
+
|
|
866
|
+
let(:options) do
|
|
867
|
+
{ polymorphic: true }
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
it 'returns the inverse type setter' do
|
|
871
|
+
expect(association.inverse_type_setter).to eq("#{name}_type=")
|
|
872
|
+
end
|
|
873
|
+
end
|
|
874
|
+
|
|
875
|
+
context 'when not polymorphic' do
|
|
876
|
+
|
|
877
|
+
it 'returns nil' do
|
|
878
|
+
expect(association.inverse_type_setter).to be_nil
|
|
879
|
+
end
|
|
880
|
+
end
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
describe '#foreign_key' do
|
|
884
|
+
|
|
885
|
+
context 'when options has foreign_key specified' do
|
|
886
|
+
|
|
887
|
+
let(:options) do
|
|
888
|
+
{ foreign_key: :other_object_id }
|
|
889
|
+
end
|
|
890
|
+
|
|
891
|
+
it 'returns the foreign key' do
|
|
892
|
+
expect(association.foreign_key).to eq(options[:foreign_key].to_s)
|
|
893
|
+
end
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
context 'when options does not have foreign_key specified' do
|
|
897
|
+
|
|
898
|
+
it 'returns the ame followed by "_id"' do
|
|
899
|
+
expect(association.foreign_key).to eq("#{name}_id")
|
|
900
|
+
end
|
|
901
|
+
end
|
|
902
|
+
end
|
|
903
|
+
|
|
904
|
+
describe '#embedded?' do
|
|
905
|
+
|
|
906
|
+
it 'returns false' do
|
|
907
|
+
expect(association.embedded?).to be(false)
|
|
908
|
+
end
|
|
909
|
+
end
|
|
910
|
+
|
|
911
|
+
describe '#primary_key' do
|
|
912
|
+
|
|
913
|
+
context 'when the :primary_key option is specified' do
|
|
914
|
+
|
|
915
|
+
context 'when the :primary_key option is true' do
|
|
916
|
+
|
|
917
|
+
let(:options) do
|
|
918
|
+
{
|
|
919
|
+
primary_key: :other_primary_key
|
|
920
|
+
}
|
|
921
|
+
end
|
|
922
|
+
|
|
923
|
+
it 'returns the primary key option as a String' do
|
|
924
|
+
expect(association.primary_key).to eq('other_primary_key')
|
|
925
|
+
end
|
|
926
|
+
end
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
context 'when the :primary_key option is not specified' do
|
|
930
|
+
|
|
931
|
+
it 'returns the default primary key' do
|
|
932
|
+
expect(association.primary_key).to eq(Mongoid::Association::Relatable::PRIMARY_KEY_DEFAULT)
|
|
933
|
+
end
|
|
934
|
+
end
|
|
935
|
+
end
|
|
936
|
+
|
|
937
|
+
describe '#indexed?' do
|
|
938
|
+
|
|
939
|
+
context 'when :index is specified in the options' do
|
|
940
|
+
|
|
941
|
+
context 'when :index is true' do
|
|
942
|
+
|
|
943
|
+
let(:options) do
|
|
944
|
+
{
|
|
945
|
+
index: true
|
|
946
|
+
}
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
it 'returns true' do
|
|
950
|
+
expect(association.indexed?).to be(true)
|
|
951
|
+
end
|
|
952
|
+
end
|
|
953
|
+
|
|
954
|
+
context 'when :index is false' do
|
|
955
|
+
|
|
956
|
+
let(:options) do
|
|
957
|
+
{
|
|
958
|
+
index: false
|
|
959
|
+
}
|
|
960
|
+
end
|
|
961
|
+
|
|
962
|
+
it 'returns false' do
|
|
963
|
+
expect(association.indexed?).to be(false)
|
|
964
|
+
end
|
|
965
|
+
end
|
|
966
|
+
end
|
|
967
|
+
|
|
968
|
+
context 'when :index is not specified in the options' do
|
|
969
|
+
|
|
970
|
+
it 'returns nil' do
|
|
971
|
+
expect(association.indexed?).to be(false)
|
|
972
|
+
end
|
|
973
|
+
end
|
|
974
|
+
end
|
|
975
|
+
|
|
976
|
+
describe '#relation' do
|
|
977
|
+
|
|
978
|
+
it 'returns Mongoid::Association::Referenced::BelongsTo::Proxy' do
|
|
979
|
+
expect(association.relation).to be(Mongoid::Association::Referenced::BelongsTo::Proxy)
|
|
980
|
+
end
|
|
981
|
+
end
|
|
982
|
+
|
|
983
|
+
describe '#validation_default' do
|
|
984
|
+
|
|
985
|
+
it 'returns false' do
|
|
986
|
+
expect(association.validation_default).to be(false)
|
|
987
|
+
end
|
|
988
|
+
end
|
|
989
|
+
|
|
990
|
+
describe '#name' do
|
|
991
|
+
|
|
992
|
+
it 'returns the name of the relation' do
|
|
993
|
+
expect(association.name).to be(name)
|
|
994
|
+
end
|
|
995
|
+
end
|
|
996
|
+
|
|
997
|
+
describe '#options' do
|
|
998
|
+
|
|
999
|
+
it 'returns the options' do
|
|
1000
|
+
expect(association.options).to be(options)
|
|
1001
|
+
end
|
|
1002
|
+
end
|
|
1003
|
+
|
|
1004
|
+
describe '#cyclic?' do
|
|
1005
|
+
|
|
1006
|
+
it 'returns false' do
|
|
1007
|
+
expect(association.cyclic?).to be(false)
|
|
1008
|
+
end
|
|
1009
|
+
end
|
|
1010
|
+
|
|
1011
|
+
describe '#merge!' do
|
|
1012
|
+
|
|
1013
|
+
end
|
|
1014
|
+
|
|
1015
|
+
describe '#store_as' do
|
|
1016
|
+
|
|
1017
|
+
it 'returns nil' do
|
|
1018
|
+
expect(association.store_as).to be_nil
|
|
1019
|
+
end
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
describe '#touchable?' do
|
|
1023
|
+
|
|
1024
|
+
context 'when :touch is in the options' do
|
|
1025
|
+
|
|
1026
|
+
let(:options) do
|
|
1027
|
+
{ touch: true}
|
|
1028
|
+
end
|
|
1029
|
+
|
|
1030
|
+
it 'returns true' do
|
|
1031
|
+
expect(association.send(:touchable?)).to be(true)
|
|
1032
|
+
end
|
|
1033
|
+
end
|
|
1034
|
+
|
|
1035
|
+
context 'when :touch is not in the options' do
|
|
1036
|
+
|
|
1037
|
+
it 'return false' do
|
|
1038
|
+
expect(association.send(:touchable?)).to be(false)
|
|
1039
|
+
end
|
|
1040
|
+
end
|
|
1041
|
+
end
|
|
1042
|
+
|
|
1043
|
+
describe '#order' do
|
|
1044
|
+
|
|
1045
|
+
it 'returns nil' do
|
|
1046
|
+
expect(association.order).to be_nil
|
|
1047
|
+
end
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
describe '#as' do
|
|
1051
|
+
|
|
1052
|
+
it 'returns nil' do
|
|
1053
|
+
expect(association.as).to be_nil
|
|
1054
|
+
end
|
|
1055
|
+
end
|
|
1056
|
+
|
|
1057
|
+
describe '#polymorphic?' do
|
|
1058
|
+
|
|
1059
|
+
context 'when :polymorphic is specified in the options as true' do
|
|
1060
|
+
|
|
1061
|
+
let(:options) do
|
|
1062
|
+
{ polymorphic: true }
|
|
1063
|
+
end
|
|
1064
|
+
|
|
1065
|
+
it 'returns true' do
|
|
1066
|
+
expect(association.polymorphic?).to be(true)
|
|
1067
|
+
end
|
|
1068
|
+
end
|
|
1069
|
+
|
|
1070
|
+
context 'when :polymorphic is specified in the options as false' do
|
|
1071
|
+
|
|
1072
|
+
let(:options) do
|
|
1073
|
+
{ polymorphic: false }
|
|
1074
|
+
end
|
|
1075
|
+
|
|
1076
|
+
it 'returns false' do
|
|
1077
|
+
expect(association.polymorphic?).to be(false)
|
|
1078
|
+
end
|
|
1079
|
+
end
|
|
1080
|
+
|
|
1081
|
+
context 'when :polymorphic is not specified in the options' do
|
|
1082
|
+
|
|
1083
|
+
it 'returns false' do
|
|
1084
|
+
expect(association.polymorphic?).to be(false)
|
|
1085
|
+
end
|
|
1086
|
+
end
|
|
1087
|
+
end
|
|
1088
|
+
|
|
1089
|
+
describe '#dependent' do
|
|
1090
|
+
|
|
1091
|
+
context 'when the dependent option is provided' do
|
|
1092
|
+
|
|
1093
|
+
context 'when the dependent option is :delete_all' do
|
|
1094
|
+
|
|
1095
|
+
let(:options) do
|
|
1096
|
+
{
|
|
1097
|
+
dependent: :delete_all
|
|
1098
|
+
}
|
|
1099
|
+
end
|
|
1100
|
+
|
|
1101
|
+
it 'returns :delete_all' do
|
|
1102
|
+
expect(association.dependent).to eq(:delete_all)
|
|
1103
|
+
end
|
|
1104
|
+
end
|
|
1105
|
+
|
|
1106
|
+
context 'when the dependent option is :destroy' do
|
|
1107
|
+
|
|
1108
|
+
let(:options) do
|
|
1109
|
+
{
|
|
1110
|
+
dependent: :destroy
|
|
1111
|
+
}
|
|
1112
|
+
end
|
|
1113
|
+
|
|
1114
|
+
it 'returns :destroy' do
|
|
1115
|
+
expect(association.dependent).to eq(:destroy)
|
|
1116
|
+
end
|
|
1117
|
+
end
|
|
1118
|
+
|
|
1119
|
+
context 'when the dependent option is :nullify' do
|
|
1120
|
+
|
|
1121
|
+
let(:options) do
|
|
1122
|
+
{
|
|
1123
|
+
dependent: :nullify
|
|
1124
|
+
}
|
|
1125
|
+
end
|
|
1126
|
+
|
|
1127
|
+
it 'returns :nullify' do
|
|
1128
|
+
expect(association.dependent).to eq(:nullify)
|
|
1129
|
+
end
|
|
1130
|
+
end
|
|
1131
|
+
|
|
1132
|
+
context 'when the dependent option is :restrict_with_exception' do
|
|
1133
|
+
|
|
1134
|
+
let(:options) do
|
|
1135
|
+
{
|
|
1136
|
+
dependent: :restrict_with_exception
|
|
1137
|
+
}
|
|
1138
|
+
end
|
|
1139
|
+
|
|
1140
|
+
it 'returns :restrict_with_exception' do
|
|
1141
|
+
expect(association.dependent).to eq(:restrict_with_exception)
|
|
1142
|
+
end
|
|
1143
|
+
end
|
|
1144
|
+
|
|
1145
|
+
context 'when the dependent option is :restrict_with_error' do
|
|
1146
|
+
|
|
1147
|
+
let(:options) do
|
|
1148
|
+
{
|
|
1149
|
+
dependent: :restrict_with_error
|
|
1150
|
+
}
|
|
1151
|
+
end
|
|
1152
|
+
|
|
1153
|
+
it 'returns :restrict_with_error' do
|
|
1154
|
+
expect(association.dependent).to eq(:restrict_with_error)
|
|
1155
|
+
end
|
|
1156
|
+
end
|
|
1157
|
+
end
|
|
1158
|
+
|
|
1159
|
+
context 'when the dependent option is not provided' do
|
|
1160
|
+
|
|
1161
|
+
it 'returns nil' do
|
|
1162
|
+
expect(association.dependent).to be_nil
|
|
1163
|
+
end
|
|
1164
|
+
end
|
|
1165
|
+
end
|
|
1166
|
+
|
|
1167
|
+
describe '#bindable?' do
|
|
1168
|
+
|
|
1169
|
+
it 'returns false' do
|
|
1170
|
+
expect(association.bindable?(Person.new)).to be(false)
|
|
1171
|
+
end
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
describe '#inverses' do
|
|
1175
|
+
|
|
1176
|
+
context 'when polymorphic' do
|
|
1177
|
+
|
|
1178
|
+
let(:options) do
|
|
1179
|
+
{
|
|
1180
|
+
polymorphic: true
|
|
1181
|
+
}
|
|
1182
|
+
end
|
|
1183
|
+
|
|
1184
|
+
let(:name) do
|
|
1185
|
+
:containable
|
|
1186
|
+
end
|
|
1187
|
+
|
|
1188
|
+
context 'when another object is passed to the method' do
|
|
1189
|
+
|
|
1190
|
+
let(:instance_of_other_class) do
|
|
1191
|
+
OwnerObject.new
|
|
1192
|
+
end
|
|
1193
|
+
|
|
1194
|
+
context 'when the relation class has only one relation whose class matches the owning class' do
|
|
1195
|
+
|
|
1196
|
+
before do
|
|
1197
|
+
OwnerObject.has_one :belonging_object, as: :containable
|
|
1198
|
+
end
|
|
1199
|
+
|
|
1200
|
+
context 'when :inverse_of is specified' do
|
|
1201
|
+
|
|
1202
|
+
before do
|
|
1203
|
+
options.merge!(inverse_of: :inverse_name)
|
|
1204
|
+
end
|
|
1205
|
+
|
|
1206
|
+
it 'returns the :inverse_of value' do
|
|
1207
|
+
expect(association.inverses(instance_of_other_class)).to eq([ :inverse_name ])
|
|
1208
|
+
end
|
|
1209
|
+
end
|
|
1210
|
+
|
|
1211
|
+
context 'when inverse_of is not specified' do
|
|
1212
|
+
|
|
1213
|
+
it 'returns the list of relations whose :as attribute matches the name of this association' do
|
|
1214
|
+
expect(association.inverses(instance_of_other_class)).to match_array([ :belonging_object ])
|
|
1215
|
+
end
|
|
1216
|
+
end
|
|
1217
|
+
end
|
|
1218
|
+
|
|
1219
|
+
context 'when the relation class has more than one relation whose class matches the owning class' do
|
|
1220
|
+
|
|
1221
|
+
before do
|
|
1222
|
+
OwnerObject.has_one :other_belonging_object, as: :containable, class_name: 'BelongingObject'
|
|
1223
|
+
OwnerObject.has_one :belonging_object, as: :containable
|
|
1224
|
+
end
|
|
1225
|
+
|
|
1226
|
+
context 'when :inverse_of is specified' do
|
|
1227
|
+
|
|
1228
|
+
before do
|
|
1229
|
+
options.merge!(inverse_of: :inverse_name)
|
|
1230
|
+
end
|
|
1231
|
+
|
|
1232
|
+
it 'returns the :inverse_of value' do
|
|
1233
|
+
expect(association.inverses(instance_of_other_class)).to eq([ :inverse_name ])
|
|
1234
|
+
end
|
|
1235
|
+
end
|
|
1236
|
+
|
|
1237
|
+
context 'when inverse_of is not specified' do
|
|
1238
|
+
|
|
1239
|
+
it 'returns the list of relations whose :as attribute matches the name of this association' do
|
|
1240
|
+
expect(association.inverses(instance_of_other_class)).to match_array([ :other_belonging_object,
|
|
1241
|
+
:belonging_object ])
|
|
1242
|
+
end
|
|
1243
|
+
|
|
1244
|
+
context 'when the relation class has two associations with the same name' do
|
|
1245
|
+
|
|
1246
|
+
before do
|
|
1247
|
+
OwnerObject.has_one :belonging_object, as: :containable
|
|
1248
|
+
OwnerObject.has_one :other_belonging_object, as: :containable
|
|
1249
|
+
end
|
|
1250
|
+
|
|
1251
|
+
it 'returns only the relations whose :as attribute and class match' do
|
|
1252
|
+
expect(association.inverses(instance_of_other_class)).to match_array([ :belonging_object ])
|
|
1253
|
+
end
|
|
1254
|
+
end
|
|
1255
|
+
end
|
|
1256
|
+
end
|
|
1257
|
+
end
|
|
1258
|
+
|
|
1259
|
+
context 'when another object is not passed to the method' do
|
|
1260
|
+
|
|
1261
|
+
context 'when inverse_of is specified' do
|
|
1262
|
+
|
|
1263
|
+
before do
|
|
1264
|
+
options.merge!(inverse_of: :inverse_name)
|
|
1265
|
+
end
|
|
1266
|
+
|
|
1267
|
+
it 'returns the :inverse_of value' do
|
|
1268
|
+
expect(association.inverses).to eq([ :inverse_name ])
|
|
1269
|
+
end
|
|
1270
|
+
end
|
|
1271
|
+
|
|
1272
|
+
context 'when inverse_of is not specified' do
|
|
1273
|
+
|
|
1274
|
+
it 'returns nil' do
|
|
1275
|
+
expect(association.inverses).to eq(nil)
|
|
1276
|
+
end
|
|
1277
|
+
end
|
|
1278
|
+
end
|
|
1279
|
+
end
|
|
1280
|
+
|
|
1281
|
+
context 'when not polymorphic' do
|
|
1282
|
+
|
|
1283
|
+
context 'when inverse_of is specified' do
|
|
1284
|
+
|
|
1285
|
+
before do
|
|
1286
|
+
options.merge!(inverse_of: :inverse_name)
|
|
1287
|
+
end
|
|
1288
|
+
|
|
1289
|
+
it 'returns the :inverse_of value' do
|
|
1290
|
+
expect(association.inverses).to eq([ :inverse_name ])
|
|
1291
|
+
end
|
|
1292
|
+
end
|
|
1293
|
+
|
|
1294
|
+
context 'when inverse_of is not specified' do
|
|
1295
|
+
|
|
1296
|
+
before do
|
|
1297
|
+
OwnerObject.has_many :belonging_objects
|
|
1298
|
+
end
|
|
1299
|
+
|
|
1300
|
+
it 'uses the inverse class to find the inverse name' do
|
|
1301
|
+
expect(association.inverses).to eq([ :belonging_objects ])
|
|
1302
|
+
end
|
|
1303
|
+
end
|
|
1304
|
+
|
|
1305
|
+
context 'when :cyclic is specified' do
|
|
1306
|
+
|
|
1307
|
+
it 'returns the cyclic inverse name' do
|
|
1308
|
+
|
|
1309
|
+
end
|
|
1310
|
+
end
|
|
1311
|
+
|
|
1312
|
+
context 'when the inverse class has more than one relation with objects of the owner class' do
|
|
1313
|
+
|
|
1314
|
+
before do
|
|
1315
|
+
OwnerObject.has_many :belonging_objects
|
|
1316
|
+
OwnerObject.has_one :other_belonging_object, class_name: 'BelongingObject'
|
|
1317
|
+
end
|
|
1318
|
+
|
|
1319
|
+
it 'raises a Mongoid::Errors::AmbiguousRelationship exception' do
|
|
1320
|
+
expect {
|
|
1321
|
+
association.inverses
|
|
1322
|
+
}.to raise_exception(Mongoid::Errors::AmbiguousRelationship)
|
|
1323
|
+
end
|
|
1324
|
+
end
|
|
1325
|
+
|
|
1326
|
+
context 'when the inverse class only has one relation with objects of the owner class' do
|
|
1327
|
+
|
|
1328
|
+
before do
|
|
1329
|
+
OwnerObject.has_many :belonging_objects
|
|
1330
|
+
end
|
|
1331
|
+
|
|
1332
|
+
it 'uses the inverse class to find the inverse name' do
|
|
1333
|
+
expect(association.inverses).to eq([ :belonging_objects ])
|
|
1334
|
+
end
|
|
1335
|
+
end
|
|
1336
|
+
end
|
|
1337
|
+
end
|
|
1338
|
+
|
|
1339
|
+
describe '#inverse' do
|
|
1340
|
+
|
|
1341
|
+
context 'when polymorphic' do
|
|
1342
|
+
|
|
1343
|
+
let(:options) do
|
|
1344
|
+
{
|
|
1345
|
+
polymorphic: true
|
|
1346
|
+
}
|
|
1347
|
+
end
|
|
1348
|
+
|
|
1349
|
+
let(:name) do
|
|
1350
|
+
:containable
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1353
|
+
context 'when another object is passed to the method' do
|
|
1354
|
+
|
|
1355
|
+
let(:instance_of_other_class) do
|
|
1356
|
+
OwnerObject.new
|
|
1357
|
+
end
|
|
1358
|
+
|
|
1359
|
+
context 'when the relation class has only one relation whose class matches the owning class' do
|
|
1360
|
+
|
|
1361
|
+
before do
|
|
1362
|
+
OwnerObject.has_many :belonging_objects, as: :containable
|
|
1363
|
+
end
|
|
1364
|
+
|
|
1365
|
+
context 'when :inverse_of is specified' do
|
|
1366
|
+
|
|
1367
|
+
before do
|
|
1368
|
+
options.merge!(inverse_of: :inverse_name)
|
|
1369
|
+
end
|
|
1370
|
+
|
|
1371
|
+
it 'returns the :inverse_of value' do
|
|
1372
|
+
expect(association.inverse(instance_of_other_class)).to eq(:inverse_name)
|
|
1373
|
+
end
|
|
1374
|
+
end
|
|
1375
|
+
|
|
1376
|
+
context 'when inverse_of is not specified' do
|
|
1377
|
+
|
|
1378
|
+
it 'returns the list of relations whose :as attribute matches the name of this association' do
|
|
1379
|
+
expect(association.inverse(instance_of_other_class)).to eq(:belonging_objects)
|
|
1380
|
+
end
|
|
1381
|
+
end
|
|
1382
|
+
end
|
|
1383
|
+
|
|
1384
|
+
context 'when the relation class has more than one relation whose class matches the owning class' do
|
|
1385
|
+
|
|
1386
|
+
before do
|
|
1387
|
+
OwnerObject.has_one :other_belonging_object, as: :containable, class_name: 'BelongingObject'
|
|
1388
|
+
OwnerObject.has_one :belonging_object, as: :containable
|
|
1389
|
+
end
|
|
1390
|
+
|
|
1391
|
+
context 'when :inverse_of is specified' do
|
|
1392
|
+
|
|
1393
|
+
before do
|
|
1394
|
+
options.merge!(inverse_of: :inverse_name)
|
|
1395
|
+
end
|
|
1396
|
+
|
|
1397
|
+
it 'returns the :inverse_of value' do
|
|
1398
|
+
expect(association.inverse(instance_of_other_class)).to eq(:inverse_name)
|
|
1399
|
+
end
|
|
1400
|
+
end
|
|
1401
|
+
|
|
1402
|
+
context 'when inverse_of is not specified' do
|
|
1403
|
+
|
|
1404
|
+
it 'returns the first candidate whose :as attribute matches the name of this association' do
|
|
1405
|
+
expect(association.inverse(instance_of_other_class)).to eq(:other_belonging_object)
|
|
1406
|
+
end
|
|
1407
|
+
end
|
|
1408
|
+
end
|
|
1409
|
+
end
|
|
1410
|
+
|
|
1411
|
+
context 'when another object is not passed to the method' do
|
|
1412
|
+
|
|
1413
|
+
context 'when inverse_of is specified' do
|
|
1414
|
+
|
|
1415
|
+
before do
|
|
1416
|
+
options.merge!(inverse_of: :inverse_name)
|
|
1417
|
+
end
|
|
1418
|
+
|
|
1419
|
+
it 'returns the :inverse_of value' do
|
|
1420
|
+
expect(association.inverse).to eq(:inverse_name)
|
|
1421
|
+
end
|
|
1422
|
+
end
|
|
1423
|
+
|
|
1424
|
+
context 'when inverse_of is not specified' do
|
|
1425
|
+
|
|
1426
|
+
it 'returns nil' do
|
|
1427
|
+
expect(association.inverse).to eq(nil)
|
|
1428
|
+
end
|
|
1429
|
+
end
|
|
1430
|
+
end
|
|
1431
|
+
end
|
|
1432
|
+
|
|
1433
|
+
context 'when not polymorphic' do
|
|
1434
|
+
|
|
1435
|
+
context 'when inverse_of is specified' do
|
|
1436
|
+
|
|
1437
|
+
before do
|
|
1438
|
+
options.merge!(inverse_of: :inverse_name)
|
|
1439
|
+
end
|
|
1440
|
+
|
|
1441
|
+
it 'returns the :inverse_of value' do
|
|
1442
|
+
expect(association.inverse).to eq(:inverse_name)
|
|
1443
|
+
end
|
|
1444
|
+
end
|
|
1445
|
+
|
|
1446
|
+
context 'when inverse_of is not specified' do
|
|
1447
|
+
|
|
1448
|
+
before do
|
|
1449
|
+
OwnerObject.has_many :belonging_objects
|
|
1450
|
+
end
|
|
1451
|
+
|
|
1452
|
+
it 'uses the inverse class to find the inverse name' do
|
|
1453
|
+
expect(association.inverse).to eq(:belonging_objects)
|
|
1454
|
+
end
|
|
1455
|
+
end
|
|
1456
|
+
|
|
1457
|
+
context 'when :cyclic is specified' do
|
|
1458
|
+
|
|
1459
|
+
it 'returns the cyclic inverse name' do
|
|
1460
|
+
|
|
1461
|
+
end
|
|
1462
|
+
end
|
|
1463
|
+
|
|
1464
|
+
context 'when the inverse class has more than one relation with objects of the owner class' do
|
|
1465
|
+
|
|
1466
|
+
before do
|
|
1467
|
+
OwnerObject.has_many :belonging_objects
|
|
1468
|
+
OwnerObject.has_many :other_belonging_objects, class_name: 'BelongingObject'
|
|
1469
|
+
end
|
|
1470
|
+
|
|
1471
|
+
it 'raises a Mongoid::Errors::AmbiguousRelationship exception' do
|
|
1472
|
+
expect {
|
|
1473
|
+
association.inverse
|
|
1474
|
+
}.to raise_exception(Mongoid::Errors::AmbiguousRelationship)
|
|
1475
|
+
end
|
|
1476
|
+
end
|
|
1477
|
+
|
|
1478
|
+
context 'when the inverse class only has one relation with objects of the owner class' do
|
|
1479
|
+
|
|
1480
|
+
before do
|
|
1481
|
+
OwnerObject.has_many :belonging_objects
|
|
1482
|
+
end
|
|
1483
|
+
|
|
1484
|
+
it 'uses the inverse class to find the inverse name' do
|
|
1485
|
+
expect(association.inverse).to eq(:belonging_objects)
|
|
1486
|
+
end
|
|
1487
|
+
end
|
|
1488
|
+
end
|
|
1489
|
+
end
|
|
1490
|
+
|
|
1491
|
+
describe '#inverse_association' do
|
|
1492
|
+
|
|
1493
|
+
end
|
|
1494
|
+
|
|
1495
|
+
describe '#autosave' do
|
|
1496
|
+
|
|
1497
|
+
context 'when the :autosave option is specified' do
|
|
1498
|
+
|
|
1499
|
+
context 'when the :autosave option is true' do
|
|
1500
|
+
|
|
1501
|
+
let(:options) do
|
|
1502
|
+
{
|
|
1503
|
+
autosave: true
|
|
1504
|
+
}
|
|
1505
|
+
end
|
|
1506
|
+
|
|
1507
|
+
it 'returns true' do
|
|
1508
|
+
expect(association.autosave).to be(true)
|
|
1509
|
+
end
|
|
1510
|
+
end
|
|
1511
|
+
|
|
1512
|
+
context 'when the :autosave option is false' do
|
|
1513
|
+
|
|
1514
|
+
let(:options) do
|
|
1515
|
+
{
|
|
1516
|
+
autosave: false
|
|
1517
|
+
}
|
|
1518
|
+
end
|
|
1519
|
+
|
|
1520
|
+
it 'returns false' do
|
|
1521
|
+
expect(association.autosave).to be(false)
|
|
1522
|
+
end
|
|
1523
|
+
end
|
|
1524
|
+
end
|
|
1525
|
+
|
|
1526
|
+
context 'when the :autosave option is not specified' do
|
|
1527
|
+
|
|
1528
|
+
it 'returns nil' do
|
|
1529
|
+
expect(association.autosave).to be(false)
|
|
1530
|
+
end
|
|
1531
|
+
end
|
|
1532
|
+
end
|
|
1533
|
+
|
|
1534
|
+
describe '#counter_cached?' do
|
|
1535
|
+
|
|
1536
|
+
context 'when the :counter_cache option is true' do
|
|
1537
|
+
|
|
1538
|
+
let(:options) do
|
|
1539
|
+
{
|
|
1540
|
+
counter_cache: true
|
|
1541
|
+
}
|
|
1542
|
+
end
|
|
1543
|
+
|
|
1544
|
+
it 'returns true' do
|
|
1545
|
+
expect(association.counter_cached?).to be(true)
|
|
1546
|
+
end
|
|
1547
|
+
end
|
|
1548
|
+
|
|
1549
|
+
context 'when the :counter_cache option is a String' do
|
|
1550
|
+
|
|
1551
|
+
let(:options) do
|
|
1552
|
+
{
|
|
1553
|
+
counter_cache: 'counts_field'
|
|
1554
|
+
}
|
|
1555
|
+
end
|
|
1556
|
+
|
|
1557
|
+
it 'returns true' do
|
|
1558
|
+
expect(association.counter_cached?).to be(true)
|
|
1559
|
+
end
|
|
1560
|
+
end
|
|
1561
|
+
|
|
1562
|
+
context 'when the :counter_cache option is false' do
|
|
1563
|
+
|
|
1564
|
+
let(:options) do
|
|
1565
|
+
{
|
|
1566
|
+
counter_cache: false
|
|
1567
|
+
}
|
|
1568
|
+
end
|
|
1569
|
+
|
|
1570
|
+
it 'returns false' do
|
|
1571
|
+
expect(association.counter_cached?).to be(false)
|
|
1572
|
+
end
|
|
1573
|
+
end
|
|
1574
|
+
|
|
1575
|
+
context 'when the :counter_cache option is not provided' do
|
|
1576
|
+
|
|
1577
|
+
it 'returns false' do
|
|
1578
|
+
expect(association.counter_cached?).to be(false)
|
|
1579
|
+
end
|
|
1580
|
+
end
|
|
1581
|
+
end
|
|
1582
|
+
|
|
1583
|
+
describe '#counter_cache_column_name' do
|
|
1584
|
+
|
|
1585
|
+
context 'when the :counter_cache option is true' do
|
|
1586
|
+
|
|
1587
|
+
let(:options) do
|
|
1588
|
+
{
|
|
1589
|
+
counter_cache: true
|
|
1590
|
+
}
|
|
1591
|
+
end
|
|
1592
|
+
|
|
1593
|
+
it 'returns the inverse name followed by "_count"' do
|
|
1594
|
+
expect(association.counter_cache_column_name).to eq('belonging_objects_count')
|
|
1595
|
+
end
|
|
1596
|
+
end
|
|
1597
|
+
|
|
1598
|
+
context 'when the :counter_cache option is a String' do
|
|
1599
|
+
|
|
1600
|
+
let(:options) do
|
|
1601
|
+
{
|
|
1602
|
+
counter_cache: 'counts_field'
|
|
1603
|
+
}
|
|
1604
|
+
end
|
|
1605
|
+
|
|
1606
|
+
it 'returns the String' do
|
|
1607
|
+
expect(association.counter_cache_column_name).to eq('counts_field')
|
|
1608
|
+
end
|
|
1609
|
+
end
|
|
1610
|
+
end
|
|
1611
|
+
|
|
1612
|
+
describe '#relation_class_name' do
|
|
1613
|
+
|
|
1614
|
+
context 'when the :class_name option is specified' do
|
|
1615
|
+
|
|
1616
|
+
let(:options) do
|
|
1617
|
+
{ class_name: 'OtherOwnerObject' }
|
|
1618
|
+
end
|
|
1619
|
+
|
|
1620
|
+
it 'returns the class name option' do
|
|
1621
|
+
expect(association.relation_class_name).to eq('OtherOwnerObject')
|
|
1622
|
+
end
|
|
1623
|
+
end
|
|
1624
|
+
|
|
1625
|
+
context 'when the class_name option is not specified' do
|
|
1626
|
+
|
|
1627
|
+
it 'uses the name of the relation to deduce the class name' do
|
|
1628
|
+
expect(association.relation_class_name).to eq('OwnerObject')
|
|
1629
|
+
end
|
|
1630
|
+
end
|
|
1631
|
+
|
|
1632
|
+
context 'when the association is polymorphic' do
|
|
1633
|
+
let(:association) do
|
|
1634
|
+
HomPolymorphicChild.relations['p_parent']
|
|
1635
|
+
end
|
|
1636
|
+
|
|
1637
|
+
it 'is the computed class name that does not match any existing class' do
|
|
1638
|
+
expect(association.relation_class_name).to eq('PParent')
|
|
1639
|
+
end
|
|
1640
|
+
end
|
|
1641
|
+
end
|
|
1642
|
+
|
|
1643
|
+
describe '#relation_class' do
|
|
1644
|
+
|
|
1645
|
+
context 'when the :class_name option is specified' do
|
|
1646
|
+
|
|
1647
|
+
let!(:_class) do
|
|
1648
|
+
class OtherOwnerObject; end
|
|
1649
|
+
OtherOwnerObject
|
|
1650
|
+
end
|
|
1651
|
+
|
|
1652
|
+
let(:options) do
|
|
1653
|
+
{ class_name: 'OtherOwnerObject' }
|
|
1654
|
+
end
|
|
1655
|
+
|
|
1656
|
+
it 'returns the class name option' do
|
|
1657
|
+
expect(association.relation_class).to eq(_class)
|
|
1658
|
+
end
|
|
1659
|
+
end
|
|
1660
|
+
|
|
1661
|
+
context 'when the class_name option is not specified' do
|
|
1662
|
+
|
|
1663
|
+
it 'uses the name of the relation to deduce the class name' do
|
|
1664
|
+
expect(association.relation_class).to eq(OwnerObject)
|
|
1665
|
+
end
|
|
1666
|
+
end
|
|
1667
|
+
|
|
1668
|
+
context 'when the association is polymorphic' do
|
|
1669
|
+
let(:association) do
|
|
1670
|
+
HomPolymorphicChild.relations['p_parent']
|
|
1671
|
+
end
|
|
1672
|
+
|
|
1673
|
+
it 'raises NameError' do
|
|
1674
|
+
expect do
|
|
1675
|
+
association.relation_class
|
|
1676
|
+
end.to raise_error(NameError, /uninitialized constant .*PParent/)
|
|
1677
|
+
end
|
|
1678
|
+
end
|
|
1679
|
+
end
|
|
1680
|
+
|
|
1681
|
+
describe '#inverse_class_name' do
|
|
1682
|
+
|
|
1683
|
+
it 'returns the name of the owner class' do
|
|
1684
|
+
expect(association.inverse_class_name).to eq(belonging_class.name)
|
|
1685
|
+
end
|
|
1686
|
+
|
|
1687
|
+
context 'polymorphic association' do
|
|
1688
|
+
let(:association) do
|
|
1689
|
+
belonging_class.belongs_to :poly_owner, polymorphic: true
|
|
1690
|
+
end
|
|
1691
|
+
|
|
1692
|
+
it 'returns the name of the owner class' do
|
|
1693
|
+
expect(association.inverse_class_name).to eq(belonging_class.name)
|
|
1694
|
+
end
|
|
1695
|
+
end
|
|
1696
|
+
end
|
|
1697
|
+
|
|
1698
|
+
describe '#inverse_class' do
|
|
1699
|
+
|
|
1700
|
+
it 'returns the owner class' do
|
|
1701
|
+
expect(association.inverse_class).to be(belonging_class)
|
|
1702
|
+
end
|
|
1703
|
+
|
|
1704
|
+
context 'polymorphic association' do
|
|
1705
|
+
let(:association) do
|
|
1706
|
+
belonging_class.belongs_to :poly_owner, polymorphic: true
|
|
1707
|
+
end
|
|
1708
|
+
|
|
1709
|
+
it 'returns the owner class' do
|
|
1710
|
+
expect(association.inverse_class).to be(belonging_class)
|
|
1711
|
+
end
|
|
1712
|
+
end
|
|
1713
|
+
end
|
|
1714
|
+
|
|
1715
|
+
describe '#inverse_of' do
|
|
1716
|
+
|
|
1717
|
+
context 'when :inverse_of is specified in the options' do
|
|
1718
|
+
|
|
1719
|
+
let(:options) do
|
|
1720
|
+
{ inverse_of: :a_belonging_object }
|
|
1721
|
+
end
|
|
1722
|
+
|
|
1723
|
+
it 'returns the inverse_of value' do
|
|
1724
|
+
expect(association.inverse_of).to eq(options[:inverse_of])
|
|
1725
|
+
end
|
|
1726
|
+
end
|
|
1727
|
+
|
|
1728
|
+
context 'when :inverse_of is not specified in the options' do
|
|
1729
|
+
|
|
1730
|
+
it 'returns nil' do
|
|
1731
|
+
expect(association.inverse_of).to be_nil
|
|
1732
|
+
end
|
|
1733
|
+
end
|
|
1734
|
+
end
|
|
1735
|
+
|
|
1736
|
+
describe '#key' do
|
|
1737
|
+
|
|
1738
|
+
it 'returns the name of the foreign_key as a string' do
|
|
1739
|
+
expect(association.key).to eq(association.foreign_key.to_s)
|
|
1740
|
+
end
|
|
1741
|
+
end
|
|
1742
|
+
|
|
1743
|
+
describe '#setter' do
|
|
1744
|
+
|
|
1745
|
+
it 'returns a string of the name followed by =' do
|
|
1746
|
+
expect(association.setter).to eq("#{name}=")
|
|
1747
|
+
end
|
|
1748
|
+
end
|
|
1749
|
+
|
|
1750
|
+
describe '#validate?' do
|
|
1751
|
+
|
|
1752
|
+
context 'when :validate is specified in the options' do
|
|
1753
|
+
|
|
1754
|
+
context 'when validate is true' do
|
|
1755
|
+
|
|
1756
|
+
let(:options) do
|
|
1757
|
+
{ validate: true }
|
|
1758
|
+
end
|
|
1759
|
+
|
|
1760
|
+
it 'returns true' do
|
|
1761
|
+
expect(association.send(:validate?)).to be(true)
|
|
1762
|
+
end
|
|
1763
|
+
end
|
|
1764
|
+
|
|
1765
|
+
context 'when validate is false' do
|
|
1766
|
+
|
|
1767
|
+
let(:options) do
|
|
1768
|
+
{ validate: false }
|
|
1769
|
+
end
|
|
1770
|
+
|
|
1771
|
+
it 'returns false' do
|
|
1772
|
+
expect(association.send(:validate?)).to be(false)
|
|
1773
|
+
end
|
|
1774
|
+
end
|
|
1775
|
+
end
|
|
1776
|
+
|
|
1777
|
+
context 'when :validate is not specified in the options' do
|
|
1778
|
+
|
|
1779
|
+
it 'returns the validation_default' do
|
|
1780
|
+
expect(association.send(:validate?)).to eq(association.validation_default)
|
|
1781
|
+
end
|
|
1782
|
+
end
|
|
1783
|
+
end
|
|
1784
|
+
|
|
1785
|
+
describe '#autobuilding?' do
|
|
1786
|
+
|
|
1787
|
+
context 'when :autobuild is specified in the options' do
|
|
1788
|
+
|
|
1789
|
+
context 'when autobuild is true' do
|
|
1790
|
+
|
|
1791
|
+
let(:options) do
|
|
1792
|
+
{ autobuild: true }
|
|
1793
|
+
end
|
|
1794
|
+
|
|
1795
|
+
it 'returns true' do
|
|
1796
|
+
expect(association.autobuilding?).to be(true)
|
|
1797
|
+
end
|
|
1798
|
+
end
|
|
1799
|
+
|
|
1800
|
+
context 'when autobuild is false' do
|
|
1801
|
+
|
|
1802
|
+
let(:options) do
|
|
1803
|
+
{ autobuild: false }
|
|
1804
|
+
end
|
|
1805
|
+
|
|
1806
|
+
it 'returns true' do
|
|
1807
|
+
expect(association.autobuilding?).to be(false)
|
|
1808
|
+
end
|
|
1809
|
+
end
|
|
1810
|
+
end
|
|
1811
|
+
|
|
1812
|
+
context 'when :validate is not specified in the options' do
|
|
1813
|
+
|
|
1814
|
+
it 'returns false' do
|
|
1815
|
+
expect(association.autobuilding?).to be(false)
|
|
1816
|
+
end
|
|
1817
|
+
end
|
|
1818
|
+
end
|
|
1819
|
+
|
|
1820
|
+
describe '#forced_nil_inverse?' do
|
|
1821
|
+
|
|
1822
|
+
it 'returns false' do
|
|
1823
|
+
expect(association.forced_nil_inverse?).to be(false)
|
|
1824
|
+
end
|
|
1825
|
+
end
|
|
1826
|
+
|
|
1827
|
+
describe '#stores_foreign_key?' do
|
|
1828
|
+
|
|
1829
|
+
it 'returns true' do
|
|
1830
|
+
expect(association.stores_foreign_key?).to be(true)
|
|
1831
|
+
end
|
|
1832
|
+
end
|
|
1833
|
+
|
|
1834
|
+
describe '#inverse_setter' do
|
|
1835
|
+
|
|
1836
|
+
context 'when an inverse can be determined' do
|
|
1837
|
+
|
|
1838
|
+
before do
|
|
1839
|
+
OwnerObject.has_many :belonging_objects
|
|
1840
|
+
end
|
|
1841
|
+
|
|
1842
|
+
it 'returns the name of the inverse followed by =' do
|
|
1843
|
+
expect(association.inverse_setter).to eq('belonging_objects=')
|
|
1844
|
+
end
|
|
1845
|
+
end
|
|
1846
|
+
|
|
1847
|
+
context 'when an inverse cannot be determined' do
|
|
1848
|
+
|
|
1849
|
+
it 'returns nil' do
|
|
1850
|
+
expect(association.inverse_setter).to be_nil
|
|
1851
|
+
end
|
|
1852
|
+
end
|
|
1853
|
+
end
|
|
1854
|
+
|
|
1855
|
+
describe '#extension' do
|
|
1856
|
+
|
|
1857
|
+
context 'when a block is passed' do
|
|
1858
|
+
|
|
1859
|
+
let(:association) do
|
|
1860
|
+
belonging_class.belongs_to name, options do; end
|
|
1861
|
+
end
|
|
1862
|
+
|
|
1863
|
+
it 'defines an extension module' do
|
|
1864
|
+
expect(association.extension).to be_a(Module)
|
|
1865
|
+
end
|
|
1866
|
+
|
|
1867
|
+
it 'returns the extension' do
|
|
1868
|
+
expect(association.extension).to eq(
|
|
1869
|
+
"#{belonging_class.name}::#{belonging_class.name}#{name.to_s.camelize}RelationExtension".constantize)
|
|
1870
|
+
end
|
|
1871
|
+
end
|
|
1872
|
+
|
|
1873
|
+
context 'when an :extension is not specified in the options' do
|
|
1874
|
+
|
|
1875
|
+
it 'returns false' do
|
|
1876
|
+
expect(association.extension).to be_nil
|
|
1877
|
+
end
|
|
1878
|
+
end
|
|
1879
|
+
end
|
|
1880
|
+
|
|
1881
|
+
describe '#foreign_key_setter' do
|
|
1882
|
+
|
|
1883
|
+
it 'returns the foriegn key field followed by "="' do
|
|
1884
|
+
expect(association.foreign_key_setter).to eq("owner_object_id=")
|
|
1885
|
+
end
|
|
1886
|
+
end
|
|
1887
|
+
|
|
1888
|
+
describe '#destructive?' do
|
|
1889
|
+
|
|
1890
|
+
context 'when the dependent option is provided' do
|
|
1891
|
+
|
|
1892
|
+
context 'when the dependent option is :delete_all' do
|
|
1893
|
+
|
|
1894
|
+
let(:options) do
|
|
1895
|
+
{
|
|
1896
|
+
dependent: :delete_all
|
|
1897
|
+
}
|
|
1898
|
+
end
|
|
1899
|
+
|
|
1900
|
+
it 'returns true' do
|
|
1901
|
+
expect(association.destructive?).to be(true)
|
|
1902
|
+
end
|
|
1903
|
+
end
|
|
1904
|
+
|
|
1905
|
+
context 'when the dependent option is :destroy' do
|
|
1906
|
+
|
|
1907
|
+
let(:options) do
|
|
1908
|
+
{
|
|
1909
|
+
dependent: :destroy
|
|
1910
|
+
}
|
|
1911
|
+
end
|
|
1912
|
+
|
|
1913
|
+
it 'returns true' do
|
|
1914
|
+
expect(association.destructive?).to be(true)
|
|
1915
|
+
end
|
|
1916
|
+
end
|
|
1917
|
+
|
|
1918
|
+
context 'when the dependent option is :nullify' do
|
|
1919
|
+
|
|
1920
|
+
let(:options) do
|
|
1921
|
+
{
|
|
1922
|
+
dependent: :nullify
|
|
1923
|
+
}
|
|
1924
|
+
end
|
|
1925
|
+
|
|
1926
|
+
it 'returns false' do
|
|
1927
|
+
expect(association.destructive?).to be(false)
|
|
1928
|
+
end
|
|
1929
|
+
end
|
|
1930
|
+
|
|
1931
|
+
context 'when the dependent option is :restrict_with_exception' do
|
|
1932
|
+
|
|
1933
|
+
let(:options) do
|
|
1934
|
+
{
|
|
1935
|
+
dependent: :restrict_with_exception
|
|
1936
|
+
}
|
|
1937
|
+
end
|
|
1938
|
+
|
|
1939
|
+
it 'returns false' do
|
|
1940
|
+
expect(association.destructive?).to be(false)
|
|
1941
|
+
end
|
|
1942
|
+
end
|
|
1943
|
+
|
|
1944
|
+
context 'when the dependent option is :restrict_with_error' do
|
|
1945
|
+
|
|
1946
|
+
let(:options) do
|
|
1947
|
+
{
|
|
1948
|
+
dependent: :restrict_with_error
|
|
1949
|
+
}
|
|
1950
|
+
end
|
|
1951
|
+
|
|
1952
|
+
it 'returns false' do
|
|
1953
|
+
expect(association.destructive?).to be(false)
|
|
1954
|
+
end
|
|
1955
|
+
end
|
|
1956
|
+
end
|
|
1957
|
+
|
|
1958
|
+
context 'when the dependent option is not provided' do
|
|
1959
|
+
|
|
1960
|
+
it 'returns false' do
|
|
1961
|
+
expect(association.destructive?).to be(false)
|
|
1962
|
+
end
|
|
1963
|
+
end
|
|
1964
|
+
end
|
|
1965
|
+
|
|
1966
|
+
describe '#nested_builder' do
|
|
1967
|
+
|
|
1968
|
+
it 'returns an instance of Association::Nested::One' do
|
|
1969
|
+
expect(association.nested_builder({}, {})).to be_a(Mongoid::Association::Nested::One)
|
|
1970
|
+
end
|
|
1971
|
+
end
|
|
1972
|
+
|
|
1973
|
+
describe '#path' do
|
|
1974
|
+
|
|
1975
|
+
it 'returns an instance of Mongoid::Atomic::Paths::Root' do
|
|
1976
|
+
expect(association.path({})).to be_a(Mongoid::Atomic::Paths::Root)
|
|
1977
|
+
end
|
|
1978
|
+
end
|
|
1979
|
+
|
|
1980
|
+
describe '#foreign_key_check' do
|
|
1981
|
+
|
|
1982
|
+
it 'returns the foreign_key followed by "_changed?"' do
|
|
1983
|
+
expect(association.foreign_key_check).to eq('owner_object_id_changed?')
|
|
1984
|
+
end
|
|
1985
|
+
end
|
|
1986
|
+
|
|
1987
|
+
describe '#create_relation' do
|
|
1988
|
+
|
|
1989
|
+
let(:owner) do
|
|
1990
|
+
BelongingObject.new
|
|
1991
|
+
end
|
|
1992
|
+
|
|
1993
|
+
let(:target) do
|
|
1994
|
+
OwnerObject.new
|
|
1995
|
+
end
|
|
1996
|
+
|
|
1997
|
+
before do
|
|
1998
|
+
OwnerObject.has_one :belonging_object
|
|
1999
|
+
end
|
|
2000
|
+
|
|
2001
|
+
it 'returns an instance of Mongoid::Association::Referenced::BelongsTo::Proxy' do
|
|
2002
|
+
expect(Mongoid::Association::Referenced::BelongsTo::Proxy).to receive(:new).and_call_original
|
|
2003
|
+
expect(association.create_relation(owner, target)).to be_a(OwnerObject)
|
|
2004
|
+
end
|
|
2005
|
+
end
|
|
2006
|
+
end
|