mongoid 3.1.6 → 4.0.2
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/CHANGELOG.md +479 -8
- data/README.md +10 -7
- data/lib/config/locales/en.yml +34 -20
- data/lib/mongoid.rb +10 -76
- data/lib/mongoid/atomic.rb +3 -14
- data/lib/mongoid/atomic/paths/embedded.rb +0 -30
- data/lib/mongoid/atomic/paths/embedded/many.rb +1 -1
- data/lib/mongoid/atomic/paths/embedded/one.rb +1 -1
- data/lib/mongoid/atomic/paths/root.rb +0 -13
- data/lib/mongoid/attributes.rb +65 -101
- data/lib/mongoid/attributes/dynamic.rb +154 -0
- data/lib/mongoid/attributes/nested.rb +82 -0
- data/lib/mongoid/attributes/processing.rb +13 -66
- data/lib/mongoid/{dirty.rb → changeable.rb} +32 -2
- data/lib/mongoid/composable.rb +105 -0
- data/lib/mongoid/config.rb +3 -9
- data/lib/mongoid/config/options.rb +1 -1
- data/lib/mongoid/contextual.rb +2 -0
- data/lib/mongoid/contextual/aggregable/memory.rb +2 -2
- data/lib/mongoid/contextual/aggregable/mongo.rb +7 -9
- data/lib/mongoid/contextual/atomic.rb +53 -53
- data/lib/mongoid/contextual/geo_near.rb +1 -1
- data/lib/mongoid/contextual/map_reduce.rb +4 -2
- data/lib/mongoid/contextual/memory.rb +23 -11
- data/lib/mongoid/contextual/mongo.rb +75 -57
- data/lib/mongoid/contextual/none.rb +90 -0
- data/lib/mongoid/contextual/text_search.rb +178 -0
- data/lib/mongoid/copyable.rb +2 -3
- data/lib/mongoid/criteria.rb +39 -34
- data/lib/mongoid/criteria/#findable.rb# +141 -0
- data/lib/mongoid/{criterion → criteria}/findable.rb +7 -47
- data/lib/mongoid/{criterion/inspection.rb → criteria/inspectable.rb} +2 -2
- data/lib/mongoid/{criterion → criteria}/marshalable.rb +3 -1
- data/lib/mongoid/{criterion → criteria}/modifiable.rb +28 -8
- data/lib/mongoid/criteria/permission.rb +70 -0
- data/lib/mongoid/{criterion/scoping.rb → criteria/scopable.rb} +2 -2
- data/lib/mongoid/document.rb +39 -24
- data/lib/mongoid/errors.rb +4 -1
- data/lib/mongoid/errors/document_not_destroyed.rb +25 -0
- data/lib/mongoid/errors/document_not_found.rb +2 -1
- data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
- data/lib/mongoid/errors/invalid_storage_parent.rb +26 -0
- data/lib/mongoid/errors/invalid_value.rb +16 -0
- data/lib/mongoid/errors/mongoid_error.rb +1 -1
- data/lib/mongoid/errors/readonly_document.rb +24 -0
- data/lib/mongoid/extensions.rb +15 -7
- data/lib/mongoid/extensions/array.rb +3 -3
- data/lib/mongoid/extensions/big_decimal.rb +1 -1
- data/lib/mongoid/extensions/boolean.rb +15 -17
- data/lib/mongoid/extensions/date.rb +1 -1
- data/lib/mongoid/extensions/date_time.rb +3 -3
- data/lib/mongoid/extensions/float.rb +2 -1
- data/lib/mongoid/extensions/hash.rb +3 -3
- data/lib/mongoid/extensions/integer.rb +1 -1
- data/lib/mongoid/extensions/object.rb +7 -7
- data/lib/mongoid/extensions/object_id.rb +5 -5
- data/lib/mongoid/extensions/range.rb +9 -3
- data/lib/mongoid/extensions/regexp.rb +1 -1
- data/lib/mongoid/extensions/set.rb +1 -1
- data/lib/mongoid/extensions/string.rb +6 -18
- data/lib/mongoid/extensions/symbol.rb +1 -1
- data/lib/mongoid/extensions/time.rb +3 -3
- data/lib/mongoid/extensions/time_with_zone.rb +1 -1
- data/lib/mongoid/factory.rb +8 -6
- data/lib/mongoid/fields.rb +41 -8
- data/lib/mongoid/fields/foreign_key.rb +3 -3
- data/lib/mongoid/fields/localized.rb +1 -1
- data/lib/mongoid/fields/standard.rb +5 -17
- data/lib/mongoid/fields/validators/macro.rb +15 -5
- data/lib/mongoid/{finders.rb → findable.rb} +35 -7
- data/lib/mongoid/{indexes.rb → indexable.rb} +50 -55
- data/lib/mongoid/indexable/specification.rb +104 -0
- data/lib/mongoid/{indexes → indexable}/validators/options.rb +2 -1
- data/lib/mongoid/{inspection.rb → inspectable.rb} +15 -11
- data/lib/mongoid/{callbacks.rb → interceptable.rb} +30 -62
- data/lib/mongoid/log_subscriber.rb +55 -0
- data/lib/mongoid/matchable.rb +152 -0
- data/lib/mongoid/{matchers → matchable}/all.rb +1 -1
- data/lib/mongoid/{matchers → matchable}/and.rb +2 -2
- data/lib/mongoid/{matchers → matchable}/default.rb +1 -1
- data/lib/mongoid/{matchers → matchable}/exists.rb +1 -1
- data/lib/mongoid/{matchers → matchable}/gt.rb +1 -1
- data/lib/mongoid/{matchers → matchable}/gte.rb +1 -1
- data/lib/mongoid/{matchers → matchable}/in.rb +2 -2
- data/lib/mongoid/{matchers → matchable}/lt.rb +1 -1
- data/lib/mongoid/{matchers → matchable}/lte.rb +1 -1
- data/lib/mongoid/{matchers → matchable}/ne.rb +2 -2
- data/lib/mongoid/{matchers → matchable}/nin.rb +3 -2
- data/lib/mongoid/{matchers → matchable}/or.rb +2 -2
- data/lib/mongoid/{matchers → matchable}/size.rb +1 -1
- data/lib/mongoid/persistable.rb +216 -0
- data/lib/mongoid/persistable/creatable.rb +189 -0
- data/lib/mongoid/persistable/deletable.rb +149 -0
- data/lib/mongoid/persistable/destroyable.rb +60 -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 +153 -0
- data/lib/mongoid/persistable/upsertable.rb +55 -0
- data/lib/mongoid/positional.rb +71 -0
- data/lib/mongoid/query_cache.rb +255 -0
- data/lib/mongoid/railtie.rb +34 -60
- data/lib/mongoid/railties/database.rake +9 -25
- data/lib/mongoid/relations.rb +11 -25
- data/lib/mongoid/relations/accessors.rb +15 -51
- data/lib/mongoid/relations/auto_save.rb +15 -36
- data/lib/mongoid/relations/binding.rb +2 -25
- data/lib/mongoid/relations/bindings/embedded/in.rb +1 -1
- data/lib/mongoid/relations/bindings/embedded/many.rb +1 -3
- data/lib/mongoid/relations/bindings/referenced/in.rb +3 -8
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -2
- data/lib/mongoid/relations/builder.rb +1 -1
- data/lib/mongoid/relations/builders.rb +2 -2
- data/lib/mongoid/relations/builders/embedded/one.rb +1 -1
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +10 -13
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +5 -6
- data/lib/mongoid/relations/builders/referenced/in.rb +1 -1
- data/lib/mongoid/relations/builders/referenced/many.rb +1 -2
- data/lib/mongoid/relations/builders/referenced/many_to_many.rb +1 -2
- data/lib/mongoid/relations/builders/referenced/one.rb +1 -1
- data/lib/mongoid/relations/cascading.rb +3 -5
- data/lib/mongoid/relations/constraint.rb +1 -1
- data/lib/mongoid/relations/conversions.rb +1 -1
- data/lib/mongoid/relations/counter_cache.rb +39 -15
- data/lib/mongoid/relations/eager.rb +46 -0
- data/lib/mongoid/relations/eager/base.rb +149 -0
- data/lib/mongoid/relations/eager/belongs_to.rb +31 -0
- data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +47 -0
- data/lib/mongoid/relations/eager/has_many.rb +38 -0
- data/lib/mongoid/relations/eager/has_one.rb +30 -0
- data/lib/mongoid/relations/embedded/batchable.rb +4 -5
- data/lib/mongoid/relations/embedded/in.rb +4 -4
- data/lib/mongoid/relations/embedded/many.rb +14 -32
- data/lib/mongoid/relations/embedded/one.rb +1 -1
- data/lib/mongoid/relations/macros.rb +3 -4
- data/lib/mongoid/relations/many.rb +51 -31
- data/lib/mongoid/relations/marshalable.rb +3 -3
- data/lib/mongoid/relations/metadata.rb +14 -79
- data/lib/mongoid/relations/nested_builder.rb +2 -2
- data/lib/mongoid/relations/one.rb +1 -1
- data/lib/mongoid/relations/options.rb +1 -0
- data/lib/mongoid/relations/polymorphic.rb +0 -1
- data/lib/mongoid/relations/proxy.rb +21 -41
- data/lib/mongoid/relations/referenced/in.rb +4 -20
- data/lib/mongoid/relations/referenced/many.rb +22 -35
- data/lib/mongoid/relations/referenced/many_to_many.rb +19 -42
- data/lib/mongoid/relations/referenced/one.rb +6 -25
- data/lib/mongoid/relations/synchronization.rb +4 -4
- data/lib/mongoid/relations/targets/enumerable.rb +10 -10
- data/lib/mongoid/relations/touchable.rb +34 -1
- data/lib/mongoid/{reloading.rb → reloadable.rb} +7 -5
- data/lib/mongoid/{scoping.rb → scopable.rb} +36 -36
- data/lib/mongoid/selectable.rb +59 -0
- data/lib/mongoid/{serialization.rb → serializable.rb} +11 -2
- data/lib/mongoid/sessions.rb +37 -345
- data/lib/mongoid/sessions/factory.rb +2 -0
- data/lib/mongoid/sessions/options.rb +185 -0
- data/lib/mongoid/sessions/storage_options.rb +140 -0
- data/lib/mongoid/sessions/thread_options.rb +19 -0
- data/lib/mongoid/sessions/validators/storage.rb +16 -3
- data/lib/mongoid/{sharding.rb → shardable.rb} +5 -1
- data/lib/mongoid/{state.rb → stateful.rb} +13 -1
- data/lib/mongoid/support/query_counter.rb +23 -0
- data/lib/mongoid/tasks/database.rake +31 -0
- data/lib/mongoid/tasks/database.rb +107 -0
- data/lib/mongoid/threaded.rb +26 -172
- data/lib/mongoid/threaded/lifecycle.rb +0 -28
- data/lib/mongoid/timestamps/updated/short.rb +2 -2
- data/lib/mongoid/{hierarchy.rb → traversable.rb} +15 -7
- data/lib/mongoid/{validations.rb → validatable.rb} +23 -10
- data/lib/mongoid/{validations → validatable}/associated.rb +4 -2
- data/lib/mongoid/{validations → validatable}/format.rb +1 -1
- data/lib/mongoid/{validations → validatable}/length.rb +1 -1
- data/lib/mongoid/{validations → validatable}/localizable.rb +1 -1
- data/lib/mongoid/{validations → validatable}/macros.rb +4 -3
- data/lib/mongoid/{validations → validatable}/presence.rb +1 -1
- data/lib/mongoid/{validations → validatable}/queryable.rb +1 -2
- data/lib/mongoid/{validations → validatable}/uniqueness.rb +25 -21
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +46 -25
- data/lib/rails/generators/mongoid/model/model_generator.rb +0 -1
- data/lib/rails/generators/mongoid/model/templates/model.rb.tt +0 -3
- data/lib/rails/generators/mongoid_generator.rb +3 -40
- data/lib/rails/mongoid.rb +0 -122
- data/lib/support/ruby_version.rb +1 -1
- data/spec/app/models/account.rb +2 -6
- data/spec/app/models/acolyte.rb +2 -1
- data/spec/app/models/actor.rb +0 -1
- data/spec/app/models/address.rb +8 -3
- data/spec/app/models/animal.rb +1 -1
- data/spec/app/models/appointment.rb +3 -3
- data/spec/app/models/article.rb +1 -4
- data/spec/app/models/audio.rb +5 -0
- data/spec/app/models/author.rb +0 -2
- data/spec/app/models/band.rb +3 -2
- data/spec/app/models/bar.rb +1 -0
- data/spec/app/models/book.rb +1 -0
- data/spec/app/models/building.rb +0 -2
- data/spec/app/models/building_address.rb +0 -2
- data/spec/app/models/bus.rb +1 -1
- data/spec/app/models/canvas.rb +1 -1
- data/spec/app/models/contextable_item.rb +5 -0
- data/spec/app/models/contractor.rb +0 -2
- data/spec/app/models/country_code.rb +1 -1
- data/spec/app/models/definition.rb +2 -2
- data/spec/app/models/dog.rb +1 -1
- data/spec/app/models/draft.rb +9 -0
- data/spec/app/models/dragon.rb +4 -0
- data/spec/app/models/drug.rb +1 -3
- data/spec/app/models/dungeon.rb +4 -0
- data/spec/app/models/edit.rb +5 -0
- data/spec/app/models/even.rb +7 -0
- data/spec/app/models/event.rb +1 -1
- data/spec/app/models/filesystem.rb +1 -0
- data/spec/app/models/fish.rb +0 -1
- data/spec/app/models/fruits.rb +6 -0
- data/spec/app/models/game.rb +0 -2
- data/spec/app/models/house.rb +1 -3
- data/spec/app/models/id_key.rb +6 -0
- data/spec/app/models/item.rb +1 -5
- data/spec/app/models/jar.rb +1 -1
- data/spec/app/models/label.rb +4 -4
- data/spec/app/models/line_item.rb +1 -1
- data/spec/app/models/login.rb +1 -1
- data/spec/app/models/message.rb +8 -0
- data/spec/app/models/movie.rb +1 -0
- data/spec/app/models/name.rb +3 -3
- data/spec/app/models/note.rb +3 -1
- data/spec/app/models/odd.rb +7 -0
- data/spec/app/models/oscar.rb +1 -1
- data/spec/app/models/parent_doc.rb +1 -1
- data/spec/app/models/person.rb +16 -10
- data/spec/app/models/phone.rb +1 -3
- data/spec/app/models/player.rb +3 -3
- data/spec/app/models/post.rb +5 -3
- data/spec/app/models/preference.rb +1 -1
- data/spec/app/models/quiz.rb +0 -3
- data/spec/app/models/record.rb +10 -5
- data/spec/app/models/registry.rb +1 -1
- data/spec/app/models/server.rb +1 -1
- data/spec/app/models/service.rb +3 -3
- data/spec/app/models/sound.rb +5 -0
- data/spec/app/models/symptom.rb +1 -1
- data/spec/app/models/template.rb +1 -1
- data/spec/app/models/title.rb +0 -1
- data/spec/app/models/track.rb +5 -5
- data/spec/app/models/tree.rb +3 -3
- data/spec/app/models/video.rb +1 -5
- data/spec/app/models/wiki_page.rb +2 -5
- data/spec/app/models/word.rb +3 -0
- data/spec/app/models/word_origin.rb +1 -1
- data/spec/config/mongoid.yml +7 -8
- data/spec/helpers.rb +18 -0
- data/spec/mongoid/#atomic_spec.rb# +365 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +22 -22
- data/spec/mongoid/atomic/paths/embedded/many_spec.rb +8 -49
- data/spec/mongoid/atomic/paths/embedded/one_spec.rb +7 -49
- data/spec/mongoid/atomic/paths/root_spec.rb +3 -61
- data/spec/mongoid/atomic/paths_spec.rb +19 -19
- data/spec/mongoid/atomic_spec.rb +19 -19
- data/spec/mongoid/{nested_attributes_spec.rb → attributes/nested_spec.rb} +474 -592
- data/spec/mongoid/attributes/readonly_spec.rb +58 -18
- data/spec/mongoid/attributes_spec.rb +349 -434
- data/spec/mongoid/{dirty_spec.rb → changeable_spec.rb} +203 -153
- data/spec/mongoid/{components_spec.rb → composable_spec.rb} +3 -3
- data/spec/mongoid/config/environment_spec.rb +3 -3
- data/spec/mongoid/config/options_spec.rb +6 -6
- data/spec/mongoid/config_spec.rb +24 -48
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +12 -12
- data/spec/mongoid/contextual/aggregable/mongo_spec.rb +78 -38
- data/spec/mongoid/contextual/atomic_spec.rb +60 -56
- data/spec/mongoid/contextual/find_and_modify_spec.rb +14 -14
- data/spec/mongoid/contextual/geo_near_spec.rb +22 -22
- data/spec/mongoid/contextual/map_reduce_spec.rb +27 -27
- data/spec/mongoid/contextual/memory_spec.rb +156 -94
- data/spec/mongoid/contextual/mongo_spec.rb +238 -150
- data/spec/mongoid/contextual/none_spec.rb +127 -0
- data/spec/mongoid/contextual/text_search_spec.rb +209 -0
- data/spec/mongoid/copyable_spec.rb +56 -68
- data/spec/mongoid/criteria/findable_spec.rb +991 -0
- data/spec/mongoid/{criterion/inspection_spec.rb → criteria/inspectable_spec.rb} +5 -5
- data/spec/mongoid/{criterion → criteria}/marshalable_spec.rb +2 -2
- data/spec/mongoid/criteria/modifiable_spec.rb +1252 -0
- data/spec/mongoid/{criterion/scoping_spec.rb → criteria/scopable_spec.rb} +37 -37
- data/spec/mongoid/criteria_spec.rb +715 -2421
- data/spec/mongoid/document_spec.rb +171 -121
- data/spec/mongoid/equality_spec.rb +22 -22
- data/spec/mongoid/errors/ambiguous_relationship_spec.rb +3 -3
- data/spec/mongoid/errors/callback_spec.rb +3 -3
- data/spec/mongoid/errors/delete_restriction_spec.rb +3 -3
- data/spec/mongoid/errors/document_not_destroyed_spec.rb +33 -0
- data/spec/mongoid/errors/document_not_found_spec.rb +11 -11
- data/spec/mongoid/errors/eager_load_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_collection_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_config_option_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_field_option_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_field_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_find_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_includes_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_index_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_options_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_path_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_scope_spec.rb +5 -5
- data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_storage_options_spec.rb +3 -3
- data/spec/mongoid/errors/invalid_time_spec.rb +3 -3
- data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -3
- data/spec/mongoid/errors/mixed_relations_spec.rb +3 -3
- data/spec/mongoid/errors/mixed_session_configuration_spec.rb +3 -3
- data/spec/mongoid/errors/mongoid_error_spec.rb +8 -8
- data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +3 -3
- data/spec/mongoid/errors/no_environment_spec.rb +3 -3
- data/spec/mongoid/errors/no_map_reduce_output_spec.rb +3 -3
- data/spec/mongoid/errors/no_metadata_spec.rb +3 -3
- data/spec/mongoid/errors/no_parent_spec.rb +3 -3
- data/spec/mongoid/errors/no_session_config_spec.rb +3 -3
- data/spec/mongoid/errors/no_session_database_spec.rb +3 -3
- data/spec/mongoid/errors/no_session_hosts_spec.rb +3 -3
- data/spec/mongoid/errors/no_sessions_config_spec.rb +3 -3
- data/spec/mongoid/errors/readonly_attribute_spec.rb +3 -3
- data/spec/mongoid/errors/readonly_document_spec.rb +29 -0
- data/spec/mongoid/errors/scope_overwrite_spec.rb +3 -3
- data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -3
- data/spec/mongoid/errors/unknown_attribute_spec.rb +5 -5
- data/spec/mongoid/errors/unsaved_document_spec.rb +3 -3
- data/spec/mongoid/errors/unsupported_javascript_spec.rb +3 -3
- data/spec/mongoid/errors/validations_spec.rb +7 -7
- data/spec/mongoid/extensions/array_spec.rb +61 -61
- data/spec/mongoid/extensions/big_decimal_spec.rb +11 -11
- data/spec/mongoid/extensions/binary_spec.rb +12 -12
- data/spec/mongoid/extensions/boolean_spec.rb +18 -18
- data/spec/mongoid/extensions/date_spec.rb +13 -13
- data/spec/mongoid/extensions/date_time_spec.rb +8 -8
- data/spec/mongoid/extensions/false_class_spec.rb +5 -5
- data/spec/mongoid/extensions/float_spec.rb +29 -15
- data/spec/mongoid/extensions/hash_spec.rb +29 -29
- data/spec/mongoid/extensions/integer_spec.rb +15 -15
- data/spec/mongoid/extensions/module_spec.rb +2 -2
- data/spec/mongoid/extensions/nil_class_spec.rb +1 -1
- data/spec/mongoid/extensions/object_id_spec.rb +134 -134
- data/spec/mongoid/extensions/object_spec.rb +26 -26
- data/spec/mongoid/extensions/range_spec.rb +61 -12
- data/spec/mongoid/extensions/regexp_spec.rb +4 -4
- data/spec/mongoid/extensions/set_spec.rb +4 -4
- data/spec/mongoid/extensions/string_spec.rb +35 -46
- data/spec/mongoid/extensions/symbol_spec.rb +9 -9
- data/spec/mongoid/extensions/time_spec.rb +49 -49
- data/spec/mongoid/extensions/time_with_zone_spec.rb +34 -34
- data/spec/mongoid/extensions/true_class_spec.rb +5 -5
- data/spec/mongoid/extensions_spec.rb +29 -0
- data/spec/mongoid/factory_spec.rb +15 -15
- data/spec/mongoid/fields/foreign_key_spec.rb +73 -66
- data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +15 -15
- data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +22 -22
- data/spec/mongoid/fields/localized_spec.rb +38 -23
- data/spec/mongoid/fields/standard_spec.rb +12 -12
- data/spec/mongoid/fields_spec.rb +263 -217
- data/spec/mongoid/findable_spec.rb +509 -0
- data/spec/mongoid/indexable/specification_spec.rb +102 -0
- data/spec/mongoid/{indexes_spec.rb → indexable_spec.rb} +171 -51
- data/spec/mongoid/{inspection_spec.rb → inspectable_spec.rb} +6 -14
- data/spec/mongoid/{callbacks_spec.rb → interceptable_spec.rb} +117 -116
- data/spec/mongoid/log_subscriber_spec.rb +75 -0
- data/spec/mongoid/loggable_spec.rb +1 -1
- data/spec/mongoid/{matchers → matchable}/all_spec.rb +4 -4
- data/spec/mongoid/{matchers → matchable}/and_spec.rb +11 -11
- data/spec/mongoid/{matchers → matchable}/default_spec.rb +15 -15
- data/spec/mongoid/{matchers → matchable}/exists_spec.rb +5 -5
- data/spec/mongoid/{matchers → matchable}/gt_spec.rb +9 -8
- data/spec/mongoid/{matchers → matchable}/gte_spec.rb +7 -7
- data/spec/mongoid/matchable/in_spec.rb +49 -0
- data/spec/mongoid/{matchers → matchable}/lt_spec.rb +7 -7
- data/spec/mongoid/{matchers → matchable}/lte_spec.rb +7 -7
- data/spec/mongoid/matchable/ne_spec.rb +46 -0
- data/spec/mongoid/matchable/nin_spec.rb +48 -0
- data/spec/mongoid/{matchers → matchable}/or_spec.rb +6 -6
- data/spec/mongoid/{matchers → matchable}/size_spec.rb +3 -3
- data/spec/mongoid/{matchers_spec.rb → matchable_spec.rb} +41 -41
- data/spec/mongoid/persistable/creatable_spec.rb +553 -0
- data/spec/mongoid/persistable/deletable_spec.rb +218 -0
- data/spec/mongoid/persistable/destroyable_spec.rb +192 -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 +498 -0
- data/spec/mongoid/persistable/settable_spec.rb +162 -0
- data/spec/mongoid/persistable/unsettable_spec.rb +155 -0
- data/spec/mongoid/persistable/updatable_spec.rb +558 -0
- data/spec/mongoid/persistable/upsertable_spec.rb +106 -0
- data/spec/mongoid/persistable_spec.rb +206 -0
- data/spec/mongoid/{atomic/positionable_spec.rb → positional_spec.rb} +14 -19
- data/spec/mongoid/query_cache_spec.rb +263 -0
- data/spec/mongoid/railties/document_spec.rb +2 -2
- data/spec/mongoid/relations/accessors_spec.rb +53 -145
- data/spec/mongoid/relations/auto_save_spec.rb +37 -17
- data/spec/mongoid/relations/bindings/embedded/in_spec.rb +12 -12
- data/spec/mongoid/relations/bindings/embedded/many_spec.rb +3 -3
- data/spec/mongoid/relations/bindings/embedded/one_spec.rb +5 -5
- data/spec/mongoid/relations/bindings/referenced/in_spec.rb +26 -26
- data/spec/mongoid/relations/bindings/referenced/many_spec.rb +10 -10
- data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +19 -19
- data/spec/mongoid/relations/bindings/referenced/one_spec.rb +12 -12
- data/spec/mongoid/relations/builders/embedded/in_spec.rb +4 -4
- data/spec/mongoid/relations/builders/embedded/many_spec.rb +18 -18
- data/spec/mongoid/relations/builders/embedded/one_spec.rb +11 -11
- data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +12 -13
- data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +14 -14
- data/spec/mongoid/relations/builders/referenced/in_spec.rb +24 -35
- data/spec/mongoid/relations/builders/referenced/many_spec.rb +15 -15
- data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +18 -18
- data/spec/mongoid/relations/builders/referenced/one_spec.rb +12 -25
- data/spec/mongoid/relations/builders_spec.rb +21 -21
- data/spec/mongoid/relations/cascading/delete_spec.rb +9 -9
- data/spec/mongoid/relations/cascading/destroy_spec.rb +6 -6
- data/spec/mongoid/relations/cascading/nullify_spec.rb +4 -4
- data/spec/mongoid/relations/cascading/restrict_spec.rb +7 -7
- data/spec/mongoid/relations/cascading_spec.rb +16 -16
- data/spec/mongoid/relations/constraint_spec.rb +8 -7
- data/spec/mongoid/relations/conversions_spec.rb +16 -14
- data/spec/mongoid/relations/counter_cache_spec.rb +85 -0
- data/spec/mongoid/relations/cyclic_spec.rb +18 -18
- data/spec/mongoid/relations/eager/belongs_to_spec.rb +154 -0
- data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +117 -0
- data/spec/mongoid/relations/eager/has_many_spec.rb +207 -0
- data/spec/mongoid/relations/eager/has_one_spec.rb +163 -0
- data/spec/mongoid/relations/eager_spec.rb +228 -0
- data/spec/mongoid/relations/embedded/dirty_spec.rb +8 -8
- data/spec/mongoid/relations/embedded/in_spec.rb +56 -57
- data/spec/mongoid/relations/embedded/many_spec.rb +467 -372
- data/spec/mongoid/relations/embedded/one_spec.rb +108 -141
- data/spec/mongoid/relations/macros_spec.rb +108 -102
- data/spec/mongoid/relations/metadata_spec.rb +180 -255
- data/spec/mongoid/relations/options_spec.rb +1 -1
- data/spec/mongoid/relations/polymorphic_spec.rb +13 -17
- data/spec/mongoid/relations/proxy_spec.rb +2 -2
- data/spec/mongoid/relations/referenced/in_spec.rb +128 -303
- data/spec/mongoid/relations/referenced/many_spec.rb +587 -527
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +401 -424
- data/spec/mongoid/relations/referenced/one_spec.rb +149 -264
- data/spec/mongoid/relations/reflections_spec.rb +6 -6
- data/spec/mongoid/relations/synchronization_spec.rb +46 -50
- data/spec/mongoid/relations/targets/enumerable_spec.rb +118 -118
- data/spec/mongoid/relations/touchable_spec.rb +333 -0
- data/spec/mongoid/relations_spec.rb +16 -15
- data/spec/mongoid/{reloading_spec.rb → reloadable_spec.rb} +38 -55
- data/spec/mongoid/{scoping_spec.rb → scopable_spec.rb} +89 -164
- data/spec/mongoid/selectable_spec.rb +134 -0
- data/spec/mongoid/{serialization_spec.rb → serializable_spec.rb} +129 -82
- data/spec/mongoid/sessions/factory_spec.rb +49 -28
- data/spec/mongoid/sessions/mongo_uri_spec.rb +7 -7
- data/spec/mongoid/sessions/options_spec.rb +108 -0
- data/spec/mongoid/sessions_spec.rb +319 -178
- data/spec/mongoid/{sharding_spec.rb → shardable_spec.rb} +8 -8
- data/spec/mongoid/{state_spec.rb → stateful_spec.rb} +36 -11
- data/spec/mongoid/tasks/database_rake_spec.rb +285 -0
- data/spec/mongoid/tasks/database_spec.rb +160 -0
- data/spec/mongoid/threaded_spec.rb +17 -70
- data/spec/mongoid/timestamps/created/short_spec.rb +6 -6
- data/spec/mongoid/timestamps/created_spec.rb +5 -5
- data/spec/mongoid/timestamps/timeless_spec.rb +6 -6
- data/spec/mongoid/timestamps/updated/short_spec.rb +11 -11
- data/spec/mongoid/timestamps/updated_spec.rb +9 -13
- data/spec/mongoid/timestamps_spec.rb +9 -13
- data/spec/mongoid/{hierarchy_spec.rb → traversable_spec.rb} +19 -19
- data/spec/mongoid/{validations → validatable}/associated_spec.rb +45 -22
- data/spec/mongoid/{validations → validatable}/format_spec.rb +6 -6
- data/spec/mongoid/{validations → validatable}/length_spec.rb +14 -14
- data/spec/mongoid/{validations → validatable}/numericality_spec.rb +1 -1
- data/spec/mongoid/{validations → validatable}/presence_spec.rb +37 -44
- data/spec/mongoid/{validations → validatable}/uniqueness_spec.rb +184 -192
- data/spec/mongoid/{validations_spec.rb → validatable_spec.rb} +28 -28
- data/spec/mongoid_spec.rb +8 -8
- data/spec/rails/mongoid_spec.rb +19 -335
- data/spec/spec_helper.rb +31 -13
- metadata +303 -283
- data/lib/mongoid/atomic/positionable.rb +0 -73
- data/lib/mongoid/components.rb +0 -92
- data/lib/mongoid/config/inflections.rb +0 -6
- data/lib/mongoid/contextual/eager.rb +0 -158
- data/lib/mongoid/errors/versioning_not_on_root.rb +0 -23
- data/lib/mongoid/identity_map.rb +0 -163
- data/lib/mongoid/json.rb +0 -16
- data/lib/mongoid/matchers.rb +0 -32
- data/lib/mongoid/matchers/strategies.rb +0 -97
- data/lib/mongoid/multi_parameter_attributes.rb +0 -105
- data/lib/mongoid/nested_attributes.rb +0 -78
- data/lib/mongoid/observer.rb +0 -192
- data/lib/mongoid/paranoia.rb +0 -136
- data/lib/mongoid/persistence.rb +0 -357
- data/lib/mongoid/persistence/atomic.rb +0 -231
- data/lib/mongoid/persistence/atomic/add_to_set.rb +0 -47
- data/lib/mongoid/persistence/atomic/bit.rb +0 -35
- data/lib/mongoid/persistence/atomic/inc.rb +0 -45
- data/lib/mongoid/persistence/atomic/operation.rb +0 -154
- data/lib/mongoid/persistence/atomic/pop.rb +0 -32
- data/lib/mongoid/persistence/atomic/pull.rb +0 -32
- data/lib/mongoid/persistence/atomic/pull_all.rb +0 -32
- data/lib/mongoid/persistence/atomic/push.rb +0 -25
- data/lib/mongoid/persistence/atomic/push_all.rb +0 -25
- data/lib/mongoid/persistence/atomic/rename.rb +0 -30
- data/lib/mongoid/persistence/atomic/sets.rb +0 -28
- data/lib/mongoid/persistence/atomic/unset.rb +0 -27
- data/lib/mongoid/persistence/deletion.rb +0 -31
- data/lib/mongoid/persistence/insertion.rb +0 -38
- data/lib/mongoid/persistence/modification.rb +0 -35
- data/lib/mongoid/persistence/operations.rb +0 -214
- data/lib/mongoid/persistence/operations/embedded/insert.rb +0 -46
- data/lib/mongoid/persistence/operations/embedded/remove.rb +0 -43
- data/lib/mongoid/persistence/operations/insert.rb +0 -34
- data/lib/mongoid/persistence/operations/remove.rb +0 -33
- data/lib/mongoid/persistence/operations/update.rb +0 -59
- data/lib/mongoid/persistence/operations/upsert.rb +0 -28
- data/lib/mongoid/persistence/upsertion.rb +0 -31
- data/lib/mongoid/unit_of_work.rb +0 -61
- data/lib/mongoid/versioning.rb +0 -217
- data/lib/rack/mongoid.rb +0 -2
- data/lib/rack/mongoid/middleware/identity_map.rb +0 -39
- data/lib/rails/generators/mongoid/observer/observer_generator.rb +0 -17
- data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +0 -4
- data/spec/app/models/actor_observer.rb +0 -15
- data/spec/app/models/callback_recorder.rb +0 -25
- data/spec/app/models/paranoid_phone.rb +0 -25
- data/spec/app/models/paranoid_post.rb +0 -36
- data/spec/app/models/phone_observer.rb +0 -6
- data/spec/mongoid/attributes/processing_spec.rb +0 -149
- data/spec/mongoid/criterion/destructive_spec.rb +0 -101
- data/spec/mongoid/criterion/modifiable_spec.rb +0 -409
- data/spec/mongoid/criterion/modification_spec.rb +0 -402
- data/spec/mongoid/errors/versioning_not_on_root_spec.rb +0 -29
- data/spec/mongoid/finders_spec.rb +0 -321
- data/spec/mongoid/identity_map_spec.rb +0 -564
- data/spec/mongoid/json_spec.rb +0 -33
- data/spec/mongoid/matchers/in_spec.rb +0 -25
- data/spec/mongoid/matchers/ne_spec.rb +0 -25
- data/spec/mongoid/matchers/nin_spec.rb +0 -25
- data/spec/mongoid/multi_parameter_attributes_spec.rb +0 -128
- data/spec/mongoid/observer_spec.rb +0 -290
- data/spec/mongoid/paranoia_spec.rb +0 -759
- data/spec/mongoid/persistence/atomic/add_to_set_spec.rb +0 -262
- data/spec/mongoid/persistence/atomic/bit_spec.rb +0 -88
- data/spec/mongoid/persistence/atomic/inc_spec.rb +0 -133
- data/spec/mongoid/persistence/atomic/pop_spec.rb +0 -111
- data/spec/mongoid/persistence/atomic/pull_all_spec.rb +0 -77
- data/spec/mongoid/persistence/atomic/pull_spec.rb +0 -80
- data/spec/mongoid/persistence/atomic/push_all_spec.rb +0 -77
- data/spec/mongoid/persistence/atomic/push_spec.rb +0 -77
- data/spec/mongoid/persistence/atomic/rename_spec.rb +0 -42
- data/spec/mongoid/persistence/atomic/sets_spec.rb +0 -154
- data/spec/mongoid/persistence/atomic/unset_spec.rb +0 -65
- data/spec/mongoid/persistence/atomic_spec.rb +0 -216
- data/spec/mongoid/persistence/operations/embedded/insert_spec.rb +0 -191
- data/spec/mongoid/persistence/operations/embedded/remove_spec.rb +0 -8
- data/spec/mongoid/persistence/operations/insert_spec.rb +0 -149
- data/spec/mongoid/persistence/operations/remove_spec.rb +0 -113
- data/spec/mongoid/persistence/operations/update_spec.rb +0 -141
- data/spec/mongoid/persistence/operations/upsert_spec.rb +0 -59
- data/spec/mongoid/persistence/operations_spec.rb +0 -313
- data/spec/mongoid/persistence_spec.rb +0 -2279
- data/spec/mongoid/unit_of_work_spec.rb +0 -196
- data/spec/mongoid/versioning_spec.rb +0 -540
- data/spec/rack/mongoid/middleware/identity_map_spec.rb +0 -72
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Persistable
|
4
|
+
|
5
|
+
# Defines behaviour for $rename operations.
|
6
|
+
#
|
7
|
+
# @since 4.0.0
|
8
|
+
module Renamable
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
# Rename fields from one value to another via $rename.
|
12
|
+
#
|
13
|
+
# @example Rename the fields.
|
14
|
+
# document.rename(title: "salutation", name: "nombre")
|
15
|
+
#
|
16
|
+
# @note This does not work for fields in embeds many relations.
|
17
|
+
#
|
18
|
+
# @param [ Hash ] renames The rename pairs of old name/new name.
|
19
|
+
#
|
20
|
+
# @return [ true, false ] If the rename suceeded.
|
21
|
+
#
|
22
|
+
# @since 4.0.0
|
23
|
+
def rename(renames)
|
24
|
+
prepare_atomic_operation do |ops|
|
25
|
+
process_atomic_operations(renames) do |old_field, new_field|
|
26
|
+
new_name = new_field.to_s
|
27
|
+
attributes[new_name] = attributes.delete(old_field)
|
28
|
+
ops[atomic_attribute_name(old_field)] = atomic_attribute_name(new_name)
|
29
|
+
end
|
30
|
+
{ "$rename" => ops }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Persistable
|
4
|
+
|
5
|
+
# Defines behaviour for persistence operations that save documents.
|
6
|
+
#
|
7
|
+
# @since 4.0.0
|
8
|
+
module Savable
|
9
|
+
|
10
|
+
# Save the document - will perform an insert if the document is new, and
|
11
|
+
# update if not.
|
12
|
+
#
|
13
|
+
# @example Save the document.
|
14
|
+
# document.save
|
15
|
+
#
|
16
|
+
# @param [ Hash ] options Options to pass to the save.
|
17
|
+
#
|
18
|
+
# @return [ true, false ] True is success, false if not.
|
19
|
+
#
|
20
|
+
# @since 1.0.0
|
21
|
+
def save(options = {})
|
22
|
+
if new_record?
|
23
|
+
!insert(options).new_record?
|
24
|
+
else
|
25
|
+
update_document(options)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Save the document - will perform an insert if the document is new, and
|
30
|
+
# update if not. If a validation error occurs an error will get raised.
|
31
|
+
#
|
32
|
+
# @example Save the document.
|
33
|
+
# document.save!
|
34
|
+
#
|
35
|
+
# @param [ Hash ] options Options to pass to the save.
|
36
|
+
#
|
37
|
+
# @raise [ Errors::Validations ] If validation failed.
|
38
|
+
# @raise [ Errors::Callback ] If a callback returns false.
|
39
|
+
#
|
40
|
+
# @return [ true, false ] True if validation passed.
|
41
|
+
#
|
42
|
+
# @since 1.0.0
|
43
|
+
def save!(options = {})
|
44
|
+
unless save(options)
|
45
|
+
fail_due_to_validation! unless errors.empty?
|
46
|
+
fail_due_to_callback!(:save!)
|
47
|
+
end
|
48
|
+
true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Persistable
|
4
|
+
|
5
|
+
# Defines behaviour for $set operations.
|
6
|
+
#
|
7
|
+
# @since 4.0.0
|
8
|
+
module Settable
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
# Perform a $set operation on the provided field/value pairs and set the
|
12
|
+
# values in the document in memory.
|
13
|
+
#
|
14
|
+
# @example Set the values.
|
15
|
+
# document.set(title: "sir", dob: Date.new(1970, 1, 1))
|
16
|
+
#
|
17
|
+
# @param [ Hash ] setters The field/value pairs to set.
|
18
|
+
#
|
19
|
+
# @return [ true ] If the operation succeeded.
|
20
|
+
#
|
21
|
+
# @since 4.0.0
|
22
|
+
def set(setters)
|
23
|
+
prepare_atomic_operation do |ops|
|
24
|
+
process_atomic_operations(setters) do |field, value|
|
25
|
+
process_attribute(field.to_s, value)
|
26
|
+
ops[atomic_attribute_name(field)] = attributes[field]
|
27
|
+
end
|
28
|
+
{ "$set" => ops }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Persistable
|
4
|
+
|
5
|
+
# Defines behaviour for $unset operations.
|
6
|
+
#
|
7
|
+
# @since 4.0.0
|
8
|
+
module Unsettable
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
# Perform an $unset operation on the provided fields and in the
|
12
|
+
# values in the document in memory.
|
13
|
+
#
|
14
|
+
# @example Unset the values.
|
15
|
+
# document.unset(:first_name, :last_name, :middle)
|
16
|
+
#
|
17
|
+
# @param [ Array<String, Symbol> ] fields The names of the fields to
|
18
|
+
# unset.
|
19
|
+
#
|
20
|
+
# @return [ true ] If the operation succeeded.
|
21
|
+
#
|
22
|
+
# @since 4.0.0
|
23
|
+
def unset(*fields)
|
24
|
+
prepare_atomic_operation do |ops|
|
25
|
+
fields.flatten.each do |field|
|
26
|
+
normalized = database_field_name(field)
|
27
|
+
attributes.delete(normalized)
|
28
|
+
ops[atomic_attribute_name(normalized)] = true
|
29
|
+
end
|
30
|
+
{ "$unset" => ops }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Persistable
|
4
|
+
|
5
|
+
# Defines behaviour for persistence operations that update existing
|
6
|
+
# documents.
|
7
|
+
#
|
8
|
+
# @since 4.0.0
|
9
|
+
module Updatable
|
10
|
+
|
11
|
+
# Update a single attribute and persist the entire document.
|
12
|
+
# This skips validation but fires the callbacks.
|
13
|
+
#
|
14
|
+
# @example Update the attribute.
|
15
|
+
# person.update_attribute(:title, "Sir")
|
16
|
+
#
|
17
|
+
# @param [ Symbol, String ] name The name of the attribute.
|
18
|
+
# @param [ Object ] value The new value of the attribute.a
|
19
|
+
#
|
20
|
+
# @raise [ Errors::ReadonlyAttribute ] If the field cannot be changed due
|
21
|
+
# to being flagged as reaodnly.
|
22
|
+
#
|
23
|
+
# @return [ true, false ] True if save was successfull, false if not.
|
24
|
+
#
|
25
|
+
# @since 2.0.0
|
26
|
+
def update_attribute(name, value)
|
27
|
+
normalized = name.to_s
|
28
|
+
unless attribute_writable?(normalized)
|
29
|
+
raise Errors::ReadonlyAttribute.new(normalized, value)
|
30
|
+
end
|
31
|
+
setter = "#{normalized}="
|
32
|
+
if respond_to?(setter)
|
33
|
+
send(setter, value)
|
34
|
+
else
|
35
|
+
write_attribute(database_field_name(normalized), value)
|
36
|
+
end
|
37
|
+
save(validate: false)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Update the document attributes in the database.
|
41
|
+
#
|
42
|
+
# @example Update the document's attributes
|
43
|
+
# document.update(:title => "Sir")
|
44
|
+
#
|
45
|
+
# @param [ Hash ] attributes The attributes to update.
|
46
|
+
#
|
47
|
+
# @return [ true, false ] True if validation passed, false if not.
|
48
|
+
#
|
49
|
+
# @since 1.0.0
|
50
|
+
def update(attributes = {})
|
51
|
+
assign_attributes(attributes)
|
52
|
+
save
|
53
|
+
end
|
54
|
+
alias :update_attributes :update
|
55
|
+
|
56
|
+
# Update the document attributes in the database and raise an error if
|
57
|
+
# validation failed.
|
58
|
+
#
|
59
|
+
# @example Update the document's attributes.
|
60
|
+
# document.update!(:title => "Sir")
|
61
|
+
#
|
62
|
+
# @param [ Hash ] attributes The attributes to update.
|
63
|
+
#
|
64
|
+
# @raise [ Errors::Validations ] If validation failed.
|
65
|
+
# @raise [ Errors::Callbacks ] If a callback returns false.
|
66
|
+
#
|
67
|
+
# @return [ true, false ] True if validation passed.
|
68
|
+
#
|
69
|
+
# @since 1.0.0
|
70
|
+
def update!(attributes = {})
|
71
|
+
result = update_attributes(attributes)
|
72
|
+
unless result
|
73
|
+
fail_due_to_validation! unless errors.empty?
|
74
|
+
fail_due_to_callback!(:update_attributes!)
|
75
|
+
end
|
76
|
+
result
|
77
|
+
end
|
78
|
+
alias :update_attributes! :update!
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
# Initialize the atomic updates.
|
83
|
+
#
|
84
|
+
# @api private
|
85
|
+
#
|
86
|
+
# @example Initialize the atomic updates.
|
87
|
+
# document.init_atomic_updates
|
88
|
+
#
|
89
|
+
# @return [ Array<Hash> ] The updates and conflicts.
|
90
|
+
#
|
91
|
+
# @since 4.0.0
|
92
|
+
def init_atomic_updates
|
93
|
+
updates = atomic_updates
|
94
|
+
conflicts = updates.delete(:conflicts) || {}
|
95
|
+
[ updates, conflicts ]
|
96
|
+
end
|
97
|
+
|
98
|
+
# Prepare the update for execution. Validates and runs callbacks, etc.
|
99
|
+
#
|
100
|
+
# @api private
|
101
|
+
#
|
102
|
+
# @example Prepare for update.
|
103
|
+
# document.prepare_update do
|
104
|
+
# collection.update(atomic_selector)
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# @param [ Hash ] options The options.
|
108
|
+
#
|
109
|
+
# @return [ true, false ] The result of the update.
|
110
|
+
#
|
111
|
+
# @since 4.0.0
|
112
|
+
def prepare_update(options = {})
|
113
|
+
return false if performing_validations?(options) &&
|
114
|
+
invalid?(options[:context] || :update)
|
115
|
+
process_flagged_destroys
|
116
|
+
result = run_callbacks(:save) do
|
117
|
+
run_callbacks(:update) do
|
118
|
+
yield(self)
|
119
|
+
true
|
120
|
+
end
|
121
|
+
end
|
122
|
+
post_process_persist(result, options) and result
|
123
|
+
end
|
124
|
+
|
125
|
+
# Update the document in the database.
|
126
|
+
#
|
127
|
+
# @example Update an existing document.
|
128
|
+
# document.update
|
129
|
+
#
|
130
|
+
# @param [ Hash ] options Options to pass to update.
|
131
|
+
#
|
132
|
+
# @option options [ true, false ] :validate Whether or not to validate.
|
133
|
+
#
|
134
|
+
# @return [ true, false ] True if succeeded, false if not.
|
135
|
+
#
|
136
|
+
# @since 1.0.0
|
137
|
+
def update_document(options = {})
|
138
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly?
|
139
|
+
prepare_update(options) do
|
140
|
+
updates, conflicts = init_atomic_updates
|
141
|
+
unless updates.empty?
|
142
|
+
coll = _root.collection
|
143
|
+
selector = atomic_selector
|
144
|
+
coll.find(selector).update(positionally(selector, updates))
|
145
|
+
conflicts.each_pair do |key, value|
|
146
|
+
coll.find(selector).update(positionally(selector, { key => value }))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Persistable
|
4
|
+
|
5
|
+
# Defines behaviour for persistence operations that upsert documents.
|
6
|
+
#
|
7
|
+
# @since 4.0.0
|
8
|
+
module Upsertable
|
9
|
+
|
10
|
+
# Perform an upsert of the document. If the document does not exist in the
|
11
|
+
# database, then Mongo will insert a new one, otherwise the fields will get
|
12
|
+
# overwritten with new values on the existing document.
|
13
|
+
#
|
14
|
+
# @example Upsert the document.
|
15
|
+
# document.upsert
|
16
|
+
#
|
17
|
+
# @param [ Hash ] options The validation options.
|
18
|
+
#
|
19
|
+
# @return [ true ] True.
|
20
|
+
#
|
21
|
+
# @since 3.0.0
|
22
|
+
def upsert(options = {})
|
23
|
+
prepare_upsert(options) do
|
24
|
+
collection.find(atomic_selector).update(as_document, [ :upsert ])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Prepare the upsert for execution.
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
#
|
34
|
+
# @example Prepare the upsert
|
35
|
+
# document.prepare_upsert do
|
36
|
+
# collection.find(selector).update(as_document)
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# @param [ Hash ] options The options hash.
|
40
|
+
#
|
41
|
+
# @return [ true, false ] If the operation succeeded.
|
42
|
+
#
|
43
|
+
# @since 4.0.0
|
44
|
+
def prepare_upsert(options = {})
|
45
|
+
return false if performing_validations?(options) && invalid?(:upsert)
|
46
|
+
result = run_callbacks(:upsert) do
|
47
|
+
yield(self)
|
48
|
+
true
|
49
|
+
end
|
50
|
+
self.new_record = false
|
51
|
+
post_process_persist(result, options) and result
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
|
4
|
+
# This module is responsible for taking update selectors and switching out
|
5
|
+
# the indexes for the $ positional operator where appropriate.
|
6
|
+
#
|
7
|
+
# @since 4.0.0
|
8
|
+
module Positional
|
9
|
+
|
10
|
+
# Takes the provided selector and atomic operations and replaces the
|
11
|
+
# indexes of the embedded documents with the positional operator when
|
12
|
+
# needed.
|
13
|
+
#
|
14
|
+
# @note The only time we can accurately know when to use the positional
|
15
|
+
# operator is at the exact time we are going to persist something. So
|
16
|
+
# we can tell by the selector that we are sending if it is actually
|
17
|
+
# possible to use the positional operator at all. For example, if the
|
18
|
+
# selector is: { "_id" => 1 }, then we could not use the positional
|
19
|
+
# operator for updating embedded documents since there would never be a
|
20
|
+
# match - we base whether we can based on the number of levels deep the
|
21
|
+
# selector goes, and if the id values are not nil.
|
22
|
+
#
|
23
|
+
# @example Process the operations.
|
24
|
+
# positionally(
|
25
|
+
# { "_id" => 1, "addresses._id" => 2 },
|
26
|
+
# { "$set" => { "addresses.0.street" => "hobrecht" }}
|
27
|
+
# )
|
28
|
+
#
|
29
|
+
# @param [ Hash ] selector The selector.
|
30
|
+
# @param [ Hash ] operations The update operations.
|
31
|
+
# @param [ Hash ] processed The processed update operations.
|
32
|
+
#
|
33
|
+
# @return [ Hash ] The new operations.
|
34
|
+
#
|
35
|
+
# @since 3.1.0
|
36
|
+
def positionally(selector, operations, processed = {})
|
37
|
+
if selector.size == 1 || selector.values.any? { |val| val.nil? }
|
38
|
+
return operations
|
39
|
+
end
|
40
|
+
keys = selector.keys.map{ |m| m.sub('._id','') } - ['_id']
|
41
|
+
keys = keys.sort_by { |s| s.length*-1 }
|
42
|
+
process_operations(keys, operations, processed)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def process_operations(keys, operations, processed)
|
48
|
+
operations.each_pair do |operation, update|
|
49
|
+
processed[operation] = process_updates(keys, update)
|
50
|
+
end
|
51
|
+
processed
|
52
|
+
end
|
53
|
+
|
54
|
+
def process_updates(keys, update, updates = {})
|
55
|
+
update.each_pair do |position, value|
|
56
|
+
updates[replace_index(keys, position)] = value
|
57
|
+
end
|
58
|
+
updates
|
59
|
+
end
|
60
|
+
|
61
|
+
def replace_index(keys, position)
|
62
|
+
# replace to $ only if that key is on the selector
|
63
|
+
keys.each do |kk|
|
64
|
+
if position =~ /^#{kk}\.\d+\.(.*)/
|
65
|
+
return "#{kk}.$.#{$1}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
position
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,255 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
|
4
|
+
# A cache of database queries on a per-request basis.
|
5
|
+
#
|
6
|
+
# @since 4.0.0
|
7
|
+
module QueryCache
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Get the cached queries.
|
11
|
+
#
|
12
|
+
# @example Get the cached queries from the current thread.
|
13
|
+
# QueryCache.cache_table
|
14
|
+
#
|
15
|
+
# @return [ Hash ] The hash of cached queries.
|
16
|
+
#
|
17
|
+
# @since 4.0.0
|
18
|
+
def cache_table
|
19
|
+
Thread.current["[mongoid]:query_cache"] ||= {}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Clear the query cache.
|
23
|
+
#
|
24
|
+
# @example Clear the cache.
|
25
|
+
# QueryCache.clear_cache
|
26
|
+
#
|
27
|
+
# @return [ nil ] Always nil.
|
28
|
+
#
|
29
|
+
# @since 4.0.0
|
30
|
+
def clear_cache
|
31
|
+
Thread.current["[mongoid]:query_cache"] = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# Set whether the cache is enabled.
|
35
|
+
#
|
36
|
+
# @example Set if the cache is enabled.
|
37
|
+
# QueryCache.enabled = true
|
38
|
+
#
|
39
|
+
# @param [ true, false ] value The enabled value.
|
40
|
+
#
|
41
|
+
# @since 4.0.0
|
42
|
+
def enabled=(value)
|
43
|
+
Thread.current["[mongoid]:query_cache:enabled"] = value
|
44
|
+
end
|
45
|
+
|
46
|
+
# Is the query cache enabled on the current thread?
|
47
|
+
#
|
48
|
+
# @example Is the query cache enabled?
|
49
|
+
# QueryCache.enabled?
|
50
|
+
#
|
51
|
+
# @return [ true, false ] If the cache is enabled.
|
52
|
+
#
|
53
|
+
# @since 4.0.0
|
54
|
+
def enabled?
|
55
|
+
!!Thread.current["[mongoid]:query_cache:enabled"]
|
56
|
+
end
|
57
|
+
|
58
|
+
# Execute the block while using the query cache.
|
59
|
+
#
|
60
|
+
# @example Execute with the cache.
|
61
|
+
# QueryCache.cache { collection.find }
|
62
|
+
#
|
63
|
+
# @return [ Object ] The result of the block.
|
64
|
+
#
|
65
|
+
# @since 4.0.0
|
66
|
+
def cache
|
67
|
+
enabled = QueryCache.enabled?
|
68
|
+
QueryCache.enabled = true
|
69
|
+
yield
|
70
|
+
ensure
|
71
|
+
QueryCache.enabled = enabled
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# The middleware to be added to a rack application in order to activate the
|
76
|
+
# query cache.
|
77
|
+
#
|
78
|
+
# @since 4.0.0
|
79
|
+
class Middleware
|
80
|
+
|
81
|
+
# Instantiate the middleware.
|
82
|
+
#
|
83
|
+
# @example Create the new middleware.
|
84
|
+
# Middleware.new(app)
|
85
|
+
#
|
86
|
+
# @param [ Object ] app The rack applciation stack.
|
87
|
+
#
|
88
|
+
# @since 4.0.0
|
89
|
+
def initialize(app)
|
90
|
+
@app = app
|
91
|
+
end
|
92
|
+
|
93
|
+
# Execute the request, wrapping in a query cache.
|
94
|
+
#
|
95
|
+
# @example Execute the request.
|
96
|
+
# middleware.call(env)
|
97
|
+
#
|
98
|
+
# @param [ Object ] env The environment.
|
99
|
+
#
|
100
|
+
# @return [ Object ] The result of the call.
|
101
|
+
#
|
102
|
+
# @since 4.0.0
|
103
|
+
def call(env)
|
104
|
+
QueryCache.cache { @app.call(env) }
|
105
|
+
ensure
|
106
|
+
QueryCache.clear_cache
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
module Base # :nodoc:
|
111
|
+
|
112
|
+
def alias_query_cache_clear(*method_names)
|
113
|
+
method_names.each do |method_name|
|
114
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
115
|
+
def #{method_name}_with_clear_cache(*args) # def upsert_with_clear_cache(*args)
|
116
|
+
QueryCache.clear_cache # QueryCache.clear_cache
|
117
|
+
#{method_name}_without_clear_cache(*args) # upsert_without_clear_cache(*args)
|
118
|
+
end # end
|
119
|
+
CODE
|
120
|
+
|
121
|
+
alias_method_chain method_name, :clear_cache
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Module to include in objects which need to wrap caching behaviour around
|
127
|
+
# them.
|
128
|
+
#
|
129
|
+
# @since 4.0.0
|
130
|
+
module Cacheable
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def with_cache(context = :cursor, more = false, &block)
|
135
|
+
return yield unless QueryCache.enabled?
|
136
|
+
return yield if system_collection?
|
137
|
+
key = cache_key.push(context)
|
138
|
+
|
139
|
+
if more
|
140
|
+
docs = yield
|
141
|
+
QueryCache.cache_table[key].push(*docs)
|
142
|
+
docs
|
143
|
+
elsif QueryCache.cache_table.has_key?(key)
|
144
|
+
instrument(key) { QueryCache.cache_table[key] }
|
145
|
+
else
|
146
|
+
QueryCache.cache_table[key] = yield
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def instrument(key, &block)
|
151
|
+
ActiveSupport::Notifications.instrument("query_cache.mongoid", key: key, &block)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Adds behaviour around caching to a Moped Query object.
|
156
|
+
#
|
157
|
+
# @since 4.0.0
|
158
|
+
module Query
|
159
|
+
extend ActiveSupport::Concern
|
160
|
+
include Cacheable
|
161
|
+
|
162
|
+
included do
|
163
|
+
extend QueryCache::Base
|
164
|
+
alias_method_chain :cursor, :cache
|
165
|
+
alias_method_chain :first, :cache
|
166
|
+
alias_query_cache_clear :remove, :remove_all, :update, :update_all, :upsert
|
167
|
+
end
|
168
|
+
|
169
|
+
# Provide a wrapped query cache cursor.
|
170
|
+
#
|
171
|
+
# @example Get the wrapped caching cursor.
|
172
|
+
# query.cursor_with_cache
|
173
|
+
#
|
174
|
+
# @return [ CachedCursor ] The cached cursor.
|
175
|
+
#
|
176
|
+
# @since 4.0.0
|
177
|
+
def cursor_with_cache
|
178
|
+
CachedCursor.new(session, operation)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Override first with caching.
|
182
|
+
#
|
183
|
+
# @example Get the first with a cache.
|
184
|
+
# query.first_with_cache
|
185
|
+
#
|
186
|
+
# @return [ Hash ] The first document.
|
187
|
+
#
|
188
|
+
# @since 4.0.0
|
189
|
+
def first_with_cache
|
190
|
+
with_cache(:first) do
|
191
|
+
first_without_cache
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
private
|
196
|
+
|
197
|
+
def cache_key
|
198
|
+
[ operation.database, operation.collection, operation.selector, operation.limit, operation.skip, operation.fields ]
|
199
|
+
end
|
200
|
+
|
201
|
+
def system_collection?
|
202
|
+
operation.collection =~ /^system./
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# Adds behaviour to the query cache for collections.
|
207
|
+
#
|
208
|
+
# @since 4.0.0
|
209
|
+
module Collection
|
210
|
+
extend ActiveSupport::Concern
|
211
|
+
|
212
|
+
included do
|
213
|
+
extend QueryCache::Base
|
214
|
+
alias_query_cache_clear :insert
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# A Cursor that attempts to load documents from memory first before hitting
|
219
|
+
# the database if the same query has already been executed.
|
220
|
+
#
|
221
|
+
# @since 4.0.0
|
222
|
+
class CachedCursor < Moped::Cursor
|
223
|
+
include Cacheable
|
224
|
+
|
225
|
+
# Override the loading of docs to attempt to fetch from the cache.
|
226
|
+
#
|
227
|
+
# @example Load the documents.
|
228
|
+
# cursor.load_docs
|
229
|
+
#
|
230
|
+
# @return [ Array<Hash> ] The documents.
|
231
|
+
#
|
232
|
+
# @since 4.0.0
|
233
|
+
def load_docs
|
234
|
+
with_cache { super }
|
235
|
+
end
|
236
|
+
|
237
|
+
def get_more
|
238
|
+
with_cache(:cursor, true) { super }
|
239
|
+
end
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
def cache_key
|
244
|
+
[ @database, @collection, @selector, @options[:limit], @options[:skip], @options[:fields] ]
|
245
|
+
end
|
246
|
+
|
247
|
+
def system_collection?
|
248
|
+
@collection =~ /^system./
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
Moped::Query.__send__(:include, Mongoid::QueryCache::Query)
|
255
|
+
Moped::Collection.__send__(:include, Mongoid::QueryCache::Collection)
|