mongoid_rails4 4.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3213 -0
- data/LICENSE +20 -0
- data/README.md +62 -0
- data/Rakefile +35 -0
- data/lib/config/locales/en.yml +448 -0
- data/lib/mongoid.rb +104 -0
- data/lib/mongoid/atomic.rb +384 -0
- data/lib/mongoid/atomic/modifiers.rb +317 -0
- data/lib/mongoid/atomic/paths.rb +3 -0
- data/lib/mongoid/atomic/paths/embedded.rb +28 -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 +39 -0
- data/lib/mongoid/attributes.rb +284 -0
- data/lib/mongoid/attributes/dynamic.rb +154 -0
- data/lib/mongoid/attributes/nested.rb +82 -0
- data/lib/mongoid/attributes/processing.rb +147 -0
- data/lib/mongoid/attributes/readonly.rb +56 -0
- data/lib/mongoid/changeable.rb +379 -0
- data/lib/mongoid/composable.rb +104 -0
- data/lib/mongoid/config.rb +263 -0
- data/lib/mongoid/config/environment.rb +44 -0
- data/lib/mongoid/config/options.rb +74 -0
- data/lib/mongoid/config/validators.rb +3 -0
- data/lib/mongoid/config/validators/option.rb +25 -0
- data/lib/mongoid/config/validators/session.rb +140 -0
- data/lib/mongoid/contextual.rb +54 -0
- data/lib/mongoid/contextual/aggregable/memory.rb +109 -0
- data/lib/mongoid/contextual/aggregable/mongo.rb +147 -0
- data/lib/mongoid/contextual/atomic.rb +180 -0
- data/lib/mongoid/contextual/command.rb +61 -0
- data/lib/mongoid/contextual/eager.rb +158 -0
- data/lib/mongoid/contextual/find_and_modify.rb +69 -0
- data/lib/mongoid/contextual/geo_near.rb +238 -0
- data/lib/mongoid/contextual/map_reduce.rb +324 -0
- data/lib/mongoid/contextual/memory.rb +440 -0
- data/lib/mongoid/contextual/mongo.rb +676 -0
- data/lib/mongoid/contextual/queryable.rb +25 -0
- data/lib/mongoid/contextual/text_search.rb +180 -0
- data/lib/mongoid/copyable.rb +67 -0
- data/lib/mongoid/criteria.rb +562 -0
- data/lib/mongoid/criteria/findable.rb +179 -0
- data/lib/mongoid/criteria/inspectable.rb +25 -0
- data/lib/mongoid/criteria/marshalable.rb +50 -0
- data/lib/mongoid/criteria/modifiable.rb +189 -0
- data/lib/mongoid/criteria/scopable.rb +158 -0
- data/lib/mongoid/document.rb +361 -0
- data/lib/mongoid/equality.rb +66 -0
- data/lib/mongoid/errors.rb +40 -0
- data/lib/mongoid/errors/ambiguous_relationship.rb +51 -0
- data/lib/mongoid/errors/callback.rb +25 -0
- data/lib/mongoid/errors/delete_restriction.rb +29 -0
- data/lib/mongoid/errors/document_not_found.rb +111 -0
- data/lib/mongoid/errors/eager_load.rb +22 -0
- data/lib/mongoid/errors/invalid_collection.rb +18 -0
- data/lib/mongoid/errors/invalid_config_option.rb +27 -0
- data/lib/mongoid/errors/invalid_field.rb +64 -0
- data/lib/mongoid/errors/invalid_field_option.rb +35 -0
- data/lib/mongoid/errors/invalid_find.rb +19 -0
- data/lib/mongoid/errors/invalid_includes.rb +32 -0
- data/lib/mongoid/errors/invalid_index.rb +28 -0
- data/lib/mongoid/errors/invalid_options.rb +28 -0
- data/lib/mongoid/errors/invalid_path.rb +21 -0
- data/lib/mongoid/errors/invalid_scope.rb +24 -0
- data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +38 -0
- data/lib/mongoid/errors/invalid_storage_options.rb +27 -0
- data/lib/mongoid/errors/invalid_time.rb +22 -0
- data/lib/mongoid/errors/inverse_not_found.rb +29 -0
- data/lib/mongoid/errors/mixed_relations.rb +32 -0
- data/lib/mongoid/errors/mixed_session_configuration.rb +28 -0
- data/lib/mongoid/errors/mongoid_error.rb +92 -0
- data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +28 -0
- data/lib/mongoid/errors/no_default_session.rb +23 -0
- data/lib/mongoid/errors/no_environment.rb +19 -0
- data/lib/mongoid/errors/no_map_reduce_output.rb +24 -0
- data/lib/mongoid/errors/no_metadata.rb +21 -0
- data/lib/mongoid/errors/no_parent.rb +24 -0
- data/lib/mongoid/errors/no_session_config.rb +22 -0
- data/lib/mongoid/errors/no_session_database.rb +27 -0
- data/lib/mongoid/errors/no_session_hosts.rb +27 -0
- data/lib/mongoid/errors/no_sessions_config.rb +20 -0
- data/lib/mongoid/errors/readonly_attribute.rb +25 -0
- data/lib/mongoid/errors/scope_overwrite.rb +21 -0
- data/lib/mongoid/errors/too_many_nested_attribute_records.rb +20 -0
- data/lib/mongoid/errors/unknown_attribute.rb +25 -0
- data/lib/mongoid/errors/unsaved_document.rb +19 -0
- data/lib/mongoid/errors/unsupported_javascript.rb +27 -0
- data/lib/mongoid/errors/validations.rb +29 -0
- data/lib/mongoid/evolvable.rb +19 -0
- data/lib/mongoid/extensions.rb +35 -0
- data/lib/mongoid/extensions/array.rb +180 -0
- data/lib/mongoid/extensions/big_decimal.rb +69 -0
- data/lib/mongoid/extensions/boolean.rb +21 -0
- data/lib/mongoid/extensions/date.rb +77 -0
- data/lib/mongoid/extensions/date_time.rb +73 -0
- data/lib/mongoid/extensions/false_class.rb +38 -0
- data/lib/mongoid/extensions/float.rb +56 -0
- data/lib/mongoid/extensions/hash.rb +209 -0
- data/lib/mongoid/extensions/integer.rb +67 -0
- data/lib/mongoid/extensions/module.rb +28 -0
- data/lib/mongoid/extensions/nil_class.rb +33 -0
- data/lib/mongoid/extensions/object.rb +274 -0
- data/lib/mongoid/extensions/object_id.rb +54 -0
- data/lib/mongoid/extensions/range.rb +79 -0
- data/lib/mongoid/extensions/regexp.rb +27 -0
- data/lib/mongoid/extensions/set.rb +55 -0
- data/lib/mongoid/extensions/string.rb +199 -0
- data/lib/mongoid/extensions/symbol.rb +54 -0
- data/lib/mongoid/extensions/time.rb +88 -0
- data/lib/mongoid/extensions/time_with_zone.rb +56 -0
- data/lib/mongoid/extensions/true_class.rb +38 -0
- data/lib/mongoid/factory.rb +46 -0
- data/lib/mongoid/fields.rb +542 -0
- data/lib/mongoid/fields/foreign_key.rb +174 -0
- data/lib/mongoid/fields/localized.rb +73 -0
- data/lib/mongoid/fields/standard.rb +273 -0
- data/lib/mongoid/fields/validators.rb +2 -0
- data/lib/mongoid/fields/validators/macro.rb +92 -0
- data/lib/mongoid/findable.rb +133 -0
- data/lib/mongoid/identity_map.rb +163 -0
- data/lib/mongoid/indexable.rb +147 -0
- data/lib/mongoid/indexable/specification.rb +115 -0
- data/lib/mongoid/indexable/validators/options.rb +103 -0
- data/lib/mongoid/inspectable.rb +59 -0
- data/lib/mongoid/interceptable.rb +265 -0
- data/lib/mongoid/loggable.rb +69 -0
- data/lib/mongoid/matchable.rb +152 -0
- data/lib/mongoid/matchable/all.rb +27 -0
- data/lib/mongoid/matchable/and.rb +30 -0
- data/lib/mongoid/matchable/default.rb +72 -0
- data/lib/mongoid/matchable/exists.rb +23 -0
- data/lib/mongoid/matchable/gt.rb +21 -0
- data/lib/mongoid/matchable/gte.rb +21 -0
- data/lib/mongoid/matchable/in.rb +24 -0
- data/lib/mongoid/matchable/lt.rb +21 -0
- data/lib/mongoid/matchable/lte.rb +21 -0
- data/lib/mongoid/matchable/ne.rb +21 -0
- data/lib/mongoid/matchable/nin.rb +21 -0
- data/lib/mongoid/matchable/or.rb +33 -0
- data/lib/mongoid/matchable/size.rb +21 -0
- data/lib/mongoid/persistable.rb +207 -0
- data/lib/mongoid/persistable/creatable.rb +189 -0
- data/lib/mongoid/persistable/deletable.rb +149 -0
- data/lib/mongoid/persistable/destroyable.rb +55 -0
- data/lib/mongoid/persistable/incrementable.rb +36 -0
- data/lib/mongoid/persistable/logical.rb +38 -0
- data/lib/mongoid/persistable/poppable.rb +39 -0
- data/lib/mongoid/persistable/pullable.rb +55 -0
- data/lib/mongoid/persistable/pushable.rb +62 -0
- data/lib/mongoid/persistable/renamable.rb +35 -0
- data/lib/mongoid/persistable/savable.rb +52 -0
- data/lib/mongoid/persistable/settable.rb +33 -0
- data/lib/mongoid/persistable/unsettable.rb +36 -0
- data/lib/mongoid/persistable/updatable.rb +151 -0
- data/lib/mongoid/persistable/upsertable.rb +55 -0
- data/lib/mongoid/positional.rb +71 -0
- data/lib/mongoid/railtie.rb +156 -0
- data/lib/mongoid/railties/database.rake +97 -0
- data/lib/mongoid/railties/document.rb +12 -0
- data/lib/mongoid/relations.rb +162 -0
- data/lib/mongoid/relations/accessors.rb +299 -0
- data/lib/mongoid/relations/auto_save.rb +106 -0
- data/lib/mongoid/relations/binding.rb +218 -0
- data/lib/mongoid/relations/bindings.rb +9 -0
- data/lib/mongoid/relations/bindings/embedded/in.rb +63 -0
- data/lib/mongoid/relations/bindings/embedded/many.rb +50 -0
- data/lib/mongoid/relations/bindings/embedded/one.rb +55 -0
- data/lib/mongoid/relations/bindings/referenced/in.rb +65 -0
- data/lib/mongoid/relations/bindings/referenced/many.rb +42 -0
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +67 -0
- data/lib/mongoid/relations/bindings/referenced/one.rb +44 -0
- data/lib/mongoid/relations/builder.rb +57 -0
- data/lib/mongoid/relations/builders.rb +104 -0
- data/lib/mongoid/relations/builders/embedded/in.rb +29 -0
- data/lib/mongoid/relations/builders/embedded/many.rb +36 -0
- data/lib/mongoid/relations/builders/embedded/one.rb +30 -0
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +174 -0
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +126 -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 +40 -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 +44 -0
- data/lib/mongoid/relations/cascading/destroy.rb +43 -0
- data/lib/mongoid/relations/cascading/nullify.rb +35 -0
- data/lib/mongoid/relations/cascading/restrict.rb +39 -0
- data/lib/mongoid/relations/constraint.rb +49 -0
- data/lib/mongoid/relations/conversions.rb +34 -0
- data/lib/mongoid/relations/counter_cache.rb +105 -0
- data/lib/mongoid/relations/cyclic.rb +107 -0
- data/lib/mongoid/relations/embedded/batchable.rb +355 -0
- data/lib/mongoid/relations/embedded/in.rb +231 -0
- data/lib/mongoid/relations/embedded/many.rb +639 -0
- data/lib/mongoid/relations/embedded/one.rb +223 -0
- data/lib/mongoid/relations/macros.rb +356 -0
- data/lib/mongoid/relations/many.rb +208 -0
- data/lib/mongoid/relations/marshalable.rb +32 -0
- data/lib/mongoid/relations/metadata.rb +1174 -0
- data/lib/mongoid/relations/nested_builder.rb +74 -0
- data/lib/mongoid/relations/one.rb +48 -0
- data/lib/mongoid/relations/options.rb +48 -0
- data/lib/mongoid/relations/polymorphic.rb +39 -0
- data/lib/mongoid/relations/proxy.rb +270 -0
- data/lib/mongoid/relations/referenced/in.rb +297 -0
- data/lib/mongoid/relations/referenced/many.rb +787 -0
- data/lib/mongoid/relations/referenced/many_to_many.rb +486 -0
- data/lib/mongoid/relations/referenced/one.rb +290 -0
- data/lib/mongoid/relations/reflections.rb +62 -0
- data/lib/mongoid/relations/synchronization.rb +169 -0
- data/lib/mongoid/relations/targets.rb +2 -0
- data/lib/mongoid/relations/targets/enumerable.rb +473 -0
- data/lib/mongoid/relations/touchable.rb +94 -0
- data/lib/mongoid/reloadable.rb +95 -0
- data/lib/mongoid/scopable.rb +379 -0
- data/lib/mongoid/selectable.rb +59 -0
- data/lib/mongoid/serializable.rb +170 -0
- data/lib/mongoid/sessions.rb +330 -0
- data/lib/mongoid/sessions/factory.rb +129 -0
- data/lib/mongoid/sessions/mongo_uri.rb +93 -0
- data/lib/mongoid/sessions/options.rb +141 -0
- data/lib/mongoid/sessions/validators.rb +2 -0
- data/lib/mongoid/sessions/validators/storage.rb +49 -0
- data/lib/mongoid/shardable.rb +65 -0
- data/lib/mongoid/state.rb +97 -0
- data/lib/mongoid/threaded.rb +383 -0
- data/lib/mongoid/threaded/lifecycle.rb +164 -0
- data/lib/mongoid/timestamps.rb +15 -0
- data/lib/mongoid/timestamps/created.rb +30 -0
- data/lib/mongoid/timestamps/created/short.rb +19 -0
- data/lib/mongoid/timestamps/short.rb +10 -0
- data/lib/mongoid/timestamps/updated.rb +39 -0
- data/lib/mongoid/timestamps/updated/short.rb +19 -0
- data/lib/mongoid/traversable.rb +192 -0
- data/lib/mongoid/unit_of_work.rb +61 -0
- data/lib/mongoid/validatable.rb +180 -0
- data/lib/mongoid/validatable/associated.rb +48 -0
- data/lib/mongoid/validatable/format.rb +20 -0
- data/lib/mongoid/validatable/length.rb +20 -0
- data/lib/mongoid/validatable/localizable.rb +30 -0
- data/lib/mongoid/validatable/macros.rb +94 -0
- data/lib/mongoid/validatable/presence.rb +86 -0
- data/lib/mongoid/validatable/queryable.rb +30 -0
- data/lib/mongoid/validatable/uniqueness.rb +330 -0
- data/lib/mongoid/version.rb +4 -0
- data/lib/rack/mongoid.rb +2 -0
- data/lib/rack/mongoid/middleware/identity_map.rb +39 -0
- data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +76 -0
- data/lib/rails/generators/mongoid/model/model_generator.rb +25 -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 +65 -0
- data/lib/rails/mongoid.rb +180 -0
- data/lib/support/ruby_version.rb +26 -0
- data/spec/app/models/account.rb +28 -0
- data/spec/app/models/acolyte.rb +17 -0
- data/spec/app/models/actor.rb +18 -0
- data/spec/app/models/actress.rb +2 -0
- data/spec/app/models/address.rb +77 -0
- data/spec/app/models/address_component.rb +5 -0
- data/spec/app/models/address_number.rb +6 -0
- data/spec/app/models/agency.rb +5 -0
- data/spec/app/models/agent.rb +12 -0
- data/spec/app/models/album.rb +14 -0
- data/spec/app/models/alert.rb +5 -0
- data/spec/app/models/animal.rb +25 -0
- data/spec/app/models/answer.rb +4 -0
- data/spec/app/models/appointment.rb +7 -0
- data/spec/app/models/article.rb +10 -0
- data/spec/app/models/artist.rb +66 -0
- data/spec/app/models/artwork.rb +4 -0
- data/spec/app/models/audio.rb +5 -0
- data/spec/app/models/augmentation.rb +11 -0
- data/spec/app/models/author.rb +4 -0
- data/spec/app/models/band.rb +26 -0
- data/spec/app/models/bar.rb +10 -0
- data/spec/app/models/basic.rb +6 -0
- data/spec/app/models/bed.rb +1 -0
- data/spec/app/models/big_palette.rb +2 -0
- data/spec/app/models/birthday.rb +13 -0
- data/spec/app/models/book.rb +13 -0
- data/spec/app/models/breed.rb +4 -0
- data/spec/app/models/browser.rb +6 -0
- data/spec/app/models/building.rb +5 -0
- data/spec/app/models/building_address.rb +5 -0
- data/spec/app/models/bus.rb +7 -0
- data/spec/app/models/business.rb +5 -0
- data/spec/app/models/callback_recorder.rb +25 -0
- data/spec/app/models/callback_test.rb +9 -0
- data/spec/app/models/canvas.rb +25 -0
- data/spec/app/models/car.rb +1 -0
- data/spec/app/models/cat.rb +8 -0
- data/spec/app/models/category.rb +8 -0
- data/spec/app/models/child.rb +4 -0
- data/spec/app/models/child_doc.rb +22 -0
- data/spec/app/models/church.rb +4 -0
- data/spec/app/models/circle.rb +3 -0
- data/spec/app/models/circuit.rb +4 -0
- data/spec/app/models/circus.rb +7 -0
- data/spec/app/models/code.rb +5 -0
- data/spec/app/models/comment.rb +16 -0
- data/spec/app/models/contractor.rb +5 -0
- data/spec/app/models/cookie.rb +6 -0
- data/spec/app/models/country_code.rb +8 -0
- data/spec/app/models/definition.rb +7 -0
- data/spec/app/models/description.rb +11 -0
- data/spec/app/models/dictionary.rb +10 -0
- data/spec/app/models/division.rb +10 -0
- data/spec/app/models/doctor.rb +12 -0
- data/spec/app/models/dog.rb +7 -0
- data/spec/app/models/dokument.rb +5 -0
- data/spec/app/models/dragon.rb +4 -0
- data/spec/app/models/driver.rb +7 -0
- data/spec/app/models/drug.rb +6 -0
- data/spec/app/models/dungeon.rb +4 -0
- data/spec/app/models/email.rb +6 -0
- data/spec/app/models/employer.rb +5 -0
- data/spec/app/models/entry.rb +6 -0
- data/spec/app/models/eraser.rb +1 -0
- data/spec/app/models/event.rb +22 -0
- data/spec/app/models/exhibition.rb +4 -0
- data/spec/app/models/exhibitor.rb +5 -0
- data/spec/app/models/eye.rb +9 -0
- data/spec/app/models/eye_bowl.rb +9 -0
- data/spec/app/models/face.rb +8 -0
- data/spec/app/models/favorite.rb +6 -0
- data/spec/app/models/filesystem.rb +5 -0
- data/spec/app/models/fire_hydrant.rb +6 -0
- data/spec/app/models/firefox.rb +4 -0
- data/spec/app/models/fish.rb +7 -0
- data/spec/app/models/folder.rb +7 -0
- data/spec/app/models/folder_item.rb +9 -0
- data/spec/app/models/fruits.rb +28 -0
- data/spec/app/models/game.rb +19 -0
- data/spec/app/models/ghost.rb +7 -0
- data/spec/app/models/home.rb +4 -0
- data/spec/app/models/house.rb +6 -0
- data/spec/app/models/html_writer.rb +3 -0
- data/spec/app/models/image.rb +22 -0
- data/spec/app/models/implant.rb +16 -0
- data/spec/app/models/item.rb +8 -0
- data/spec/app/models/jar.rb +7 -0
- data/spec/app/models/label.rb +40 -0
- data/spec/app/models/language.rb +5 -0
- data/spec/app/models/lat_lng.rb +15 -0
- data/spec/app/models/league.rb +11 -0
- data/spec/app/models/learner.rb +2 -0
- data/spec/app/models/line_item.rb +6 -0
- data/spec/app/models/location.rb +8 -0
- data/spec/app/models/login.rb +8 -0
- data/spec/app/models/manufacturer.rb +7 -0
- data/spec/app/models/meat.rb +4 -0
- data/spec/app/models/membership.rb +4 -0
- data/spec/app/models/mixed_drink.rb +4 -0
- data/spec/app/models/movie.rb +13 -0
- data/spec/app/models/my_hash.rb +2 -0
- data/spec/app/models/name.rb +23 -0
- data/spec/app/models/node.rb +5 -0
- data/spec/app/models/note.rb +12 -0
- data/spec/app/models/ordered_post.rb +6 -0
- data/spec/app/models/ordered_preference.rb +6 -0
- data/spec/app/models/oscar.rb +15 -0
- data/spec/app/models/override.rb +16 -0
- data/spec/app/models/ownable.rb +6 -0
- data/spec/app/models/owner.rb +6 -0
- data/spec/app/models/pack.rb +3 -0
- data/spec/app/models/page.rb +5 -0
- data/spec/app/models/page_question.rb +4 -0
- data/spec/app/models/palette.rb +7 -0
- data/spec/app/models/parent.rb +5 -0
- data/spec/app/models/parent_doc.rb +6 -0
- data/spec/app/models/passport.rb +5 -0
- data/spec/app/models/patient.rb +9 -0
- data/spec/app/models/pdf_writer.rb +3 -0
- data/spec/app/models/pencil.rb +1 -0
- data/spec/app/models/person.rb +205 -0
- data/spec/app/models/pet.rb +23 -0
- data/spec/app/models/pet_owner.rb +6 -0
- data/spec/app/models/phone.rb +11 -0
- data/spec/app/models/pizza.rb +7 -0
- data/spec/app/models/player.rb +35 -0
- data/spec/app/models/post.rb +44 -0
- data/spec/app/models/powerup.rb +11 -0
- data/spec/app/models/preference.rb +9 -0
- data/spec/app/models/princess.rb +8 -0
- data/spec/app/models/product.rb +15 -0
- data/spec/app/models/profile.rb +5 -0
- data/spec/app/models/pronunciation.rb +5 -0
- data/spec/app/models/purchase.rb +4 -0
- data/spec/app/models/question.rb +8 -0
- data/spec/app/models/quiz.rb +7 -0
- data/spec/app/models/rating.rb +8 -0
- data/spec/app/models/record.rb +46 -0
- data/spec/app/models/registry.rb +4 -0
- data/spec/app/models/role.rb +7 -0
- data/spec/app/models/root_category.rb +4 -0
- data/spec/app/models/sandwich.rb +4 -0
- data/spec/app/models/scheduler.rb +7 -0
- data/spec/app/models/seo.rb +7 -0
- data/spec/app/models/series.rb +4 -0
- data/spec/app/models/server.rb +13 -0
- data/spec/app/models/service.rb +22 -0
- data/spec/app/models/shape.rb +12 -0
- data/spec/app/models/shelf.rb +5 -0
- data/spec/app/models/shipping_container.rb +5 -0
- data/spec/app/models/shipping_pack.rb +3 -0
- data/spec/app/models/shop.rb +6 -0
- data/spec/app/models/short_agent.rb +4 -0
- data/spec/app/models/short_quiz.rb +5 -0
- data/spec/app/models/slave.rb +6 -0
- data/spec/app/models/song.rb +8 -0
- data/spec/app/models/sound.rb +5 -0
- data/spec/app/models/square.rb +4 -0
- data/spec/app/models/strategy.rb +3 -0
- data/spec/app/models/sub_item.rb +3 -0
- data/spec/app/models/subscription.rb +4 -0
- data/spec/app/models/survey.rb +5 -0
- data/spec/app/models/symptom.rb +6 -0
- data/spec/app/models/tag.rb +8 -0
- data/spec/app/models/target.rb +5 -0
- data/spec/app/models/template.rb +5 -0
- data/spec/app/models/thing.rb +9 -0
- data/spec/app/models/title.rb +3 -0
- data/spec/app/models/tool.rb +8 -0
- data/spec/app/models/topping.rb +5 -0
- data/spec/app/models/track.rb +38 -0
- data/spec/app/models/translation.rb +5 -0
- data/spec/app/models/tree.rb +9 -0
- data/spec/app/models/truck.rb +3 -0
- data/spec/app/models/user.rb +21 -0
- data/spec/app/models/user_account.rb +10 -0
- data/spec/app/models/validation_callback.rb +10 -0
- data/spec/app/models/vehicle.rb +11 -0
- data/spec/app/models/version.rb +5 -0
- data/spec/app/models/vet_visit.rb +5 -0
- data/spec/app/models/video.rb +13 -0
- data/spec/app/models/weapon.rb +11 -0
- data/spec/app/models/wiki_page.rb +14 -0
- data/spec/app/models/word.rb +15 -0
- data/spec/app/models/word_origin.rb +11 -0
- data/spec/app/models/writer.rb +11 -0
- data/spec/config/mongoid.yml +38 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +456 -0
- data/spec/mongoid/atomic/paths/embedded/many_spec.rb +118 -0
- data/spec/mongoid/atomic/paths/embedded/one_spec.rb +110 -0
- data/spec/mongoid/atomic/paths/root_spec.rb +48 -0
- data/spec/mongoid/atomic/paths_spec.rb +270 -0
- data/spec/mongoid/atomic_spec.rb +365 -0
- data/spec/mongoid/attributes/nested_spec.rb +4832 -0
- data/spec/mongoid/attributes/readonly_spec.rb +169 -0
- data/spec/mongoid/attributes_spec.rb +1412 -0
- data/spec/mongoid/changeable_spec.rb +1507 -0
- data/spec/mongoid/composable_spec.rb +24 -0
- data/spec/mongoid/config/environment_spec.rb +83 -0
- data/spec/mongoid/config/options_spec.rb +56 -0
- data/spec/mongoid/config_spec.rb +318 -0
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +293 -0
- data/spec/mongoid/contextual/aggregable/mongo_spec.rb +455 -0
- data/spec/mongoid/contextual/atomic_spec.rb +529 -0
- data/spec/mongoid/contextual/find_and_modify_spec.rb +220 -0
- data/spec/mongoid/contextual/geo_near_spec.rb +405 -0
- data/spec/mongoid/contextual/map_reduce_spec.rb +464 -0
- data/spec/mongoid/contextual/memory_spec.rb +1236 -0
- data/spec/mongoid/contextual/mongo_spec.rb +1843 -0
- data/spec/mongoid/contextual/text_search_spec.rb +207 -0
- data/spec/mongoid/copyable_spec.rb +393 -0
- data/spec/mongoid/criteria/findable_spec.rb +1189 -0
- data/spec/mongoid/criteria/inspectable_spec.rb +27 -0
- data/spec/mongoid/criteria/marshalable_spec.rb +28 -0
- data/spec/mongoid/criteria/modifiable_spec.rb +1063 -0
- data/spec/mongoid/criteria/scopable_spec.rb +391 -0
- data/spec/mongoid/criteria_spec.rb +3821 -0
- data/spec/mongoid/document_spec.rb +1205 -0
- data/spec/mongoid/equality_spec.rb +241 -0
- data/spec/mongoid/errors/ambiguous_relationship_spec.rb +29 -0
- data/spec/mongoid/errors/callback_spec.rb +29 -0
- data/spec/mongoid/errors/delete_restriction_spec.rb +29 -0
- data/spec/mongoid/errors/document_not_found_spec.rb +104 -0
- data/spec/mongoid/errors/eager_load_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_collection_spec.rb +36 -0
- data/spec/mongoid/errors/invalid_config_option_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_field_option_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_field_spec.rb +37 -0
- data/spec/mongoid/errors/invalid_find_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_includes_spec.rb +40 -0
- data/spec/mongoid/errors/invalid_index_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_options_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_path_spec.rb +23 -0
- data/spec/mongoid/errors/invalid_scope_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +17 -0
- data/spec/mongoid/errors/invalid_storage_options_spec.rb +29 -0
- data/spec/mongoid/errors/invalid_time_spec.rb +29 -0
- data/spec/mongoid/errors/inverse_not_found_spec.rb +29 -0
- data/spec/mongoid/errors/mixed_relations_spec.rb +29 -0
- data/spec/mongoid/errors/mixed_session_configuration_spec.rb +29 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +48 -0
- data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +29 -0
- data/spec/mongoid/errors/no_environment_spec.rb +29 -0
- data/spec/mongoid/errors/no_map_reduce_output_spec.rb +29 -0
- data/spec/mongoid/errors/no_metadata_spec.rb +23 -0
- data/spec/mongoid/errors/no_parent_spec.rb +29 -0
- data/spec/mongoid/errors/no_session_config_spec.rb +29 -0
- data/spec/mongoid/errors/no_session_database_spec.rb +29 -0
- data/spec/mongoid/errors/no_session_hosts_spec.rb +29 -0
- data/spec/mongoid/errors/no_sessions_config_spec.rb +29 -0
- data/spec/mongoid/errors/readonly_attribute_spec.rb +29 -0
- data/spec/mongoid/errors/scope_overwrite_spec.rb +29 -0
- data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +29 -0
- data/spec/mongoid/errors/unknown_attribute_spec.rb +29 -0
- data/spec/mongoid/errors/unsaved_document_spec.rb +37 -0
- data/spec/mongoid/errors/unsupported_javascript_spec.rb +29 -0
- data/spec/mongoid/errors/validations_spec.rb +45 -0
- data/spec/mongoid/extensions/array_spec.rb +638 -0
- data/spec/mongoid/extensions/big_decimal_spec.rb +104 -0
- data/spec/mongoid/extensions/binary_spec.rb +60 -0
- data/spec/mongoid/extensions/boolean_spec.rb +135 -0
- data/spec/mongoid/extensions/date_spec.rb +235 -0
- data/spec/mongoid/extensions/date_time_spec.rb +155 -0
- data/spec/mongoid/extensions/false_class_spec.rb +42 -0
- data/spec/mongoid/extensions/float_spec.rb +133 -0
- data/spec/mongoid/extensions/hash_spec.rb +333 -0
- data/spec/mongoid/extensions/integer_spec.rb +136 -0
- data/spec/mongoid/extensions/module_spec.rb +42 -0
- data/spec/mongoid/extensions/nil_class_spec.rb +11 -0
- data/spec/mongoid/extensions/object_id_spec.rb +946 -0
- data/spec/mongoid/extensions/object_spec.rb +292 -0
- data/spec/mongoid/extensions/range_spec.rb +105 -0
- data/spec/mongoid/extensions/regexp_spec.rb +47 -0
- data/spec/mongoid/extensions/set_spec.rb +33 -0
- data/spec/mongoid/extensions/string_spec.rb +357 -0
- data/spec/mongoid/extensions/symbol_spec.rb +76 -0
- data/spec/mongoid/extensions/time_spec.rb +467 -0
- data/spec/mongoid/extensions/time_with_zone_spec.rb +405 -0
- data/spec/mongoid/extensions/true_class_spec.rb +42 -0
- data/spec/mongoid/extensions_spec.rb +15 -0
- data/spec/mongoid/factory_spec.rb +185 -0
- data/spec/mongoid/fields/foreign_key_spec.rb +694 -0
- data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +184 -0
- data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +201 -0
- data/spec/mongoid/fields/localized_spec.rb +386 -0
- data/spec/mongoid/fields/standard_spec.rb +166 -0
- data/spec/mongoid/fields_spec.rb +1229 -0
- data/spec/mongoid/findable_spec.rb +342 -0
- data/spec/mongoid/identity_map_spec.rb +564 -0
- data/spec/mongoid/indexable/specification_spec.rb +87 -0
- data/spec/mongoid/indexable_spec.rb +504 -0
- data/spec/mongoid/inspectable_spec.rb +49 -0
- data/spec/mongoid/interceptable_spec.rb +1564 -0
- data/spec/mongoid/loggable_spec.rb +21 -0
- data/spec/mongoid/matchable/all_spec.rb +31 -0
- data/spec/mongoid/matchable/and_spec.rb +162 -0
- data/spec/mongoid/matchable/default_spec.rb +130 -0
- data/spec/mongoid/matchable/exists_spec.rb +57 -0
- data/spec/mongoid/matchable/gt_spec.rb +75 -0
- data/spec/mongoid/matchable/gte_spec.rb +74 -0
- data/spec/mongoid/matchable/in_spec.rb +25 -0
- data/spec/mongoid/matchable/lt_spec.rb +74 -0
- data/spec/mongoid/matchable/lte_spec.rb +74 -0
- data/spec/mongoid/matchable/ne_spec.rb +25 -0
- data/spec/mongoid/matchable/nin_spec.rb +25 -0
- data/spec/mongoid/matchable/or_spec.rb +106 -0
- data/spec/mongoid/matchable/size_spec.rb +25 -0
- data/spec/mongoid/matchable_spec.rb +532 -0
- data/spec/mongoid/persistable/creatable_spec.rb +512 -0
- data/spec/mongoid/persistable/deletable_spec.rb +205 -0
- data/spec/mongoid/persistable/destroyable_spec.rb +148 -0
- data/spec/mongoid/persistable/incrementable_spec.rb +173 -0
- data/spec/mongoid/persistable/logical_spec.rb +143 -0
- data/spec/mongoid/persistable/poppable_spec.rb +115 -0
- data/spec/mongoid/persistable/pullable_spec.rb +228 -0
- data/spec/mongoid/persistable/pushable_spec.rb +258 -0
- data/spec/mongoid/persistable/renamable_spec.rb +135 -0
- data/spec/mongoid/persistable/savable_spec.rb +432 -0
- data/spec/mongoid/persistable/settable_spec.rb +139 -0
- data/spec/mongoid/persistable/unsettable_spec.rb +155 -0
- data/spec/mongoid/persistable/updatable_spec.rb +522 -0
- data/spec/mongoid/persistable/upsertable_spec.rb +106 -0
- data/spec/mongoid/persistable_spec.rb +206 -0
- data/spec/mongoid/positional_spec.rb +227 -0
- data/spec/mongoid/railties/document_spec.rb +24 -0
- data/spec/mongoid/relations/accessors_spec.rb +736 -0
- data/spec/mongoid/relations/auto_save_spec.rb +261 -0
- data/spec/mongoid/relations/bindings/embedded/in_spec.rb +171 -0
- data/spec/mongoid/relations/bindings/embedded/many_spec.rb +54 -0
- data/spec/mongoid/relations/bindings/embedded/one_spec.rb +77 -0
- data/spec/mongoid/relations/bindings/referenced/in_spec.rb +241 -0
- data/spec/mongoid/relations/bindings/referenced/many_spec.rb +153 -0
- data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +178 -0
- data/spec/mongoid/relations/bindings/referenced/one_spec.rb +131 -0
- data/spec/mongoid/relations/builders/embedded/in_spec.rb +34 -0
- data/spec/mongoid/relations/builders/embedded/many_spec.rb +132 -0
- data/spec/mongoid/relations/builders/embedded/one_spec.rb +99 -0
- data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +234 -0
- data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +250 -0
- data/spec/mongoid/relations/builders/referenced/in_spec.rb +241 -0
- data/spec/mongoid/relations/builders/referenced/many_spec.rb +137 -0
- data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +178 -0
- data/spec/mongoid/relations/builders/referenced/one_spec.rb +124 -0
- data/spec/mongoid/relations/builders_spec.rb +226 -0
- data/spec/mongoid/relations/cascading/delete_spec.rb +101 -0
- data/spec/mongoid/relations/cascading/destroy_spec.rb +47 -0
- data/spec/mongoid/relations/cascading/nullify_spec.rb +32 -0
- data/spec/mongoid/relations/cascading/restrict_spec.rb +68 -0
- data/spec/mongoid/relations/cascading_spec.rb +355 -0
- data/spec/mongoid/relations/constraint_spec.rb +74 -0
- data/spec/mongoid/relations/conversions_spec.rb +126 -0
- data/spec/mongoid/relations/counter_cache_spec.rb +205 -0
- data/spec/mongoid/relations/cyclic_spec.rb +156 -0
- data/spec/mongoid/relations/embedded/dirty_spec.rb +65 -0
- data/spec/mongoid/relations/embedded/in_spec.rb +579 -0
- data/spec/mongoid/relations/embedded/many_spec.rb +3781 -0
- data/spec/mongoid/relations/embedded/one_spec.rb +1014 -0
- data/spec/mongoid/relations/macros_spec.rb +613 -0
- data/spec/mongoid/relations/metadata_spec.rb +1917 -0
- data/spec/mongoid/relations/options_spec.rb +35 -0
- data/spec/mongoid/relations/polymorphic_spec.rb +128 -0
- data/spec/mongoid/relations/proxy_spec.rb +48 -0
- data/spec/mongoid/relations/referenced/in_spec.rb +1435 -0
- data/spec/mongoid/relations/referenced/many_spec.rb +3546 -0
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +3556 -0
- data/spec/mongoid/relations/referenced/one_spec.rb +1289 -0
- data/spec/mongoid/relations/reflections_spec.rb +101 -0
- data/spec/mongoid/relations/synchronization_spec.rb +449 -0
- data/spec/mongoid/relations/targets/enumerable_spec.rb +1710 -0
- data/spec/mongoid/relations/touchable_spec.rb +296 -0
- data/spec/mongoid/relations_spec.rb +188 -0
- data/spec/mongoid/reloadable_spec.rb +305 -0
- data/spec/mongoid/scopable_spec.rb +926 -0
- data/spec/mongoid/selectable_spec.rb +134 -0
- data/spec/mongoid/serializable_spec.rb +862 -0
- data/spec/mongoid/sessions/factory_spec.rb +312 -0
- data/spec/mongoid/sessions/mongo_uri_spec.rb +103 -0
- data/spec/mongoid/sessions/options_spec.rb +71 -0
- data/spec/mongoid/sessions_spec.rb +1078 -0
- data/spec/mongoid/shardable_spec.rb +61 -0
- data/spec/mongoid/state_spec.rb +102 -0
- data/spec/mongoid/threaded_spec.rb +258 -0
- data/spec/mongoid/timestamps/created/short_spec.rb +51 -0
- data/spec/mongoid/timestamps/created_spec.rb +44 -0
- data/spec/mongoid/timestamps/updated/short_spec.rb +90 -0
- data/spec/mongoid/timestamps/updated_spec.rb +86 -0
- data/spec/mongoid/timestamps_spec.rb +112 -0
- data/spec/mongoid/traversable_spec.rb +244 -0
- data/spec/mongoid/unit_of_work_spec.rb +196 -0
- data/spec/mongoid/validatable/associated_spec.rb +183 -0
- data/spec/mongoid/validatable/format_spec.rb +83 -0
- data/spec/mongoid/validatable/length_spec.rb +119 -0
- data/spec/mongoid/validatable/numericality_spec.rb +30 -0
- data/spec/mongoid/validatable/presence_spec.rb +511 -0
- data/spec/mongoid/validatable/uniqueness_spec.rb +2305 -0
- data/spec/mongoid/validatable_spec.rb +309 -0
- data/spec/mongoid_spec.rb +74 -0
- data/spec/rack/mongoid/middleware/identity_map_spec.rb +72 -0
- data/spec/rails/mongoid_spec.rb +462 -0
- data/spec/spec_helper.rb +103 -0
- metadata +1159 -0
@@ -0,0 +1,208 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Relations
|
4
|
+
|
5
|
+
# This is the superclass for all many to one and many to many relation
|
6
|
+
# proxies.
|
7
|
+
class Many < Proxy
|
8
|
+
|
9
|
+
delegate :avg, :max, :min, :sum, to: :criteria
|
10
|
+
delegate :length, :size, to: :target
|
11
|
+
|
12
|
+
# Is the relation empty?
|
13
|
+
#
|
14
|
+
# @example Is the relation empty??
|
15
|
+
# person.addresses.blank?
|
16
|
+
#
|
17
|
+
# @return [ true, false ] If the relation is empty or not.
|
18
|
+
#
|
19
|
+
# @since 2.1.0
|
20
|
+
def blank?
|
21
|
+
size == 0
|
22
|
+
end
|
23
|
+
|
24
|
+
# Creates a new document on the references many relation. This will
|
25
|
+
# save the document if the parent has been persisted.
|
26
|
+
#
|
27
|
+
# @example Create and save the new document.
|
28
|
+
# person.posts.create(:text => "Testing")
|
29
|
+
#
|
30
|
+
# @overload create(attributes = nil, options = {}, type = nil)
|
31
|
+
# @param [ Hash ] attributes The attributes to create with.
|
32
|
+
# @param [ Hash ] options The scoped assignment options.
|
33
|
+
# @param [ Class ] type The optional type of document to create.
|
34
|
+
#
|
35
|
+
# @overload create(attributes = nil, type = nil)
|
36
|
+
# @param [ Hash ] attributes The attributes to create with.
|
37
|
+
# @param [ Class ] type The optional type of document to create.
|
38
|
+
#
|
39
|
+
# @return [ Document ] The newly created document.
|
40
|
+
#
|
41
|
+
# @since 2.0.0.beta.1
|
42
|
+
def create(attributes = nil, type = nil, &block)
|
43
|
+
doc = build(attributes, type, &block)
|
44
|
+
base.persisted? ? doc.save : raise_unsaved(doc)
|
45
|
+
doc
|
46
|
+
end
|
47
|
+
|
48
|
+
# Creates a new document on the references many relation. This will
|
49
|
+
# save the document if the parent has been persisted and will raise an
|
50
|
+
# error if validation fails.
|
51
|
+
#
|
52
|
+
# @example Create and save the new document.
|
53
|
+
# person.posts.create!(:text => "Testing")
|
54
|
+
#
|
55
|
+
# @overload create!(attributes = nil, options = {}, type = nil)
|
56
|
+
# @param [ Hash ] attributes The attributes to create with.
|
57
|
+
# @param [ Class ] type The optional type of document to create.
|
58
|
+
#
|
59
|
+
# @overload create!(attributes = nil, type = nil)
|
60
|
+
# @param [ Hash ] attributes The attributes to create with.
|
61
|
+
# @param [ Class ] type The optional type of document to create.
|
62
|
+
#
|
63
|
+
# @raise [ Errors::Validations ] If validation failed.
|
64
|
+
#
|
65
|
+
# @return [ Document ] The newly created document.
|
66
|
+
#
|
67
|
+
# @since 2.0.0.beta.1
|
68
|
+
def create!(attributes = nil, type = nil, &block)
|
69
|
+
doc = build(attributes, type, &block)
|
70
|
+
base.persisted? ? doc.save! : raise_unsaved(doc)
|
71
|
+
doc
|
72
|
+
end
|
73
|
+
|
74
|
+
# Find the first document given the conditions, or creates a new document
|
75
|
+
# with the conditions that were supplied.
|
76
|
+
#
|
77
|
+
# @example Find or create.
|
78
|
+
# person.posts.find_or_create_by(:title => "Testing")
|
79
|
+
#
|
80
|
+
# @overload find_or_create_by(attributes = nil, type = nil)
|
81
|
+
# @param [ Hash ] attributes The attributes to search or create with.
|
82
|
+
# @param [ Class ] type The optional type of document to create.
|
83
|
+
#
|
84
|
+
# @overload find_or_create_by(attributes = nil, type = nil)
|
85
|
+
# @param [ Hash ] attributes The attributes to search or create with.
|
86
|
+
# @param [ Class ] type The optional type of document to create.
|
87
|
+
#
|
88
|
+
# @return [ Document ] An existing document or newly created one.
|
89
|
+
def find_or_create_by(attrs = {}, type = nil, &block)
|
90
|
+
find_or(:create, attrs, type, &block)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Find the first +Document+ given the conditions, or instantiates a new document
|
94
|
+
# with the conditions that were supplied
|
95
|
+
#
|
96
|
+
# @example Find or initialize.
|
97
|
+
# person.posts.find_or_initialize_by(:title => "Test")
|
98
|
+
#
|
99
|
+
# @overload find_or_initialize_by(attributes = {}, type = nil)
|
100
|
+
# @param [ Hash ] attributes The attributes to search or initialize with.
|
101
|
+
# @param [ Class ] type The optional subclass to build.
|
102
|
+
#
|
103
|
+
# @overload find_or_initialize_by(attributes = {}, type = nil)
|
104
|
+
# @param [ Hash ] attributes The attributes to search or initialize with.
|
105
|
+
# @param [ Class ] type The optional subclass to build.
|
106
|
+
#
|
107
|
+
# @return [ Document ] An existing document or newly instantiated one.
|
108
|
+
def find_or_initialize_by(attrs = {}, type = nil, &block)
|
109
|
+
find_or(:build, attrs, type, &block)
|
110
|
+
end
|
111
|
+
|
112
|
+
# This proxy can never be nil.
|
113
|
+
#
|
114
|
+
# @example Is the proxy nil?
|
115
|
+
# relation.nil?
|
116
|
+
#
|
117
|
+
# @return [ false ] Always false.
|
118
|
+
#
|
119
|
+
# @since 2.0.0
|
120
|
+
def nil?
|
121
|
+
false
|
122
|
+
end
|
123
|
+
|
124
|
+
# Since method_missing is overridden we should override this as well.
|
125
|
+
#
|
126
|
+
# @example Does the proxy respond to the method?
|
127
|
+
# relation.respond_to?(:name)
|
128
|
+
#
|
129
|
+
# @param [ Symbol ] name The method name.
|
130
|
+
#
|
131
|
+
# @return [ true, false ] If the proxy responds to the method.
|
132
|
+
#
|
133
|
+
# @since 2.0.0
|
134
|
+
def respond_to?(name, include_private = false)
|
135
|
+
[].respond_to?(name, include_private) ||
|
136
|
+
klass.respond_to?(name, include_private) || super
|
137
|
+
end
|
138
|
+
|
139
|
+
# This is public access to the relation's criteria.
|
140
|
+
#
|
141
|
+
# @example Get the scoped relation.
|
142
|
+
# relation.scoped
|
143
|
+
#
|
144
|
+
# @return [ Criteria ] The scoped criteria.
|
145
|
+
#
|
146
|
+
# @since 2.1.0
|
147
|
+
def scoped
|
148
|
+
criteria
|
149
|
+
end
|
150
|
+
|
151
|
+
# Gets the document as a serializable hash, used by ActiveModel's JSON and
|
152
|
+
# XML serializers. This override is just to be able to pass the :include
|
153
|
+
# and :except options to get associations in the hash.
|
154
|
+
#
|
155
|
+
# @example Get the serializable hash.
|
156
|
+
# relation.serializable_hash
|
157
|
+
#
|
158
|
+
# @param [ Hash ] options The options to pass.
|
159
|
+
#
|
160
|
+
# @option options [ Symbol ] :include What relations to include
|
161
|
+
# @option options [ Symbol ] :only Limit the fields to only these.
|
162
|
+
# @option options [ Symbol ] :except Dont include these fields.
|
163
|
+
#
|
164
|
+
# @return [ Hash ] The documents, ready to be serialized.
|
165
|
+
#
|
166
|
+
# @since 2.0.0.rc.6
|
167
|
+
def serializable_hash(options = {})
|
168
|
+
target.map { |document| document.serializable_hash(options) }
|
169
|
+
end
|
170
|
+
|
171
|
+
# Get a criteria for the embedded documents without the default scoping
|
172
|
+
# applied.
|
173
|
+
#
|
174
|
+
# @example Get the unscoped criteria.
|
175
|
+
# person.addresses.unscoped
|
176
|
+
#
|
177
|
+
# @return [ Criteria ] The unscoped criteria.
|
178
|
+
#
|
179
|
+
# @since 2.4.0
|
180
|
+
def unscoped
|
181
|
+
criteria.unscoped
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
# Find the first object given the supplied attributes or create/initialize it.
|
187
|
+
#
|
188
|
+
# @example Find or create|initialize.
|
189
|
+
# person.addresses.find_or(:create, :street => "Bond")
|
190
|
+
#
|
191
|
+
# @overload find_or(method, attributes = {}, type = nil)
|
192
|
+
# @param [ Symbol ] method The method name, create or new.
|
193
|
+
# @param [ Hash ] attributes The attributes to search or build with.
|
194
|
+
# @param [ Class ] type The optional subclass to build.
|
195
|
+
#
|
196
|
+
# @overload find_or(attributes = {}, type = nil)
|
197
|
+
# @param [ Symbol ] method The method name, create or new.
|
198
|
+
# @param [ Hash ] attributes The attributes to search or build with.
|
199
|
+
# @param [ Class ] type The optional subclass to build.
|
200
|
+
#
|
201
|
+
# @return [ Document ] A matching document or a new/created one.
|
202
|
+
def find_or(method, attrs = {}, type = nil, &block)
|
203
|
+
attrs["_type"] = type.to_s if type
|
204
|
+
where(attrs).first || send(method, attrs, type, &block)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Relations
|
4
|
+
module Marshalable
|
5
|
+
|
6
|
+
# Provides the data needed to Marshal.dump a relation proxy.
|
7
|
+
#
|
8
|
+
# @example Dump the proxy.
|
9
|
+
# Marshal.dump(proxy)
|
10
|
+
#
|
11
|
+
# @return [ Array<Object> ] The dumped data.
|
12
|
+
#
|
13
|
+
# @since 3.0.15
|
14
|
+
def marshal_dump
|
15
|
+
[ base, target, metadata ]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Takes the provided data and sets it back on the proxy.
|
19
|
+
#
|
20
|
+
# @example Load the proxy.
|
21
|
+
# Marshal.load(proxy)
|
22
|
+
#
|
23
|
+
# @return [ Array<Object> ] The loaded data.
|
24
|
+
#
|
25
|
+
# @since 3.0.15
|
26
|
+
def marshal_load(data)
|
27
|
+
@base, @target, @metadata = data
|
28
|
+
extend_proxy(metadata.extension) if metadata.extension?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,1174 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Relations
|
4
|
+
|
5
|
+
# The "Grand Poobah" of information about any relation is this class. It
|
6
|
+
# contains everything you could ever possible want to know.
|
7
|
+
class Metadata < Hash
|
8
|
+
|
9
|
+
delegate :foreign_key_default, :stores_foreign_key?, to: :relation
|
10
|
+
|
11
|
+
# Returns the as option of the relation.
|
12
|
+
#
|
13
|
+
# @example Get the as option.
|
14
|
+
# metadata.as
|
15
|
+
#
|
16
|
+
# @return [ true, false ] The as option.
|
17
|
+
#
|
18
|
+
# @since 2.1.0
|
19
|
+
def as
|
20
|
+
self[:as]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Tells whether an as option exists.
|
24
|
+
#
|
25
|
+
# @example Is the as option set?
|
26
|
+
# metadata.as?
|
27
|
+
#
|
28
|
+
# @return [ true, false ] True if an as exists, false if not.
|
29
|
+
#
|
30
|
+
# @since 2.0.0.rc.1
|
31
|
+
def as?
|
32
|
+
!!as
|
33
|
+
end
|
34
|
+
|
35
|
+
# Is the relation autobuilding if accessed via the getter and the
|
36
|
+
# document is new.
|
37
|
+
#
|
38
|
+
# @example Is the relation autobuilding?
|
39
|
+
# metadata.autobuilding?
|
40
|
+
#
|
41
|
+
# @return [ true, false ] If the relation autobuilds.
|
42
|
+
#
|
43
|
+
# @since 3.0.0
|
44
|
+
def autobuilding?
|
45
|
+
!!self[:autobuild]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the autosave option of the relation.
|
49
|
+
#
|
50
|
+
# @example Get the autosave option.
|
51
|
+
# metadata.autosave
|
52
|
+
#
|
53
|
+
# @return [ true, false ] The autosave option.
|
54
|
+
#
|
55
|
+
# @since 2.1.0
|
56
|
+
def autosave
|
57
|
+
self[:autosave]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Does the metadata have a autosave option?
|
61
|
+
#
|
62
|
+
# @example Is the relation autosaving?
|
63
|
+
# metadata.autosave?
|
64
|
+
#
|
65
|
+
# @return [ true, false ] If the relation autosaves.
|
66
|
+
#
|
67
|
+
# @since 2.1.0
|
68
|
+
def autosave?
|
69
|
+
!!autosave
|
70
|
+
end
|
71
|
+
|
72
|
+
# Gets a relation builder associated with the relation this metadata is
|
73
|
+
# for.
|
74
|
+
#
|
75
|
+
# @example Get the builder.
|
76
|
+
# metadata.builder(document)
|
77
|
+
#
|
78
|
+
# @param [ Document ] base The base document.
|
79
|
+
# @param [ Object ] object A document or attributes to give the builder.
|
80
|
+
#
|
81
|
+
# @return [ Builder ] The builder for the relation.
|
82
|
+
#
|
83
|
+
# @since 2.0.0.rc.1
|
84
|
+
def builder(base, object)
|
85
|
+
relation.builder(base, self, object)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the name of the strategy used for handling dependent relations.
|
89
|
+
#
|
90
|
+
# @example Get the strategy.
|
91
|
+
# metadata.cascade_strategy
|
92
|
+
#
|
93
|
+
# @return [ Object ] The cascading strategy to use.
|
94
|
+
#
|
95
|
+
# @since 2.0.0.rc.1
|
96
|
+
def cascade_strategy
|
97
|
+
if dependent?
|
98
|
+
"Mongoid::Relations::Cascading::#{dependent.to_s.classify}".constantize
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Is this an embedded relations that allows callbacks to cascade down to
|
103
|
+
# it?
|
104
|
+
#
|
105
|
+
# @example Does the relation have cascading callbacks?
|
106
|
+
# metadata.cascading_callbacks?
|
107
|
+
#
|
108
|
+
# @return [ true, false ] If the relation cascades callbacks.
|
109
|
+
#
|
110
|
+
# @since 2.3.0
|
111
|
+
def cascading_callbacks?
|
112
|
+
!!self[:cascade_callbacks]
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns the name of the class that this relation contains. If the
|
116
|
+
# class_name was provided as an option this will return that, otherwise
|
117
|
+
# it will determine the name from the name property.
|
118
|
+
#
|
119
|
+
# @example Get the class name.
|
120
|
+
# metadata.class_name
|
121
|
+
#
|
122
|
+
# @return [ String ] The name of the relation's proxied class.
|
123
|
+
#
|
124
|
+
# @since 2.0.0.rc.1
|
125
|
+
def class_name
|
126
|
+
@class_name ||= (self[:class_name] || classify).sub(/\A::/,"")
|
127
|
+
end
|
128
|
+
|
129
|
+
# Get the foreign key contraint for the metadata.
|
130
|
+
#
|
131
|
+
# @example Get the constaint.
|
132
|
+
# metadata.constraint
|
133
|
+
#
|
134
|
+
# @return [ Constraint ] The constraint.
|
135
|
+
#
|
136
|
+
# @since 2.0.0.rc.1
|
137
|
+
def constraint
|
138
|
+
@constraint ||= Constraint.new(self)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Does the metadata have a counter cache?
|
142
|
+
#
|
143
|
+
# @example Is the metadata counter_cached?
|
144
|
+
# metadata.counter_cached?
|
145
|
+
#
|
146
|
+
# @return [ true, false ] If the metadata has counter_cache
|
147
|
+
#
|
148
|
+
# @since 3.1.0
|
149
|
+
def counter_cached?
|
150
|
+
!!self[:counter_cache]
|
151
|
+
end
|
152
|
+
|
153
|
+
# Returns the counter cache column name
|
154
|
+
#
|
155
|
+
# @example Get the counter cache column.
|
156
|
+
# metadata.counter_cache_column_name
|
157
|
+
#
|
158
|
+
# @return [ String ] The counter cache column
|
159
|
+
#
|
160
|
+
# @since 3.1.0
|
161
|
+
def counter_cache_column_name
|
162
|
+
if self[:counter_cache] == true
|
163
|
+
"#{inverse || inverse_class_name.demodulize.underscore.pluralize}_count"
|
164
|
+
else
|
165
|
+
self[:counter_cache].to_s
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Get the criteria that is used to query for this metadata's relation.
|
170
|
+
#
|
171
|
+
# @example Get the criteria.
|
172
|
+
# metadata.criteria([ id_one, id_two ], Person)
|
173
|
+
#
|
174
|
+
# @param [ Object ] object The foreign key used for the query.
|
175
|
+
# @param [ Class ] type The base class.
|
176
|
+
#
|
177
|
+
# @return [ Criteria ] The criteria.
|
178
|
+
#
|
179
|
+
# @since 2.1.0
|
180
|
+
def criteria(object, type)
|
181
|
+
relation.criteria(self, object, type)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns the cyclic option of the relation.
|
185
|
+
#
|
186
|
+
# @example Get the cyclic option.
|
187
|
+
# metadata.cyclic
|
188
|
+
#
|
189
|
+
# @return [ true, false ] The cyclic option.
|
190
|
+
#
|
191
|
+
# @since 2.1.0
|
192
|
+
def cyclic
|
193
|
+
self[:cyclic]
|
194
|
+
end
|
195
|
+
|
196
|
+
# Does the metadata have a cyclic option?
|
197
|
+
#
|
198
|
+
# @example Is the metadata cyclic?
|
199
|
+
# metadata.cyclic?
|
200
|
+
#
|
201
|
+
# @return [ true, false ] If the metadata is cyclic.
|
202
|
+
#
|
203
|
+
# @since 2.1.0
|
204
|
+
def cyclic?
|
205
|
+
!!cyclic
|
206
|
+
end
|
207
|
+
|
208
|
+
# Returns the dependent option of the relation.
|
209
|
+
#
|
210
|
+
# @example Get the dependent option.
|
211
|
+
# metadata.dependent
|
212
|
+
#
|
213
|
+
# @return [ Symbol ] The dependent option.
|
214
|
+
#
|
215
|
+
# @since 2.1.0
|
216
|
+
def dependent
|
217
|
+
self[:dependent]
|
218
|
+
end
|
219
|
+
|
220
|
+
# Does the metadata have a dependent option?
|
221
|
+
#
|
222
|
+
# @example Is the metadata performing cascades?
|
223
|
+
# metadata.dependent?
|
224
|
+
#
|
225
|
+
# @return [ true, false ] If the metadata cascades.
|
226
|
+
#
|
227
|
+
# @since 2.1.0
|
228
|
+
def dependent?
|
229
|
+
!!dependent
|
230
|
+
end
|
231
|
+
|
232
|
+
# Get the criteria needed to eager load this relation.
|
233
|
+
#
|
234
|
+
# @example Get the eager loading criteria.
|
235
|
+
# metadata.eager_load(criteria)
|
236
|
+
#
|
237
|
+
# @param [ Array<Object> ] ids The ids of the returned parents.
|
238
|
+
#
|
239
|
+
# @return [ Criteria ] The eager loading criteria.
|
240
|
+
#
|
241
|
+
# @since 2.2.0
|
242
|
+
def eager_load(ids)
|
243
|
+
relation.eager_load(self, ids)
|
244
|
+
end
|
245
|
+
|
246
|
+
# Will determine if the relation is an embedded one or not. Currently
|
247
|
+
# only checks against embeds one and many.
|
248
|
+
#
|
249
|
+
# @example Is the document embedded.
|
250
|
+
# metadata.embedded?
|
251
|
+
#
|
252
|
+
# @return [ true, false ] True if embedded, false if not.
|
253
|
+
#
|
254
|
+
# @since 2.0.0.rc.1
|
255
|
+
def embedded?
|
256
|
+
@embedded ||= (macro == :embeds_one || macro == :embeds_many)
|
257
|
+
end
|
258
|
+
|
259
|
+
# Returns the extension of the relation.
|
260
|
+
#
|
261
|
+
# @example Get the relation extension.
|
262
|
+
# metadata.extension
|
263
|
+
#
|
264
|
+
# @return [ Module ] The extension or nil.
|
265
|
+
#
|
266
|
+
# @since 2.0.0.rc.1
|
267
|
+
def extension
|
268
|
+
self[:extend]
|
269
|
+
end
|
270
|
+
|
271
|
+
# Tells whether an extension definition exist for this relation.
|
272
|
+
#
|
273
|
+
# @example Is an extension defined?
|
274
|
+
# metadata.extension?
|
275
|
+
#
|
276
|
+
# @return [ true, false ] True if an extension exists, false if not.
|
277
|
+
#
|
278
|
+
# @since 2.0.0.rc.1
|
279
|
+
def extension?
|
280
|
+
!!extension
|
281
|
+
end
|
282
|
+
|
283
|
+
# Does this metadata have a forced nil inverse_of defined. (Used in many
|
284
|
+
# to manies)
|
285
|
+
#
|
286
|
+
# @example Is this a forced nil inverse?
|
287
|
+
# metadata.forced_nil_inverse?
|
288
|
+
#
|
289
|
+
# @return [ true, false ] If inverse_of has been explicitly set to nil.
|
290
|
+
#
|
291
|
+
# @since 2.3.3
|
292
|
+
def forced_nil_inverse?
|
293
|
+
@forced_nil_inverse ||= has_key?(:inverse_of) && inverse_of.nil?
|
294
|
+
end
|
295
|
+
|
296
|
+
# Handles all the logic for figuring out what the foreign_key is for each
|
297
|
+
# relations query. The logic is as follows:
|
298
|
+
#
|
299
|
+
# 1. If the developer defined a custom key, use that.
|
300
|
+
# 2. If the relation stores a foreign key,
|
301
|
+
# use the class_name_id strategy.
|
302
|
+
# 3. If the relation does not store the key,
|
303
|
+
# use the inverse_class_name_id strategy.
|
304
|
+
#
|
305
|
+
# @example Get the foreign key.
|
306
|
+
# metadata.foreign_key
|
307
|
+
#
|
308
|
+
# @return [ String ] The foreign key for the relation.
|
309
|
+
#
|
310
|
+
# @since 2.0.0.rc.1
|
311
|
+
def foreign_key
|
312
|
+
@foreign_key ||= determine_foreign_key
|
313
|
+
end
|
314
|
+
|
315
|
+
# Get the name of the method to check if the foreign key has changed.
|
316
|
+
#
|
317
|
+
# @example Get the foreign key check method.
|
318
|
+
# metadata.foreign_key_check
|
319
|
+
#
|
320
|
+
# @return [ String ] The foreign key check.
|
321
|
+
#
|
322
|
+
# @since 2.1.0
|
323
|
+
def foreign_key_check
|
324
|
+
@foreign_key_check ||= "#{foreign_key}_changed?"
|
325
|
+
end
|
326
|
+
|
327
|
+
# Returns the name of the method used to set the foreign key on a
|
328
|
+
# document.
|
329
|
+
#
|
330
|
+
# @example Get the setter for the foreign key.
|
331
|
+
# metadata.foreign_key_setter
|
332
|
+
#
|
333
|
+
# @return [ String ] The foreign_key plus =.
|
334
|
+
#
|
335
|
+
# @since 2.0.0.rc.1
|
336
|
+
def foreign_key_setter
|
337
|
+
@foreign_key_setter ||= "#{foreign_key}="
|
338
|
+
end
|
339
|
+
|
340
|
+
# Returns the index option of the relation.
|
341
|
+
#
|
342
|
+
# @example Get the index option.
|
343
|
+
# metadata.index
|
344
|
+
#
|
345
|
+
# @return [ true, false ] The index option.
|
346
|
+
#
|
347
|
+
# @since 2.1.0
|
348
|
+
def index
|
349
|
+
self[:index]
|
350
|
+
end
|
351
|
+
|
352
|
+
# Tells whether a foreign key index exists on the relation.
|
353
|
+
#
|
354
|
+
# @example Is the key indexed?
|
355
|
+
# metadata.indexed?
|
356
|
+
#
|
357
|
+
# @return [ true, false ] True if an index exists, false if not.
|
358
|
+
#
|
359
|
+
# @since 2.0.0.rc.1
|
360
|
+
def indexed?
|
361
|
+
!!index
|
362
|
+
end
|
363
|
+
|
364
|
+
# Instantiate new metadata for a relation.
|
365
|
+
#
|
366
|
+
# @example Create the new metadata.
|
367
|
+
# Metadata.new(:name => :addresses)
|
368
|
+
#
|
369
|
+
# @param [ Hash ] properties The relation options.
|
370
|
+
#
|
371
|
+
# @since 2.0.0.rc.1
|
372
|
+
def initialize(properties = {})
|
373
|
+
Options.validate!(properties)
|
374
|
+
merge!(properties)
|
375
|
+
end
|
376
|
+
|
377
|
+
# Since a lot of the information from the metadata is inferred and not
|
378
|
+
# explicitly stored in the hash, the inspection needs to be much more
|
379
|
+
# detailed.
|
380
|
+
#
|
381
|
+
# @example Inspect the metadata.
|
382
|
+
# metadata.inspect
|
383
|
+
#
|
384
|
+
# @return [ String ] Oodles of information in a nice format.
|
385
|
+
#
|
386
|
+
# @since 2.0.0.rc.1
|
387
|
+
def inspect
|
388
|
+
%Q{#<Mongoid::Relations::Metadata
|
389
|
+
autobuild: #{autobuilding?}
|
390
|
+
class_name: #{class_name}
|
391
|
+
cyclic: #{cyclic.inspect}
|
392
|
+
counter_cache:#{counter_cached?}
|
393
|
+
dependent: #{dependent.inspect}
|
394
|
+
inverse_of: #{inverse_of.inspect}
|
395
|
+
key: #{key}
|
396
|
+
macro: #{macro}
|
397
|
+
name: #{name}
|
398
|
+
order: #{order.inspect}
|
399
|
+
polymorphic: #{polymorphic?}
|
400
|
+
relation: #{relation}
|
401
|
+
setter: #{setter}>
|
402
|
+
}
|
403
|
+
end
|
404
|
+
|
405
|
+
# Get the name of the inverse relations if they exists. If this is a
|
406
|
+
# polymorphic relation then just return the :as option that was defined.
|
407
|
+
#
|
408
|
+
# @example Get the names of the inverses.
|
409
|
+
# metadata.inverses
|
410
|
+
#
|
411
|
+
# @param [ Document ] other The document to aid in the discovery.
|
412
|
+
#
|
413
|
+
# @return [ Array<Symbol> ] The inverse name.
|
414
|
+
def inverses(other = nil)
|
415
|
+
if self[:polymorphic]
|
416
|
+
lookup_inverses(other)
|
417
|
+
else
|
418
|
+
@inverses ||= determine_inverses
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
# Get the name of the inverse relation if it exists. If this is a
|
423
|
+
# polymorphic relation then just return the :as option that was defined.
|
424
|
+
#
|
425
|
+
# @example Get the name of the inverse.
|
426
|
+
# metadata.inverse
|
427
|
+
#
|
428
|
+
# @param [ Document ] other The document to aid in the discovery.
|
429
|
+
#
|
430
|
+
# @return [ Symbol ] The inverse name.
|
431
|
+
#
|
432
|
+
# @since 2.0.0.rc.1
|
433
|
+
def inverse(other = nil)
|
434
|
+
invs = inverses(other)
|
435
|
+
invs.first if invs.count == 1
|
436
|
+
end
|
437
|
+
|
438
|
+
# Returns the inverse_class_name option of the relation.
|
439
|
+
#
|
440
|
+
# @example Get the inverse_class_name option.
|
441
|
+
# metadata.inverse_class_name
|
442
|
+
#
|
443
|
+
# @return [ true, false ] The inverse_class_name option.
|
444
|
+
#
|
445
|
+
# @since 2.1.0
|
446
|
+
def inverse_class_name
|
447
|
+
self[:inverse_class_name]
|
448
|
+
end
|
449
|
+
|
450
|
+
# Returns the if the inverse class name option exists.
|
451
|
+
#
|
452
|
+
# @example Is an inverse class name defined?
|
453
|
+
# metadata.inverse_class_name?
|
454
|
+
#
|
455
|
+
# @return [ true, false ] If the inverse if defined.
|
456
|
+
#
|
457
|
+
# @since 2.1.0
|
458
|
+
def inverse_class_name?
|
459
|
+
!!inverse_class_name
|
460
|
+
end
|
461
|
+
|
462
|
+
# Used for relational many to many only. This determines the name of the
|
463
|
+
# foreign key field on the inverse side of the relation, since in this
|
464
|
+
# case there are keys on both sides.
|
465
|
+
#
|
466
|
+
# @example Find the inverse foreign key
|
467
|
+
# metadata.inverse_foreign_key
|
468
|
+
#
|
469
|
+
# @return [ String ] The foreign key on the inverse.
|
470
|
+
#
|
471
|
+
# @since 2.0.0.rc.1
|
472
|
+
def inverse_foreign_key
|
473
|
+
@inverse_foreign_key ||= determine_inverse_foreign_key
|
474
|
+
end
|
475
|
+
|
476
|
+
# Returns the inverse class of the proxied relation.
|
477
|
+
#
|
478
|
+
# @example Get the inverse class.
|
479
|
+
# metadata.inverse_klass
|
480
|
+
#
|
481
|
+
# @return [ Class ] The class of the inverse of the relation.
|
482
|
+
#
|
483
|
+
# @since 2.0.0.rc.1
|
484
|
+
def inverse_klass
|
485
|
+
@inverse_klass ||= inverse_class_name.constantize
|
486
|
+
end
|
487
|
+
|
488
|
+
# Get the metadata for the inverse relation.
|
489
|
+
#
|
490
|
+
# @example Get the inverse metadata.
|
491
|
+
# metadata.inverse_metadata(doc)
|
492
|
+
#
|
493
|
+
# @param [ Document, Class ] object The document or class.
|
494
|
+
#
|
495
|
+
# @return [ Metadata ] The inverse metadata.
|
496
|
+
#
|
497
|
+
# @since 2.1.0
|
498
|
+
def inverse_metadata(object)
|
499
|
+
object.reflect_on_association(inverse(object))
|
500
|
+
end
|
501
|
+
|
502
|
+
# Returns the inverse_of option of the relation.
|
503
|
+
#
|
504
|
+
# @example Get the inverse_of option.
|
505
|
+
# metadata.inverse_of
|
506
|
+
#
|
507
|
+
# @return [ true, false ] The inverse_of option.
|
508
|
+
#
|
509
|
+
# @since 2.1.0
|
510
|
+
def inverse_of
|
511
|
+
self[:inverse_of]
|
512
|
+
end
|
513
|
+
|
514
|
+
# Does the metadata have a inverse_of option?
|
515
|
+
#
|
516
|
+
# @example Is an inverse_of defined?
|
517
|
+
# metadata.inverse_of?
|
518
|
+
#
|
519
|
+
# @return [ true, false ] If the relation has an inverse_of defined.
|
520
|
+
#
|
521
|
+
# @since 2.1.0
|
522
|
+
def inverse_of?
|
523
|
+
!!inverse_of
|
524
|
+
end
|
525
|
+
|
526
|
+
# Returns the setter for the inverse side of the relation.
|
527
|
+
#
|
528
|
+
# @example Get the inverse setter.
|
529
|
+
# metadata.inverse_setter
|
530
|
+
#
|
531
|
+
# @param [ Document ] other A document to aid in the discovery.
|
532
|
+
#
|
533
|
+
# @return [ String ] The inverse setter name.
|
534
|
+
#
|
535
|
+
# @since 2.0.0.rc.1
|
536
|
+
def inverse_setter(other = nil)
|
537
|
+
inverse(other).__setter__
|
538
|
+
end
|
539
|
+
|
540
|
+
# Returns the name of the field in which to store the name of the class
|
541
|
+
# for the polymorphic relation.
|
542
|
+
#
|
543
|
+
# @example Get the name of the field.
|
544
|
+
# metadata.inverse_type
|
545
|
+
#
|
546
|
+
# @return [ String ] The name of the field for storing the type.
|
547
|
+
#
|
548
|
+
# @since 2.0.0.rc.1
|
549
|
+
def inverse_type
|
550
|
+
@inverse_type ||= determine_inverse_for(:type)
|
551
|
+
end
|
552
|
+
|
553
|
+
# Gets the setter for the field that sets the type of document on a
|
554
|
+
# polymorphic relation.
|
555
|
+
#
|
556
|
+
# @example Get the inverse type setter.
|
557
|
+
# metadata.inverse_type_setter
|
558
|
+
#
|
559
|
+
# @return [ String ] The name of the setter.
|
560
|
+
#
|
561
|
+
# @since 2.0.0.rc.1
|
562
|
+
def inverse_type_setter
|
563
|
+
@inverse_type_setter ||= inverse_type.__setter__
|
564
|
+
end
|
565
|
+
|
566
|
+
# This returns the key that is to be used to grab the attributes for the
|
567
|
+
# relation or the foreign key or id that a referenced relation will use
|
568
|
+
# to query for the object.
|
569
|
+
#
|
570
|
+
# @example Get the lookup key.
|
571
|
+
# metadata.key
|
572
|
+
#
|
573
|
+
# @return [ String ] The association name, foreign key name, or _id.
|
574
|
+
#
|
575
|
+
# @since 2.0.0.rc.1
|
576
|
+
def key
|
577
|
+
@key ||= determine_key
|
578
|
+
end
|
579
|
+
|
580
|
+
# Returns the class of the proxied relation.
|
581
|
+
#
|
582
|
+
# @example Get the class.
|
583
|
+
# metadata.klass
|
584
|
+
#
|
585
|
+
# @return [ Class ] The class of the relation.
|
586
|
+
#
|
587
|
+
# @since 2.0.0.rc.1
|
588
|
+
def klass
|
589
|
+
@klass ||= class_name.constantize
|
590
|
+
end
|
591
|
+
|
592
|
+
# Is this metadata representing a one to many or many to many relation?
|
593
|
+
#
|
594
|
+
# @example Is the relation a many?
|
595
|
+
# metadata.many?
|
596
|
+
#
|
597
|
+
# @return [ true, false ] If the relation is a many.
|
598
|
+
#
|
599
|
+
# @since 2.1.6
|
600
|
+
def many?
|
601
|
+
@many ||= (relation.macro.to_s =~ /many/)
|
602
|
+
end
|
603
|
+
|
604
|
+
# Returns the macro for the relation of this metadata.
|
605
|
+
#
|
606
|
+
# @example Get the macro.
|
607
|
+
# metadata.macro
|
608
|
+
#
|
609
|
+
# @return [ Symbol ] The macro.
|
610
|
+
#
|
611
|
+
# @since 2.0.0.rc.1
|
612
|
+
def macro
|
613
|
+
relation.macro
|
614
|
+
end
|
615
|
+
|
616
|
+
# Get the name associated with this metadata.
|
617
|
+
#
|
618
|
+
# @example Get the name.
|
619
|
+
# metadata.name
|
620
|
+
#
|
621
|
+
# @return [ Symbol ] The name.
|
622
|
+
#
|
623
|
+
# @since 2.1.0
|
624
|
+
def name
|
625
|
+
self[:name]
|
626
|
+
end
|
627
|
+
|
628
|
+
# Is the name defined?
|
629
|
+
#
|
630
|
+
# @example Is the name defined?
|
631
|
+
# metadata.name?
|
632
|
+
#
|
633
|
+
# @return [ true, false ] If the name is defined.
|
634
|
+
#
|
635
|
+
# @since 2.1.0
|
636
|
+
def name?
|
637
|
+
!!name
|
638
|
+
end
|
639
|
+
|
640
|
+
# Does the relation have a destructive dependent option specified. This
|
641
|
+
# is true for :dependent => :delete and :dependent => :destroy.
|
642
|
+
#
|
643
|
+
# @example Is the relation destructive?
|
644
|
+
# metadata.destructive?
|
645
|
+
#
|
646
|
+
# @return [ true, false ] If the relation is destructive.
|
647
|
+
#
|
648
|
+
# @since 2.1.0
|
649
|
+
def destructive?
|
650
|
+
@destructive ||= (dependent == :delete || dependent == :destroy)
|
651
|
+
end
|
652
|
+
|
653
|
+
# Gets a relation nested builder associated with the relation this metadata
|
654
|
+
# is for. Nested builders are used in conjunction with nested attributes.
|
655
|
+
#
|
656
|
+
# @example Get the nested builder.
|
657
|
+
# metadata.nested_builder(attributes, options)
|
658
|
+
#
|
659
|
+
# @param [ Hash ] attributes The attributes to build the relation with.
|
660
|
+
# @param [ Hash ] options Options for the nested builder.
|
661
|
+
#
|
662
|
+
# @return [ NestedBuilder ] The nested builder for the relation.
|
663
|
+
#
|
664
|
+
# @since 2.0.0.rc.1
|
665
|
+
def nested_builder(attributes, options)
|
666
|
+
relation.nested_builder(self, attributes, options)
|
667
|
+
end
|
668
|
+
|
669
|
+
# Get the path calculator for the supplied document.
|
670
|
+
#
|
671
|
+
# @example Get the path calculator.
|
672
|
+
# metadata.path(document)
|
673
|
+
#
|
674
|
+
# @param [ Document ] document The document to calculate on.
|
675
|
+
#
|
676
|
+
# @return [ Object ] The atomic path calculator.
|
677
|
+
#
|
678
|
+
# @since 2.1.0
|
679
|
+
def path(document)
|
680
|
+
relation.path(document)
|
681
|
+
end
|
682
|
+
|
683
|
+
# Returns true if the relation is polymorphic.
|
684
|
+
#
|
685
|
+
# @example Is the relation polymorphic?
|
686
|
+
# metadata.polymorphic?
|
687
|
+
#
|
688
|
+
# @return [ true, false ] True if the relation is polymorphic, false if not.
|
689
|
+
#
|
690
|
+
# @since 2.0.0.rc.1
|
691
|
+
def polymorphic?
|
692
|
+
@polymorphic ||= (!!self[:as] || !!self[:polymorphic])
|
693
|
+
end
|
694
|
+
|
695
|
+
# Get the primary key field for finding the related document.
|
696
|
+
#
|
697
|
+
# @example Get the primary key.
|
698
|
+
# metadata.primary_key
|
699
|
+
#
|
700
|
+
# @return [ String ] The primary key field.
|
701
|
+
#
|
702
|
+
# @since 3.1.0
|
703
|
+
def primary_key
|
704
|
+
@primary_key ||= (self[:primary_key] || "_id").to_s
|
705
|
+
end
|
706
|
+
|
707
|
+
# Get the relation associated with this metadata.
|
708
|
+
#
|
709
|
+
# @example Get the relation.
|
710
|
+
# metadata.relation
|
711
|
+
#
|
712
|
+
# @return [ Proxy ] The relation proxy class.
|
713
|
+
#
|
714
|
+
# @since 2.1.0
|
715
|
+
def relation
|
716
|
+
self[:relation]
|
717
|
+
end
|
718
|
+
|
719
|
+
# Gets the method name used to set this relation.
|
720
|
+
#
|
721
|
+
# @example Get the setter.
|
722
|
+
# metadata = Metadata.new(:name => :person)
|
723
|
+
# metadata.setter # => "person="
|
724
|
+
#
|
725
|
+
# @return [ String ] The name plus "=".
|
726
|
+
#
|
727
|
+
# @since 2.0.0.rc.1
|
728
|
+
def setter
|
729
|
+
@setter ||= "#{name}="
|
730
|
+
end
|
731
|
+
|
732
|
+
# Returns the name of the field in which to store the name of the class
|
733
|
+
# for the polymorphic relation.
|
734
|
+
#
|
735
|
+
# @example Get the name of the field.
|
736
|
+
# metadata.inverse_type
|
737
|
+
#
|
738
|
+
# @return [ String ] The name of the field for storing the type.
|
739
|
+
#
|
740
|
+
# @since 2.0.0.rc.1
|
741
|
+
def type
|
742
|
+
@type ||= polymorphic? ? "#{as}_type" : nil
|
743
|
+
end
|
744
|
+
|
745
|
+
# Gets the setter for the field that sets the type of document on a
|
746
|
+
# polymorphic relation.
|
747
|
+
#
|
748
|
+
# @example Get the inverse type setter.
|
749
|
+
# metadata.inverse_type_setter
|
750
|
+
#
|
751
|
+
# @return [ String ] The name of the setter.
|
752
|
+
#
|
753
|
+
# @since 2.0.0.rc.1
|
754
|
+
def type_setter
|
755
|
+
@type_setter ||= type.__setter__
|
756
|
+
end
|
757
|
+
|
758
|
+
|
759
|
+
# Key where embedded document is save.
|
760
|
+
# By default is the name of relation
|
761
|
+
#
|
762
|
+
# @return [ String ] the name of key where save
|
763
|
+
#
|
764
|
+
# @since 3.0.0
|
765
|
+
def store_as
|
766
|
+
@store_as ||= (self[:store_as].try(:to_s) || name.to_s)
|
767
|
+
end
|
768
|
+
|
769
|
+
# Are we validating this relation automatically?
|
770
|
+
#
|
771
|
+
# @example Is automatic validation on?
|
772
|
+
# metadata.validate?
|
773
|
+
#
|
774
|
+
# @return [ true, false ] True unless explictly set to false.
|
775
|
+
#
|
776
|
+
# @since 2.0.0.rc.1
|
777
|
+
def validate?
|
778
|
+
unless self[:validate].nil?
|
779
|
+
self[:validate]
|
780
|
+
else
|
781
|
+
self[:validate] = relation.validation_default
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
# Returns the metadata itself. Here for compatibility with Rails
|
786
|
+
# association metadata.
|
787
|
+
#
|
788
|
+
# @example Get the options.
|
789
|
+
# metadata.options
|
790
|
+
#
|
791
|
+
# @return [ Metadata ] self.
|
792
|
+
#
|
793
|
+
# @since 2.4.6
|
794
|
+
def options
|
795
|
+
self
|
796
|
+
end
|
797
|
+
|
798
|
+
# Returns default order for this association.
|
799
|
+
#
|
800
|
+
# @example Get default order
|
801
|
+
# metadata.order
|
802
|
+
#
|
803
|
+
# @return [ Criterion::Complex, nil] nil if doesn't set
|
804
|
+
#
|
805
|
+
# @since 2.1.0
|
806
|
+
def order
|
807
|
+
self[:order]
|
808
|
+
end
|
809
|
+
|
810
|
+
# Is a default order set?
|
811
|
+
#
|
812
|
+
# @example Is the order set?
|
813
|
+
# metadata.order?
|
814
|
+
#
|
815
|
+
# @return [ true, false ] If the order is set.
|
816
|
+
#
|
817
|
+
# @since 2.1.0
|
818
|
+
def order?
|
819
|
+
!!order
|
820
|
+
end
|
821
|
+
|
822
|
+
# Is this relation touchable?
|
823
|
+
#
|
824
|
+
# @example Is the relation touchable?
|
825
|
+
# metadata.touchable?
|
826
|
+
#
|
827
|
+
# @return [ true, false ] If the relation can be touched.
|
828
|
+
#
|
829
|
+
# @since 3.0.0
|
830
|
+
def touchable?
|
831
|
+
!!self[:touch]
|
832
|
+
end
|
833
|
+
|
834
|
+
# Returns the metadata class types.
|
835
|
+
#
|
836
|
+
# @example Get the relation class types.
|
837
|
+
# metadata.type_relation
|
838
|
+
#
|
839
|
+
# @return [ Hash ] The hash with relation class types.
|
840
|
+
#
|
841
|
+
# @since 3.1.0
|
842
|
+
def type_relation
|
843
|
+
{ _type: { "$in" => klass._types }}
|
844
|
+
end
|
845
|
+
|
846
|
+
private
|
847
|
+
|
848
|
+
# Returns the class name for the relation.
|
849
|
+
#
|
850
|
+
# @example Get the class name.
|
851
|
+
# metadata.classify
|
852
|
+
#
|
853
|
+
# @return [ String ] The classified name.
|
854
|
+
#
|
855
|
+
# @since 2.0.0.rc.1
|
856
|
+
def classify
|
857
|
+
@classify ||= "#{find_module}::#{name.to_s.classify}"
|
858
|
+
end
|
859
|
+
|
860
|
+
# Get the name for the inverse field.
|
861
|
+
#
|
862
|
+
# @api private
|
863
|
+
#
|
864
|
+
# @example Get the inverse field name.
|
865
|
+
# metadata.determine_inverse_for(:type)
|
866
|
+
#
|
867
|
+
# @param [ Symbol ] field The inverse field name.
|
868
|
+
#
|
869
|
+
# @return [ String ] The name of the field.
|
870
|
+
#
|
871
|
+
# @since 3.0.0
|
872
|
+
def determine_inverse_for(field)
|
873
|
+
relation.stores_foreign_key? && polymorphic? ? "#{name}_#{field}" : nil
|
874
|
+
end
|
875
|
+
|
876
|
+
# Deterimene the inverses that can be memoized.
|
877
|
+
#
|
878
|
+
# @api private
|
879
|
+
#
|
880
|
+
# @example Determin the inverses.
|
881
|
+
# metadata.determine_inverses
|
882
|
+
#
|
883
|
+
# @return [ Array<Symbol> ] The inverses.
|
884
|
+
#
|
885
|
+
# @since 3.0.0
|
886
|
+
def determine_inverses
|
887
|
+
return [ inverse_of ] if has_key?(:inverse_of)
|
888
|
+
return [ as ] if has_key?(:as)
|
889
|
+
return [ cyclic_inverse ] if self[:cyclic]
|
890
|
+
[ inverse_relation ]
|
891
|
+
end
|
892
|
+
|
893
|
+
# Find the module the class with the specific name is in.
|
894
|
+
# This is done by starting at the inverse_class_name's
|
895
|
+
# module and stepping down to see where it is defined.
|
896
|
+
#
|
897
|
+
# @api private
|
898
|
+
#
|
899
|
+
# @example Find the module.
|
900
|
+
# metadata.find_module
|
901
|
+
#
|
902
|
+
# @return [ String ] The module.
|
903
|
+
#
|
904
|
+
# @since 3.0.0
|
905
|
+
def find_module
|
906
|
+
if inverse_class_name.present?
|
907
|
+
parts = inverse_class_name.split('::')
|
908
|
+
modules = parts.size.times.map { |i| parts.first(i).join('::') }.reverse
|
909
|
+
find_from_parts(modules)
|
910
|
+
end
|
911
|
+
end
|
912
|
+
|
913
|
+
# Find the modules from a reversed list.
|
914
|
+
#
|
915
|
+
# @api private
|
916
|
+
#
|
917
|
+
# @example Find the module from the parts.
|
918
|
+
# metadata.find_from_parts([ "Namespace", "Module" ])
|
919
|
+
#
|
920
|
+
# @param [ Array<String> ] The modules.
|
921
|
+
#
|
922
|
+
# @return [ String ] The matching module.
|
923
|
+
#
|
924
|
+
# @since 3.0.0
|
925
|
+
def find_from_parts(modules)
|
926
|
+
modules.find do |mod|
|
927
|
+
ActiveSupport::Inflector.constantize(mod).constants.include?(
|
928
|
+
name.to_s.classify.to_sym
|
929
|
+
)
|
930
|
+
end
|
931
|
+
end
|
932
|
+
|
933
|
+
# Get the name of the inverse relation in a cyclic relation.
|
934
|
+
#
|
935
|
+
# @example Get the cyclic inverse name.
|
936
|
+
#
|
937
|
+
# class Role
|
938
|
+
# include Mongoid::Document
|
939
|
+
# embedded_in :parent_role, :cyclic => true
|
940
|
+
# embeds_many :child_roles, :cyclic => true
|
941
|
+
# end
|
942
|
+
#
|
943
|
+
# metadata = Metadata.new(:name => :parent_role)
|
944
|
+
# metadata.cyclic_inverse # => "child_roles"
|
945
|
+
#
|
946
|
+
# @return [ String ] The cyclic inverse name.
|
947
|
+
#
|
948
|
+
# @since 2.0.0.rc.1
|
949
|
+
def cyclic_inverse
|
950
|
+
@cyclic_inverse ||= determine_cyclic_inverse
|
951
|
+
end
|
952
|
+
|
953
|
+
# Determine the cyclic inverse. Performance improvement with the
|
954
|
+
# memoization.
|
955
|
+
#
|
956
|
+
# @example Determine the inverse.
|
957
|
+
# metadata.determine_cyclic_inverse
|
958
|
+
#
|
959
|
+
# @return [ String ] The cyclic inverse name.
|
960
|
+
#
|
961
|
+
# @since 2.0.0.rc.1
|
962
|
+
def determine_cyclic_inverse
|
963
|
+
underscored = class_name.demodulize.underscore
|
964
|
+
klass.relations.each_pair do |key, meta|
|
965
|
+
if key =~ /#{underscored.singularize}|#{underscored.pluralize}/ &&
|
966
|
+
meta.relation != relation
|
967
|
+
return key.to_sym
|
968
|
+
end
|
969
|
+
end
|
970
|
+
end
|
971
|
+
|
972
|
+
# Determine the value for the relation's foreign key. Performance
|
973
|
+
# improvement.
|
974
|
+
#
|
975
|
+
# @example Determine the foreign key.
|
976
|
+
# metadata.determine_foreign_key
|
977
|
+
#
|
978
|
+
# @return [ String ] The foreign key.
|
979
|
+
#
|
980
|
+
# @since 2.0.0.rc.1
|
981
|
+
def determine_foreign_key
|
982
|
+
return self[:foreign_key].to_s if self[:foreign_key]
|
983
|
+
suffix = relation.foreign_key_suffix
|
984
|
+
if relation.stores_foreign_key?
|
985
|
+
relation.foreign_key(name)
|
986
|
+
else
|
987
|
+
if polymorphic?
|
988
|
+
"#{self[:as]}#{suffix}"
|
989
|
+
else
|
990
|
+
inverse_of ? "#{inverse_of}#{suffix}" : inverse_class_name.foreign_key
|
991
|
+
end
|
992
|
+
end
|
993
|
+
end
|
994
|
+
|
995
|
+
# Determine the inverse foreign key of the relation.
|
996
|
+
#
|
997
|
+
# @example Determine the inverse foreign key.
|
998
|
+
# metadata.determine_inverse_foreign_key
|
999
|
+
#
|
1000
|
+
# @return [ String ] The inverse.
|
1001
|
+
#
|
1002
|
+
# @since 2.3.2
|
1003
|
+
def determine_inverse_foreign_key
|
1004
|
+
if has_key?(:inverse_of)
|
1005
|
+
inverse_of ? "#{inverse_of.to_s.singularize}#{relation.foreign_key_suffix}" : nil
|
1006
|
+
else
|
1007
|
+
"#{inverse_class_name.demodulize.underscore}#{relation.foreign_key_suffix}"
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
# Determine the inverse relation. Memoizing #inverse_relation and adding
|
1012
|
+
# this method dropped 5 seconds off the test suite as a performance
|
1013
|
+
# improvement.
|
1014
|
+
#
|
1015
|
+
# @example Determine the inverse.
|
1016
|
+
# metadata.determine_inverse_relation
|
1017
|
+
#
|
1018
|
+
# @return [ Symbol ] The name of the inverse.
|
1019
|
+
#
|
1020
|
+
# @since 2.0.0.rc.1
|
1021
|
+
def determine_inverse_relation
|
1022
|
+
default = foreign_key_match || klass.relations[inverse_klass.name.underscore]
|
1023
|
+
return default.name if default
|
1024
|
+
names = inverse_relation_candidate_names
|
1025
|
+
if names.size > 1
|
1026
|
+
raise Errors::AmbiguousRelationship.new(klass, inverse_klass, name, names)
|
1027
|
+
end
|
1028
|
+
names.first
|
1029
|
+
end
|
1030
|
+
|
1031
|
+
# Return metadata where the foreign key matches the foreign key on this
|
1032
|
+
# relation.
|
1033
|
+
#
|
1034
|
+
# @api private
|
1035
|
+
#
|
1036
|
+
# @example Return a foreign key match.
|
1037
|
+
# meta.foreign_key_match
|
1038
|
+
#
|
1039
|
+
# @return [ Metadata ] A match, if any.
|
1040
|
+
#
|
1041
|
+
# @since 2.4.11
|
1042
|
+
def foreign_key_match
|
1043
|
+
if fk = self[:foreign_key]
|
1044
|
+
relations_metadata.detect do |meta|
|
1045
|
+
fk == meta.foreign_key if meta.stores_foreign_key?
|
1046
|
+
end
|
1047
|
+
end
|
1048
|
+
end
|
1049
|
+
|
1050
|
+
# Get the inverse relation candidates.
|
1051
|
+
#
|
1052
|
+
# @api private
|
1053
|
+
#
|
1054
|
+
# @example Get the inverse relation candidates.
|
1055
|
+
# metadata.inverse_relation_candidates
|
1056
|
+
#
|
1057
|
+
# @return [ Array<Metdata> ] The candidates.
|
1058
|
+
#
|
1059
|
+
# @since 3.0.0
|
1060
|
+
def inverse_relation_candidates
|
1061
|
+
relations_metadata.select do |meta|
|
1062
|
+
next if meta.name == name
|
1063
|
+
meta.class_name == inverse_class_name
|
1064
|
+
end
|
1065
|
+
end
|
1066
|
+
|
1067
|
+
# Get the candidates for inverse relations.
|
1068
|
+
#
|
1069
|
+
# @api private
|
1070
|
+
#
|
1071
|
+
# @example Get the candidates.
|
1072
|
+
# metadata.inverse_relation_candidates
|
1073
|
+
#
|
1074
|
+
# @return [ Array<Symbol> ] The candidates.
|
1075
|
+
#
|
1076
|
+
# @since 3.0.0
|
1077
|
+
def inverse_relation_candidate_names
|
1078
|
+
@candidate_names ||= inverse_relation_candidates.map(&:name)
|
1079
|
+
end
|
1080
|
+
|
1081
|
+
# Determine the key for the relation in the attributes.
|
1082
|
+
#
|
1083
|
+
# @example Get the key.
|
1084
|
+
# metadata.determine_key
|
1085
|
+
#
|
1086
|
+
# @return [ String ] The key in the attributes.
|
1087
|
+
#
|
1088
|
+
# @since 2.0.0.rc.1
|
1089
|
+
def determine_key
|
1090
|
+
return store_as.to_s if relation.embedded?
|
1091
|
+
relation.stores_foreign_key? ? foreign_key : primary_key
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
# Determine the name of the inverse relation.
|
1095
|
+
#
|
1096
|
+
# @example Get the inverse name.
|
1097
|
+
# metadata.inverse_relation
|
1098
|
+
#
|
1099
|
+
# @return [ Symbol ] The name of the inverse relation.
|
1100
|
+
#
|
1101
|
+
# @since 2.0.0.rc.1
|
1102
|
+
def inverse_relation
|
1103
|
+
@inverse_relation ||= determine_inverse_relation
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
# Infer the name of the inverse relation from the class.
|
1107
|
+
#
|
1108
|
+
# @example Get the inverse name
|
1109
|
+
# metadata.inverse_name
|
1110
|
+
#
|
1111
|
+
# @return [ String ] The inverse class name underscored.
|
1112
|
+
#
|
1113
|
+
# @since 2.0.0.rc.1
|
1114
|
+
def inverse_name
|
1115
|
+
@inverse_name ||= inverse_klass.name.underscore
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
# For polymorphic children, we need to figure out the inverse from the
|
1119
|
+
# actual instance on the other side, since we cannot know the exact class
|
1120
|
+
# name to infer it from at load time.
|
1121
|
+
#
|
1122
|
+
# @example Find the inverses.
|
1123
|
+
# metadata.lookup_inverses(other)
|
1124
|
+
#
|
1125
|
+
# @param [ Document ] : The inverse document.
|
1126
|
+
#
|
1127
|
+
# @return [ Array<String> ] The inverse names.
|
1128
|
+
def lookup_inverses(other)
|
1129
|
+
return [ inverse_of ] if inverse_of
|
1130
|
+
if other
|
1131
|
+
matches = []
|
1132
|
+
other.class.relations.values.each do |meta|
|
1133
|
+
if meta.as == name && meta.class_name == inverse_class_name
|
1134
|
+
matches.push(meta.name)
|
1135
|
+
end
|
1136
|
+
end
|
1137
|
+
matches
|
1138
|
+
end
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
# For polymorphic children, we need to figure out the inverse from the
|
1142
|
+
# actual instance on the other side, since we cannot know the exact class
|
1143
|
+
# name to infer it from at load time.
|
1144
|
+
#
|
1145
|
+
# @example Find the inverse.
|
1146
|
+
# metadata.lookup_inverse(other)
|
1147
|
+
#
|
1148
|
+
# @param [ Document ] : The inverse document.
|
1149
|
+
#
|
1150
|
+
# @return [ String ] The inverse name.
|
1151
|
+
#
|
1152
|
+
# @since 2.0.0.rc.1
|
1153
|
+
def lookup_inverse(other)
|
1154
|
+
if invs = lookup_inverses(other) && invs.count == 1
|
1155
|
+
invs.first
|
1156
|
+
end
|
1157
|
+
end
|
1158
|
+
|
1159
|
+
# Get the relation metadata only.
|
1160
|
+
#
|
1161
|
+
# @api private
|
1162
|
+
#
|
1163
|
+
# @example Get the relation metadata.
|
1164
|
+
# metadata.relations_metadata
|
1165
|
+
#
|
1166
|
+
# @return [ Array<Metadata> ] The metadata.
|
1167
|
+
#
|
1168
|
+
# @since 3.0.0
|
1169
|
+
def relations_metadata
|
1170
|
+
klass.relations.values
|
1171
|
+
end
|
1172
|
+
end
|
1173
|
+
end
|
1174
|
+
end
|