mongoid 3.1.4 → 3.1.5
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 +34 -0
- data/lib/mongoid/contextual.rb +3 -0
- data/lib/mongoid/criteria.rb +10 -2
- data/lib/mongoid/document.rb +1 -1
- data/lib/mongoid/paranoia.rb +4 -0
- data/lib/mongoid/persistence/upsertion.rb +1 -0
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +16 -2
- data/lib/mongoid/relations/macros.rb +1 -1
- data/lib/mongoid/relations/one.rb +12 -0
- data/lib/mongoid/relations/referenced/in.rb +18 -1
- data/lib/mongoid/relations/referenced/many_to_many.rb +2 -2
- data/lib/mongoid/validations.rb +1 -1
- data/lib/mongoid/validations/localizable.rb +1 -1
- data/lib/mongoid/validations/presence.rb +1 -1
- data/lib/mongoid/validations/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/support/ruby_version.rb +1 -1
- data/spec/app/models/account.rb +32 -0
- data/spec/app/models/acolyte.rb +16 -0
- data/spec/app/models/actor.rb +19 -0
- data/spec/app/models/actor_observer.rb +15 -0
- data/spec/app/models/actress.rb +2 -0
- data/spec/app/models/address.rb +72 -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 +13 -0
- data/spec/app/models/artist.rb +66 -0
- data/spec/app/models/artwork.rb +4 -0
- data/spec/app/models/augmentation.rb +11 -0
- data/spec/app/models/author.rb +6 -0
- data/spec/app/models/band.rb +25 -0
- data/spec/app/models/bar.rb +9 -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 +12 -0
- data/spec/app/models/breed.rb +4 -0
- data/spec/app/models/browser.rb +6 -0
- data/spec/app/models/building.rb +7 -0
- data/spec/app/models/building_address.rb +7 -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 +7 -0
- data/spec/app/models/cookie.rb +6 -0
- data/spec/app/models/country_code.rb +8 -0
- data/spec/app/models/definition.rb +8 -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/driver.rb +7 -0
- data/spec/app/models/drug.rb +8 -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 +4 -0
- data/spec/app/models/fire_hydrant.rb +6 -0
- data/spec/app/models/firefox.rb +4 -0
- data/spec/app/models/fish.rb +8 -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 +21 -0
- data/spec/app/models/ghost.rb +7 -0
- data/spec/app/models/home.rb +4 -0
- data/spec/app/models/house.rb +8 -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 +12 -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 +12 -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/paranoid_phone.rb +25 -0
- data/spec/app/models/paranoid_post.rb +36 -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 +201 -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/phone_observer.rb +6 -0
- data/spec/app/models/pizza.rb +7 -0
- data/spec/app/models/player.rb +35 -0
- data/spec/app/models/post.rb +43 -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 +17 -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 +10 -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/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 +4 -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 +17 -0
- data/spec/app/models/video_game.rb +1 -0
- data/spec/app/models/weapon.rb +11 -0
- data/spec/app/models/wiki_page.rb +17 -0
- data/spec/app/models/word.rb +12 -0
- data/spec/app/models/word_origin.rb +11 -0
- data/spec/app/models/writer.rb +11 -0
- data/spec/config/mongoid.yml +40 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +456 -0
- data/spec/mongoid/atomic/paths/embedded/many_spec.rb +159 -0
- data/spec/mongoid/atomic/paths/embedded/one_spec.rb +152 -0
- data/spec/mongoid/atomic/paths/root_spec.rb +106 -0
- data/spec/mongoid/atomic/paths_spec.rb +270 -0
- data/spec/mongoid/atomic/positionable_spec.rb +227 -0
- data/spec/mongoid/atomic_spec.rb +365 -0
- data/spec/mongoid/attributes/processing_spec.rb +149 -0
- data/spec/mongoid/attributes/readonly_spec.rb +169 -0
- data/spec/mongoid/attributes_spec.rb +1705 -0
- data/spec/mongoid/callbacks_spec.rb +1564 -0
- data/spec/mongoid/components_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 +334 -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 +525 -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 +1757 -0
- data/spec/mongoid/copyable_spec.rb +393 -0
- data/spec/mongoid/criteria_spec.rb +5140 -0
- data/spec/mongoid/criterion/destructive_spec.rb +101 -0
- data/spec/mongoid/criterion/inspection_spec.rb +27 -0
- data/spec/mongoid/criterion/marshalable_spec.rb +28 -0
- data/spec/mongoid/criterion/modifiable_spec.rb +409 -0
- data/spec/mongoid/criterion/modification_spec.rb +402 -0
- data/spec/mongoid/criterion/scoping_spec.rb +391 -0
- data/spec/mongoid/dirty_spec.rb +1508 -0
- data/spec/mongoid/document_spec.rb +1146 -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/errors/versioning_not_on_root_spec.rb +29 -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 +368 -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/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 +1253 -0
- data/spec/mongoid/finders_spec.rb +321 -0
- data/spec/mongoid/hierarchy_spec.rb +244 -0
- data/spec/mongoid/identity_map_spec.rb +564 -0
- data/spec/mongoid/indexes_spec.rb +404 -0
- data/spec/mongoid/inspection_spec.rb +57 -0
- data/spec/mongoid/json_spec.rb +33 -0
- data/spec/mongoid/loggable_spec.rb +21 -0
- data/spec/mongoid/matchers/all_spec.rb +31 -0
- data/spec/mongoid/matchers/and_spec.rb +162 -0
- data/spec/mongoid/matchers/default_spec.rb +130 -0
- data/spec/mongoid/matchers/exists_spec.rb +57 -0
- data/spec/mongoid/matchers/gt_spec.rb +74 -0
- data/spec/mongoid/matchers/gte_spec.rb +74 -0
- data/spec/mongoid/matchers/in_spec.rb +25 -0
- data/spec/mongoid/matchers/lt_spec.rb +74 -0
- data/spec/mongoid/matchers/lte_spec.rb +74 -0
- data/spec/mongoid/matchers/ne_spec.rb +25 -0
- data/spec/mongoid/matchers/nin_spec.rb +25 -0
- data/spec/mongoid/matchers/or_spec.rb +106 -0
- data/spec/mongoid/matchers/size_spec.rb +25 -0
- data/spec/mongoid/matchers_spec.rb +532 -0
- data/spec/mongoid/multi_parameter_attributes_spec.rb +128 -0
- data/spec/mongoid/nested_attributes_spec.rb +4945 -0
- data/spec/mongoid/observer_spec.rb +290 -0
- data/spec/mongoid/paranoia_spec.rb +759 -0
- data/spec/mongoid/persistence/atomic/add_to_set_spec.rb +262 -0
- data/spec/mongoid/persistence/atomic/bit_spec.rb +88 -0
- data/spec/mongoid/persistence/atomic/inc_spec.rb +133 -0
- data/spec/mongoid/persistence/atomic/pop_spec.rb +111 -0
- data/spec/mongoid/persistence/atomic/pull_all_spec.rb +77 -0
- data/spec/mongoid/persistence/atomic/pull_spec.rb +80 -0
- data/spec/mongoid/persistence/atomic/push_all_spec.rb +77 -0
- data/spec/mongoid/persistence/atomic/push_spec.rb +77 -0
- data/spec/mongoid/persistence/atomic/rename_spec.rb +42 -0
- data/spec/mongoid/persistence/atomic/sets_spec.rb +154 -0
- data/spec/mongoid/persistence/atomic/unset_spec.rb +65 -0
- data/spec/mongoid/persistence/atomic_spec.rb +216 -0
- data/spec/mongoid/persistence/operations/embedded/insert_spec.rb +191 -0
- data/spec/mongoid/persistence/operations/embedded/remove_spec.rb +8 -0
- data/spec/mongoid/persistence/operations/insert_spec.rb +149 -0
- data/spec/mongoid/persistence/operations/remove_spec.rb +113 -0
- data/spec/mongoid/persistence/operations/update_spec.rb +141 -0
- data/spec/mongoid/persistence/operations/upsert_spec.rb +59 -0
- data/spec/mongoid/persistence/operations_spec.rb +313 -0
- data/spec/mongoid/persistence_spec.rb +2279 -0
- data/spec/mongoid/railties/document_spec.rb +24 -0
- data/spec/mongoid/relations/accessors_spec.rb +844 -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 +580 -0
- data/spec/mongoid/relations/embedded/many_spec.rb +3841 -0
- data/spec/mongoid/relations/embedded/one_spec.rb +1055 -0
- data/spec/mongoid/relations/macros_spec.rb +625 -0
- data/spec/mongoid/relations/metadata_spec.rb +2030 -0
- data/spec/mongoid/relations/options_spec.rb +35 -0
- data/spec/mongoid/relations/polymorphic_spec.rb +132 -0
- data/spec/mongoid/relations/proxy_spec.rb +48 -0
- data/spec/mongoid/relations/referenced/in_spec.rb +1501 -0
- data/spec/mongoid/relations/referenced/many_spec.rb +3632 -0
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +3561 -0
- data/spec/mongoid/relations/referenced/one_spec.rb +1331 -0
- data/spec/mongoid/relations/reflections_spec.rb +101 -0
- data/spec/mongoid/relations/synchronization_spec.rb +453 -0
- data/spec/mongoid/relations/targets/enumerable_spec.rb +1710 -0
- data/spec/mongoid/relations_spec.rb +188 -0
- data/spec/mongoid/reloading_spec.rb +305 -0
- data/spec/mongoid/scoping_spec.rb +978 -0
- data/spec/mongoid/serialization_spec.rb +833 -0
- data/spec/mongoid/sessions/factory_spec.rb +312 -0
- data/spec/mongoid/sessions/mongo_uri_spec.rb +103 -0
- data/spec/mongoid/sessions_spec.rb +1111 -0
- data/spec/mongoid/sharding_spec.rb +61 -0
- data/spec/mongoid/state_spec.rb +102 -0
- data/spec/mongoid/threaded_spec.rb +296 -0
- data/spec/mongoid/timestamps/created/short_spec.rb +51 -0
- data/spec/mongoid/timestamps/created_spec.rb +44 -0
- data/spec/mongoid/timestamps/timeless_spec.rb +130 -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/unit_of_work_spec.rb +196 -0
- data/spec/mongoid/validations/associated_spec.rb +183 -0
- data/spec/mongoid/validations/format_spec.rb +83 -0
- data/spec/mongoid/validations/length_spec.rb +223 -0
- data/spec/mongoid/validations/numericality_spec.rb +30 -0
- data/spec/mongoid/validations/presence_spec.rb +592 -0
- data/spec/mongoid/validations/uniqueness_spec.rb +2399 -0
- data/spec/mongoid/validations_spec.rb +309 -0
- data/spec/mongoid/versioning_spec.rb +540 -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 +93 -0
- metadata +826 -6
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Mongoid::Attributes::Processing do
|
|
4
|
+
|
|
5
|
+
describe "#process_attributes" do
|
|
6
|
+
|
|
7
|
+
let(:building) do
|
|
8
|
+
Building.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context "when setting embedded documents via the parent" do
|
|
12
|
+
|
|
13
|
+
let(:attributes) do
|
|
14
|
+
{
|
|
15
|
+
building_address: { city: "Berlin" },
|
|
16
|
+
contractors: [{ name: "Joe" }]
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "when providing a role" do
|
|
21
|
+
|
|
22
|
+
context "when creating new documents" do
|
|
23
|
+
|
|
24
|
+
before do
|
|
25
|
+
building.process_attributes(attributes, :admin, true)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
let(:building_address) do
|
|
29
|
+
building.building_address
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
let(:contractor) do
|
|
33
|
+
building.contractors.first
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context "when the child fields are accessible to the role" do
|
|
37
|
+
|
|
38
|
+
it "sets the fields on the 1-1 child" do
|
|
39
|
+
building_address.city.should eq("Berlin")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "sets the fields on the 1-n child" do
|
|
43
|
+
contractor.name.should eq("Joe")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "when updating the document" do
|
|
48
|
+
|
|
49
|
+
let(:updates) do
|
|
50
|
+
{
|
|
51
|
+
building_address: { city: "Kiew" },
|
|
52
|
+
contractors: [{ name: "Jim" }]
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
before do
|
|
57
|
+
building.process_attributes(updates, :admin, true)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "updates the 1-1 child" do
|
|
61
|
+
building_address.city.should eq("Kiew")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "updates the 1-n child" do
|
|
65
|
+
contractor.name.should eq("Jim")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "when turning off mass assignment" do
|
|
72
|
+
|
|
73
|
+
context "when creating new documents" do
|
|
74
|
+
|
|
75
|
+
before do
|
|
76
|
+
building.process_attributes(attributes, :default, false)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
let(:building_address) do
|
|
80
|
+
building.building_address
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
let(:contractor) do
|
|
84
|
+
building.contractors.first
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context "when the child fields are accessible to the role" do
|
|
88
|
+
|
|
89
|
+
it "sets the fields on the 1-1 child" do
|
|
90
|
+
building_address.city.should eq("Berlin")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "sets the fields on the 1-n child" do
|
|
94
|
+
contractor.name.should eq("Joe")
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context "when updating the document" do
|
|
99
|
+
|
|
100
|
+
let(:updates) do
|
|
101
|
+
{
|
|
102
|
+
building_address: { city: "Kiew" },
|
|
103
|
+
contractors: [{ name: "Jim" }]
|
|
104
|
+
}
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
before do
|
|
108
|
+
building.process_attributes(updates, :default, false)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "updates the 1-1 child" do
|
|
112
|
+
building_address.city.should eq("Kiew")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "updates the 1-n child" do
|
|
116
|
+
contractor.name.should eq("Jim")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context "with a key that is not a valid ruby identifier" do
|
|
120
|
+
let(:dynamic_updates) do
|
|
121
|
+
{
|
|
122
|
+
building_address: { :"postal-code" => "V8N 1A1" },
|
|
123
|
+
contractors: [{ :"license number" => "12345" }]
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
before do
|
|
128
|
+
building.process_attributes(dynamic_updates, :default, false)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "updates the 1-1 child" do
|
|
132
|
+
building_address['postal-code'].should eq("V8N 1A1")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "updates the 1-n child" do
|
|
136
|
+
contractor['license number'].should eq("12345")
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "correctly handles a second call to #process_attributes" do
|
|
140
|
+
building.process_attributes(dynamic_updates, :default, false)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Mongoid::Attributes::Readonly do
|
|
4
|
+
|
|
5
|
+
describe ".attr_readonly" do
|
|
6
|
+
|
|
7
|
+
after do
|
|
8
|
+
Person.readonly_attributes.clear
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context "when providing a single field" do
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
Person.attr_readonly :title
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "adds the field to readonly attributes" do
|
|
18
|
+
Person.readonly_attributes.to_a.should eq([ "title" ])
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "when providing multiple fields" do
|
|
23
|
+
|
|
24
|
+
before do
|
|
25
|
+
Person.attr_readonly :title, :terms
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "adds the fields to readonly attributes" do
|
|
29
|
+
Person.readonly_attributes.to_a.should eq([ "title", "terms" ])
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "when creating a new document with a readonly field" do
|
|
34
|
+
|
|
35
|
+
before do
|
|
36
|
+
Person.attr_readonly :title, :terms
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
let(:person) do
|
|
40
|
+
Person.create(title: "sir", terms: true)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "sets the first readonly value" do
|
|
44
|
+
person.title.should eq("sir")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "sets subsequent readonly values" do
|
|
48
|
+
person.terms.should be_true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "persists the first readonly value" do
|
|
52
|
+
person.reload.title.should eq("sir")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "persists subsequent readonly values" do
|
|
56
|
+
person.reload.terms.should be_true
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context "when updating an existing readonly field" do
|
|
61
|
+
|
|
62
|
+
before do
|
|
63
|
+
Person.attr_readonly :title, :terms
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
let(:person) do
|
|
67
|
+
Person.create(title: "sir", terms: true)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "when updating via the setter" do
|
|
71
|
+
|
|
72
|
+
before do
|
|
73
|
+
person.title = "mr"
|
|
74
|
+
person.save
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "does not update the field" do
|
|
78
|
+
person.title.should eq("sir")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "does not persist the changes" do
|
|
82
|
+
person.reload.title.should eq("sir")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context "when updating via []=" do
|
|
87
|
+
|
|
88
|
+
before do
|
|
89
|
+
person[:title] = "mr"
|
|
90
|
+
person.save
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "does not update the field" do
|
|
94
|
+
person.title.should eq("sir")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "does not persist the changes" do
|
|
98
|
+
person.reload.title.should eq("sir")
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context "when updating via write_attribute" do
|
|
103
|
+
|
|
104
|
+
before do
|
|
105
|
+
person.write_attribute(:title, "mr")
|
|
106
|
+
person.save
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "does not update the field" do
|
|
110
|
+
person.title.should eq("sir")
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "does not persist the changes" do
|
|
114
|
+
person.reload.title.should eq("sir")
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
context "when updating via update_attributes" do
|
|
119
|
+
|
|
120
|
+
before do
|
|
121
|
+
person.update_attributes(title: "mr")
|
|
122
|
+
person.save
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "does not update the field" do
|
|
126
|
+
person.title.should eq("sir")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "does not persist the changes" do
|
|
130
|
+
person.reload.title.should eq("sir")
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context "when updating via update_attributes!" do
|
|
135
|
+
|
|
136
|
+
before do
|
|
137
|
+
person.update_attributes!(title: "mr")
|
|
138
|
+
person.save
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "does not update the field" do
|
|
142
|
+
person.title.should eq("sir")
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "does not persist the changes" do
|
|
146
|
+
person.reload.title.should eq("sir")
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
context "when updating via update_attribute" do
|
|
151
|
+
|
|
152
|
+
it "raises an error" do
|
|
153
|
+
expect {
|
|
154
|
+
person.update_attribute(:title, "mr")
|
|
155
|
+
}.to raise_error(Mongoid::Errors::ReadonlyAttribute)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context "when updating via remove_attribute" do
|
|
160
|
+
|
|
161
|
+
it "raises an error" do
|
|
162
|
+
expect {
|
|
163
|
+
person.remove_attribute(:title)
|
|
164
|
+
}.to raise_error(Mongoid::Errors::ReadonlyAttribute)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
@@ -0,0 +1,1705 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Mongoid::Attributes do
|
|
4
|
+
|
|
5
|
+
describe "\#{attribute}" do
|
|
6
|
+
|
|
7
|
+
context "when setting the value in the getter" do
|
|
8
|
+
|
|
9
|
+
let(:account) do
|
|
10
|
+
Account.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "does not cause an infinite loop" do
|
|
14
|
+
account.overridden.should eq("not recommended")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "#[]" do
|
|
20
|
+
|
|
21
|
+
context "when the document is a new record" do
|
|
22
|
+
|
|
23
|
+
let(:person) do
|
|
24
|
+
Person.new
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "when accessing a localized field" do
|
|
28
|
+
|
|
29
|
+
before do
|
|
30
|
+
person.desc = "testing"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "when passing just the name" do
|
|
34
|
+
|
|
35
|
+
it "returns the full value" do
|
|
36
|
+
person[:desc].should eq("en" => "testing")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "when passing the name with locale" do
|
|
41
|
+
|
|
42
|
+
it "returns the value for the locale" do
|
|
43
|
+
person["desc.en"].should eq("testing")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "when attribute does not exist" do
|
|
49
|
+
|
|
50
|
+
it "returns the default value" do
|
|
51
|
+
person[:age].should eq(100)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context "when attribute is not accessible" do
|
|
56
|
+
|
|
57
|
+
before do
|
|
58
|
+
person.owner_id = 5
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "returns the value" do
|
|
62
|
+
person[:owner_id].should eq(5)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "when the document is an existing record" do
|
|
68
|
+
|
|
69
|
+
let!(:person) do
|
|
70
|
+
Person.create(title: "sir")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "when the attribute does not exist" do
|
|
74
|
+
|
|
75
|
+
before do
|
|
76
|
+
person.collection
|
|
77
|
+
.find({ _id: person.id })
|
|
78
|
+
.update({ "$unset" => { age: 1 }})
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context "when found" do
|
|
82
|
+
|
|
83
|
+
let(:found) do
|
|
84
|
+
Person.find(person.id)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "returns the default value" do
|
|
88
|
+
found[:age].should eq(100)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context "when reloaded" do
|
|
93
|
+
|
|
94
|
+
before do
|
|
95
|
+
Mongoid.raise_not_found_error = false
|
|
96
|
+
person.reload
|
|
97
|
+
Mongoid.raise_not_found_error = true
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "returns the default value" do
|
|
101
|
+
person[:age].should eq(100)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
describe "#[]=" do
|
|
109
|
+
|
|
110
|
+
let(:person) do
|
|
111
|
+
Person.new
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
context "when setting the attribute to nil" do
|
|
115
|
+
|
|
116
|
+
before do
|
|
117
|
+
person[:age] = nil
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "does not use the default value" do
|
|
121
|
+
person.age.should be_nil
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
context "when field has a default value" do
|
|
126
|
+
|
|
127
|
+
before do
|
|
128
|
+
person[:terms] = true
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "allows overwriting of the default value" do
|
|
132
|
+
person.terms.should be_true
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
describe ".attr_accessible" do
|
|
138
|
+
|
|
139
|
+
context "when the field is not _id" do
|
|
140
|
+
|
|
141
|
+
let(:account) do
|
|
142
|
+
Account.new(number: 999999)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "prevents setting via mass assignment" do
|
|
146
|
+
account.number.should be_nil
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
context "when the field is _id" do
|
|
151
|
+
|
|
152
|
+
let(:account) do
|
|
153
|
+
Account.new(_id: "ABBA")
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it "prevents setting via mass assignment" do
|
|
157
|
+
account._id.should_not eq("ABBA")
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
context "when using instantiate" do
|
|
162
|
+
|
|
163
|
+
let(:account) do
|
|
164
|
+
Account.instantiate("_id" => "1", "balance" => "ABBA")
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "ignores any protected attribute" do
|
|
168
|
+
account.balance.should eq("ABBA")
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
context "when using override" do
|
|
173
|
+
|
|
174
|
+
let(:account) do
|
|
175
|
+
Account.new
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "ignores any protected attribute" do
|
|
179
|
+
account.write_attributes({balance: "ABBA"}, false)
|
|
180
|
+
account.balance.should eq("ABBA")
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
context "when mass assignment role is indicated" do
|
|
185
|
+
|
|
186
|
+
context "when attributes assigned from default role" do
|
|
187
|
+
|
|
188
|
+
let(:article) do
|
|
189
|
+
Article.new(
|
|
190
|
+
title: "Some Title",
|
|
191
|
+
is_rss: true,
|
|
192
|
+
user_login: "SomeLogin"
|
|
193
|
+
)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it "sets the title field for default role" do
|
|
197
|
+
article.title.should eq("Some Title")
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it "sets the user login field for the default role" do
|
|
201
|
+
article.user_login.should eq("SomeLogin")
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "sets the rss field for the default role" do
|
|
205
|
+
article.is_rss.should be_false
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
context "when attributes assigned from parser role" do
|
|
210
|
+
|
|
211
|
+
let(:article) do
|
|
212
|
+
Article.new({
|
|
213
|
+
title: "Some Title",
|
|
214
|
+
is_rss: true,
|
|
215
|
+
user_login: "SomeLogin"
|
|
216
|
+
}, as: :parser
|
|
217
|
+
)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it "sets the title field" do
|
|
221
|
+
article.title.should eq("Some Title")
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it "sets the rss field" do
|
|
225
|
+
article.is_rss.should be_true
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it "does not set the user login field" do
|
|
229
|
+
article.user_login.should be_nil
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
context "when attributes assigned without protection" do
|
|
234
|
+
|
|
235
|
+
let(:article) do
|
|
236
|
+
Article.new(
|
|
237
|
+
{ title: "Some Title",
|
|
238
|
+
is_rss: true,
|
|
239
|
+
user_login: "SomeLogin"
|
|
240
|
+
}, without_protection: true
|
|
241
|
+
)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it "sets the title field" do
|
|
245
|
+
article.title.should eq("Some Title")
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it "sets the user login field" do
|
|
249
|
+
article.user_login.should eq("SomeLogin")
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it "sets the rss field" do
|
|
253
|
+
article.is_rss.should be_true
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
describe ".attr_protected" do
|
|
260
|
+
|
|
261
|
+
context "when the field is not _id" do
|
|
262
|
+
|
|
263
|
+
let(:person) do
|
|
264
|
+
Person.new(security_code: "ABBA")
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it "prevents setting via mass assignment" do
|
|
268
|
+
person.security_code.should be_nil
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
context "when the field is _id" do
|
|
273
|
+
|
|
274
|
+
let(:game) do
|
|
275
|
+
Game.new(_id: "ABBA")
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it "prevents setting via mass assignment" do
|
|
279
|
+
game._id.should_not eq("ABBA")
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
context "when using instantiate" do
|
|
284
|
+
|
|
285
|
+
let(:person) do
|
|
286
|
+
Person.instantiate("_id" => "1", "security_code" => "ABBA")
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "ignores any protected attribute" do
|
|
290
|
+
person.security_code.should eq("ABBA")
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
context "when using override" do
|
|
295
|
+
|
|
296
|
+
let(:person) do
|
|
297
|
+
Person.new
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it "ignores any protected attribute" do
|
|
301
|
+
person.write_attributes({security_code: "ABBA"}, false)
|
|
302
|
+
person.security_code.should eq("ABBA")
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
context "when mass assignment role is indicated" do
|
|
307
|
+
|
|
308
|
+
let(:item) do
|
|
309
|
+
Item.new
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
context "when attributes assigned from default role" do
|
|
313
|
+
|
|
314
|
+
before do
|
|
315
|
+
item.assign_attributes(
|
|
316
|
+
title: "Some Title",
|
|
317
|
+
is_rss: true,
|
|
318
|
+
user_login: "SomeLogin"
|
|
319
|
+
)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it "sets the field for the default role" do
|
|
323
|
+
item.is_rss.should be_true
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
it "does not set the field for non default role title" do
|
|
327
|
+
item.title.should be_nil
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
it "does not set the field for non default role user login" do
|
|
331
|
+
item.user_login.should be_nil
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
context "when attributes assigned from parser role" do
|
|
336
|
+
|
|
337
|
+
before do
|
|
338
|
+
item.assign_attributes(
|
|
339
|
+
{ title: "Some Title",
|
|
340
|
+
is_rss: true,
|
|
341
|
+
user_login: "SomeLogin" }, as: :parser
|
|
342
|
+
)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
it "sets the user login field for parser role" do
|
|
346
|
+
item.user_login.should eq("SomeLogin")
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
it "sets the is rss field for parse role" do
|
|
350
|
+
item.is_rss.should be_false
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
it "does not set the title field" do
|
|
354
|
+
item.title.should be_nil
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
context "when attributes assigned without protection" do
|
|
359
|
+
|
|
360
|
+
before do
|
|
361
|
+
item.assign_attributes(
|
|
362
|
+
{ title: "Some Title",
|
|
363
|
+
is_rss: true,
|
|
364
|
+
user_login: "SomeLogin"
|
|
365
|
+
}, without_protection: true
|
|
366
|
+
)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it "sets the title attribute" do
|
|
370
|
+
item.title.should eq("Some Title")
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
it "sets the user login attribute" do
|
|
374
|
+
item.user_login.should eq("SomeLogin")
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
it "sets the rss attribute" do
|
|
378
|
+
item.is_rss.should be_true
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
describe "#_id" do
|
|
385
|
+
|
|
386
|
+
let(:person) do
|
|
387
|
+
Person.new
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
it "delegates to #id" do
|
|
391
|
+
person._id.should eq(person.id)
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
describe "#_id=" do
|
|
396
|
+
|
|
397
|
+
after(:all) do
|
|
398
|
+
Person.field(
|
|
399
|
+
:_id,
|
|
400
|
+
type: Moped::BSON::ObjectId,
|
|
401
|
+
pre_processed: true,
|
|
402
|
+
default: ->{ Moped::BSON::ObjectId.new }
|
|
403
|
+
)
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
context "when using object ids" do
|
|
407
|
+
|
|
408
|
+
before(:all) do
|
|
409
|
+
Person.field(
|
|
410
|
+
:_id,
|
|
411
|
+
type: Moped::BSON::ObjectId,
|
|
412
|
+
pre_processed: true,
|
|
413
|
+
default: ->{ Moped::BSON::ObjectId.new }
|
|
414
|
+
)
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
let(:person) do
|
|
418
|
+
Person.new
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
let(:bson_id) do
|
|
422
|
+
Moped::BSON::ObjectId.new
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
context "when providing an object id" do
|
|
426
|
+
|
|
427
|
+
before do
|
|
428
|
+
person._id = bson_id
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
it "sets the id as the object id" do
|
|
432
|
+
person.id.should eq(bson_id)
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
context "when providing a string" do
|
|
437
|
+
|
|
438
|
+
before do
|
|
439
|
+
person._id = bson_id.to_s
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
it "sets the id as the object id" do
|
|
443
|
+
person.id.should eq(bson_id)
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
context "when providing an integer" do
|
|
448
|
+
|
|
449
|
+
before do
|
|
450
|
+
person._id = 2
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
it "sets the id as the supplied value to_s" do
|
|
454
|
+
person.id.should eq(2)
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
context "when using string ids" do
|
|
460
|
+
|
|
461
|
+
before(:all) do
|
|
462
|
+
Person.field(
|
|
463
|
+
:_id,
|
|
464
|
+
type: String,
|
|
465
|
+
pre_processed: true,
|
|
466
|
+
default: ->{ Moped::BSON::ObjectId.new.to_s }
|
|
467
|
+
)
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
let(:person) do
|
|
471
|
+
Person.new
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
let(:bson_id) do
|
|
475
|
+
Moped::BSON::ObjectId.new
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
context "when providing an object id" do
|
|
479
|
+
|
|
480
|
+
before do
|
|
481
|
+
person._id = bson_id
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
it "sets the id as the string of the object id" do
|
|
485
|
+
person.id.should eq(bson_id.to_s)
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
context "when providing a string" do
|
|
490
|
+
|
|
491
|
+
before do
|
|
492
|
+
person._id = bson_id.to_s
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
it "sets the id as the string" do
|
|
496
|
+
person.id.should eq(bson_id.to_s)
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
context "when providing an integer" do
|
|
501
|
+
|
|
502
|
+
before do
|
|
503
|
+
person._id = 2
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
it "sets the id as the supplied value to_s" do
|
|
507
|
+
person.id.should eq("2")
|
|
508
|
+
end
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
context "when using integer ids" do
|
|
513
|
+
|
|
514
|
+
before(:all) do
|
|
515
|
+
Person.field(:_id, type: Integer)
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
let(:person) do
|
|
519
|
+
Person.new
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
context "when providing a string" do
|
|
523
|
+
|
|
524
|
+
before do
|
|
525
|
+
person._id = 1.to_s
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
it "sets the id as the integer" do
|
|
529
|
+
person.id.should eq(1)
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
context "when providing an integer" do
|
|
534
|
+
|
|
535
|
+
before do
|
|
536
|
+
person._id = 2
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
it "sets the id as the supplied value" do
|
|
540
|
+
person.id.should eq(2)
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
describe "#method_missing" do
|
|
547
|
+
|
|
548
|
+
let(:attributes) do
|
|
549
|
+
{ testing: "Testing" }
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
let(:person) do
|
|
553
|
+
Person.new(attributes)
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
before do
|
|
557
|
+
Mongoid.configure.allow_dynamic_fields = true
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
context "when an attribute exists" do
|
|
561
|
+
|
|
562
|
+
it "allows the getter" do
|
|
563
|
+
person.testing.should eq("Testing")
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
it "allows the setter" do
|
|
567
|
+
person.testing = "Test"
|
|
568
|
+
person.testing.should eq("Test")
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
it "allows the getter before_type_cast" do
|
|
572
|
+
person.testing_before_type_cast.should eq("Testing")
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
it "returns true for respond_to?" do
|
|
576
|
+
person.respond_to?(:testing).should be_true
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
context "when the provided value needs mongoization" do
|
|
581
|
+
|
|
582
|
+
let(:new_years) do
|
|
583
|
+
DateTime.new(2013, 1, 1, 0, 0, 0)
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
before do
|
|
587
|
+
person[:new_years] = new_years
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
it "mongoizes the dynamic field" do
|
|
591
|
+
person.new_years.should be_a(Time)
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
it "keeps the same value" do
|
|
595
|
+
person.new_years.should eq(new_years)
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
describe "#process" do
|
|
601
|
+
|
|
602
|
+
context "when passing non accessible fields" do
|
|
603
|
+
|
|
604
|
+
let(:person) do
|
|
605
|
+
Person.new(owner_id: 6)
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
it "does not set the value" do
|
|
609
|
+
person.owner_id.should be_nil
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
context "when attributes dont have fields defined" do
|
|
614
|
+
|
|
615
|
+
let(:attributes) do
|
|
616
|
+
{
|
|
617
|
+
nofieldstring: "Testing",
|
|
618
|
+
nofieldint: 5,
|
|
619
|
+
employer: Employer.new
|
|
620
|
+
}
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
context "when allowing dynamic fields" do
|
|
624
|
+
|
|
625
|
+
let!(:person) do
|
|
626
|
+
Person.new(attributes)
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
before do
|
|
630
|
+
Mongoid.configure.allow_dynamic_fields = true
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
context "when attribute is a string" do
|
|
634
|
+
|
|
635
|
+
it "adds the string to the attributes" do
|
|
636
|
+
person.attributes["nofieldstring"].should eq("Testing")
|
|
637
|
+
end
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
context "when attribute is not a string" do
|
|
641
|
+
|
|
642
|
+
it "adds a cast value to the attributes" do
|
|
643
|
+
person.attributes["nofieldint"].should eq(5)
|
|
644
|
+
end
|
|
645
|
+
end
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
context "when not allowing dynamic fields" do
|
|
649
|
+
|
|
650
|
+
let!(:attributes) do
|
|
651
|
+
{ nofieldstring: "Testing" }
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
before do
|
|
655
|
+
Mongoid.configure.allow_dynamic_fields = false
|
|
656
|
+
Person.fields.delete(:nofieldstring)
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
after do
|
|
660
|
+
Mongoid.configure.allow_dynamic_fields = true
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
it "raises an unknown attribute error" do
|
|
664
|
+
expect {
|
|
665
|
+
Person.new({ anothernew: "Test" })
|
|
666
|
+
}.to raise_error(Mongoid::Errors::UnknownAttribute)
|
|
667
|
+
end
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
context "when supplied hash has string values" do
|
|
672
|
+
|
|
673
|
+
let(:bson_id) do
|
|
674
|
+
Moped::BSON::ObjectId.new
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
let!(:attributes) do
|
|
678
|
+
{
|
|
679
|
+
title: "value",
|
|
680
|
+
age: "30",
|
|
681
|
+
terms: "true",
|
|
682
|
+
score: "",
|
|
683
|
+
name: {
|
|
684
|
+
_id: "2", first_name: "Test", last_name: "User"
|
|
685
|
+
},
|
|
686
|
+
addresses: [
|
|
687
|
+
{ _id: "3", street: "First Street" },
|
|
688
|
+
{ _id: "4", street: "Second Street" }
|
|
689
|
+
]
|
|
690
|
+
}
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
let!(:person) do
|
|
694
|
+
Person.new(attributes)
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
it "casts integers" do
|
|
698
|
+
person[:age].should eq(30)
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
it "casts booleans" do
|
|
702
|
+
person[:terms].should be_true
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
it "sets empty strings to nil" do
|
|
706
|
+
person[:score].should be_nil
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
context "when associations provided in the attributes" do
|
|
711
|
+
|
|
712
|
+
context "when association is a has_one" do
|
|
713
|
+
|
|
714
|
+
let(:name) do
|
|
715
|
+
Name.new(first_name: "Testy")
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
let(:attributes) do
|
|
719
|
+
{ name: name }
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
let(:person) do
|
|
723
|
+
Person.new(attributes)
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
it "sets the associations" do
|
|
727
|
+
person.name.should eq(name)
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
context "when association is a references_one" do
|
|
732
|
+
|
|
733
|
+
let(:game) do
|
|
734
|
+
Game.new(score: 100)
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
let(:attributes) do
|
|
738
|
+
{ game: game }
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
let!(:person) do
|
|
742
|
+
Person.new(attributes)
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
it "sets the parent association" do
|
|
746
|
+
person.game.should eq(game)
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
it "sets the inverse association" do
|
|
750
|
+
game.person.should eq(person)
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
context "when association is a embedded_in" do
|
|
755
|
+
|
|
756
|
+
let(:person) do
|
|
757
|
+
Person.new
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
let(:name) do
|
|
761
|
+
Name.new(first_name: "Tyler", person: person)
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
it "sets the association" do
|
|
765
|
+
name.person.should eq(person)
|
|
766
|
+
end
|
|
767
|
+
end
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
context "when non-associations provided in the attributes" do
|
|
771
|
+
|
|
772
|
+
let(:employer) do
|
|
773
|
+
Employer.new
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
let(:attributes) do
|
|
777
|
+
{ employer_id: employer.id, title: "Sir" }
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
let(:person) do
|
|
781
|
+
Person.new(attributes)
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
it "calls the setter for the association" do
|
|
785
|
+
person.employer_id.should eq("1")
|
|
786
|
+
end
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
context "when an empty array is provided in the attributes" do
|
|
790
|
+
|
|
791
|
+
let(:attributes) do
|
|
792
|
+
{ aliases: [] }
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
let(:person) do
|
|
796
|
+
Person.new(attributes)
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
it "sets the empty array" do
|
|
800
|
+
person.aliases.should be_empty
|
|
801
|
+
end
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
context "when an empty hash is provided in the attributes" do
|
|
805
|
+
|
|
806
|
+
let(:attributes) do
|
|
807
|
+
{ map: {} }
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
let(:person) do
|
|
811
|
+
Person.new(attributes)
|
|
812
|
+
end
|
|
813
|
+
|
|
814
|
+
it "sets the empty hash" do
|
|
815
|
+
person.map.should eq({})
|
|
816
|
+
end
|
|
817
|
+
end
|
|
818
|
+
end
|
|
819
|
+
|
|
820
|
+
context "updating when attributes already exist" do
|
|
821
|
+
|
|
822
|
+
let(:person) do
|
|
823
|
+
Person.new(title: "Sir")
|
|
824
|
+
end
|
|
825
|
+
|
|
826
|
+
let(:attributes) do
|
|
827
|
+
{ dob: "2000-01-01" }
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
before do
|
|
831
|
+
person.process_attributes(attributes)
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
it "only overwrites supplied attributes" do
|
|
835
|
+
person.title.should eq("Sir")
|
|
836
|
+
end
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
describe "#read_attribute" do
|
|
840
|
+
|
|
841
|
+
context "when the document is a new record" do
|
|
842
|
+
|
|
843
|
+
let(:person) do
|
|
844
|
+
Person.new
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
context "when attribute does not exist" do
|
|
848
|
+
|
|
849
|
+
it "returns the default value" do
|
|
850
|
+
person.age.should eq(100)
|
|
851
|
+
person.pets.should be_false
|
|
852
|
+
end
|
|
853
|
+
|
|
854
|
+
end
|
|
855
|
+
|
|
856
|
+
context "when attribute is not accessible" do
|
|
857
|
+
|
|
858
|
+
before do
|
|
859
|
+
person.owner_id = 5
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
it "returns the value" do
|
|
863
|
+
person.read_attribute(:owner_id).should eq(5)
|
|
864
|
+
end
|
|
865
|
+
end
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
context "when the document is an existing record" do
|
|
869
|
+
|
|
870
|
+
let(:person) do
|
|
871
|
+
Person.create
|
|
872
|
+
end
|
|
873
|
+
|
|
874
|
+
context "when the attribute does not exist" do
|
|
875
|
+
|
|
876
|
+
before do
|
|
877
|
+
person.collection
|
|
878
|
+
.find({ _id: person.id })
|
|
879
|
+
.update({ "$unset" => { age: 1 }})
|
|
880
|
+
Mongoid.raise_not_found_error = false
|
|
881
|
+
person.reload
|
|
882
|
+
Mongoid.raise_not_found_error = true
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
it "returns the default value" do
|
|
886
|
+
person.age.should eq(100)
|
|
887
|
+
end
|
|
888
|
+
end
|
|
889
|
+
end
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
describe "#read_attribute_before_type_cast" do
|
|
893
|
+
let(:person) do
|
|
894
|
+
Person.create
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
context "when the attribute has not yet been assigned" do
|
|
898
|
+
|
|
899
|
+
it "returns the default value" do
|
|
900
|
+
person.age_before_type_cast.should eq(100)
|
|
901
|
+
end
|
|
902
|
+
end
|
|
903
|
+
|
|
904
|
+
context "after the attribute has been assigned" do
|
|
905
|
+
|
|
906
|
+
it "returns the default value" do
|
|
907
|
+
person.age = "old"
|
|
908
|
+
person.age_before_type_cast.should eq("old")
|
|
909
|
+
end
|
|
910
|
+
end
|
|
911
|
+
end
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
describe "#attribute_present?" do
|
|
915
|
+
|
|
916
|
+
context "when document is a new record" do
|
|
917
|
+
|
|
918
|
+
let(:person) do
|
|
919
|
+
Person.new
|
|
920
|
+
end
|
|
921
|
+
|
|
922
|
+
context "when attribute does not exist" do
|
|
923
|
+
|
|
924
|
+
it "returns false" do
|
|
925
|
+
person.attribute_present?(:owner_id).should be_false
|
|
926
|
+
end
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
context "when attribute does exist" do
|
|
930
|
+
before do
|
|
931
|
+
person.owner_id = 5
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
it "returns true" do
|
|
935
|
+
person.attribute_present?(:owner_id).should be_true
|
|
936
|
+
end
|
|
937
|
+
end
|
|
938
|
+
end
|
|
939
|
+
|
|
940
|
+
context "when the document is an existing record" do
|
|
941
|
+
|
|
942
|
+
let(:person) do
|
|
943
|
+
Person.create
|
|
944
|
+
end
|
|
945
|
+
|
|
946
|
+
context "when the attribute does not exist" do
|
|
947
|
+
|
|
948
|
+
before do
|
|
949
|
+
person.collection
|
|
950
|
+
.find({ _id: person.id })
|
|
951
|
+
.update({ "$unset" => { age: 1 }})
|
|
952
|
+
Mongoid.raise_not_found_error = false
|
|
953
|
+
person.reload
|
|
954
|
+
Mongoid.raise_not_found_error = true
|
|
955
|
+
end
|
|
956
|
+
|
|
957
|
+
it "returns true" do
|
|
958
|
+
person.attribute_present?(:age).should be_true
|
|
959
|
+
end
|
|
960
|
+
end
|
|
961
|
+
end
|
|
962
|
+
|
|
963
|
+
context "when the value is boolean" do
|
|
964
|
+
|
|
965
|
+
let(:person) do
|
|
966
|
+
Person.new
|
|
967
|
+
end
|
|
968
|
+
|
|
969
|
+
context "when attribute does not exist" do
|
|
970
|
+
|
|
971
|
+
context "when the value is true" do
|
|
972
|
+
|
|
973
|
+
it "return true" do
|
|
974
|
+
person.terms = false
|
|
975
|
+
person.attribute_present?(:terms).should be_true
|
|
976
|
+
end
|
|
977
|
+
end
|
|
978
|
+
|
|
979
|
+
context "when the value is false" do
|
|
980
|
+
|
|
981
|
+
it "return true" do
|
|
982
|
+
person.terms = false
|
|
983
|
+
person.attribute_present?(:terms).should be_true
|
|
984
|
+
end
|
|
985
|
+
end
|
|
986
|
+
end
|
|
987
|
+
end
|
|
988
|
+
|
|
989
|
+
context "when the value is blank string" do
|
|
990
|
+
|
|
991
|
+
let(:person) do
|
|
992
|
+
Person.new(title: '')
|
|
993
|
+
end
|
|
994
|
+
|
|
995
|
+
it "return false" do
|
|
996
|
+
person.attribute_present?(:title).should be_false
|
|
997
|
+
end
|
|
998
|
+
end
|
|
999
|
+
end
|
|
1000
|
+
|
|
1001
|
+
describe "#has_attribute?" do
|
|
1002
|
+
|
|
1003
|
+
let(:person) do
|
|
1004
|
+
Person.new(title: "sir")
|
|
1005
|
+
end
|
|
1006
|
+
|
|
1007
|
+
context "when the key is in the attributes" do
|
|
1008
|
+
|
|
1009
|
+
context "when provided a symbol" do
|
|
1010
|
+
|
|
1011
|
+
it "returns true" do
|
|
1012
|
+
person.has_attribute?(:title).should be_true
|
|
1013
|
+
end
|
|
1014
|
+
end
|
|
1015
|
+
|
|
1016
|
+
context "when provided a string" do
|
|
1017
|
+
|
|
1018
|
+
it "returns true" do
|
|
1019
|
+
person.has_attribute?("title").should be_true
|
|
1020
|
+
end
|
|
1021
|
+
end
|
|
1022
|
+
end
|
|
1023
|
+
|
|
1024
|
+
context "when the key is not in the attributes" do
|
|
1025
|
+
|
|
1026
|
+
it "returns false" do
|
|
1027
|
+
person.has_attribute?(:employer_id).should be_false
|
|
1028
|
+
end
|
|
1029
|
+
end
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
describe '#has_attribute_before_type_cast?' do
|
|
1033
|
+
|
|
1034
|
+
let(:person) do
|
|
1035
|
+
Person.new
|
|
1036
|
+
end
|
|
1037
|
+
|
|
1038
|
+
context "before the attribute has been assigned" do
|
|
1039
|
+
|
|
1040
|
+
it "returns false" do
|
|
1041
|
+
person.has_attribute_before_type_cast?(:age).should be_false
|
|
1042
|
+
end
|
|
1043
|
+
end
|
|
1044
|
+
|
|
1045
|
+
context "after the attribute has been assigned" do
|
|
1046
|
+
|
|
1047
|
+
it "returns true" do
|
|
1048
|
+
person.age = 'old'
|
|
1049
|
+
person.has_attribute_before_type_cast?(:age).should be_true
|
|
1050
|
+
end
|
|
1051
|
+
end
|
|
1052
|
+
end
|
|
1053
|
+
|
|
1054
|
+
describe "#remove_attribute" do
|
|
1055
|
+
|
|
1056
|
+
context "when the attribute exists" do
|
|
1057
|
+
|
|
1058
|
+
let(:person) do
|
|
1059
|
+
Person.create(title: "Sir")
|
|
1060
|
+
end
|
|
1061
|
+
|
|
1062
|
+
before do
|
|
1063
|
+
person.remove_attribute(:title)
|
|
1064
|
+
end
|
|
1065
|
+
|
|
1066
|
+
it "removes the attribute" do
|
|
1067
|
+
person.title.should be_nil
|
|
1068
|
+
end
|
|
1069
|
+
|
|
1070
|
+
it "removes the key from the attributes hash" do
|
|
1071
|
+
person.has_attribute?(:title).should be_false
|
|
1072
|
+
end
|
|
1073
|
+
|
|
1074
|
+
context "when saving after the removal" do
|
|
1075
|
+
|
|
1076
|
+
before do
|
|
1077
|
+
person.save
|
|
1078
|
+
end
|
|
1079
|
+
|
|
1080
|
+
it "persists the removal" do
|
|
1081
|
+
person.reload.has_attribute?(:title).should be_false
|
|
1082
|
+
end
|
|
1083
|
+
end
|
|
1084
|
+
end
|
|
1085
|
+
|
|
1086
|
+
context "when the attribute exists in embedded document" do
|
|
1087
|
+
|
|
1088
|
+
let(:pet) do
|
|
1089
|
+
Animal.new(name: "Cat")
|
|
1090
|
+
end
|
|
1091
|
+
|
|
1092
|
+
let(:person) do
|
|
1093
|
+
Person.new(pet: pet)
|
|
1094
|
+
end
|
|
1095
|
+
|
|
1096
|
+
before do
|
|
1097
|
+
person.save
|
|
1098
|
+
person.pet.remove_attribute(:name)
|
|
1099
|
+
end
|
|
1100
|
+
|
|
1101
|
+
it "removes the attribute" do
|
|
1102
|
+
person.pet.name.should be_nil
|
|
1103
|
+
end
|
|
1104
|
+
|
|
1105
|
+
it "removes the key from the attributes hash" do
|
|
1106
|
+
person.pet.has_attribute?(:name).should be_false
|
|
1107
|
+
end
|
|
1108
|
+
|
|
1109
|
+
context "when saving after the removal" do
|
|
1110
|
+
|
|
1111
|
+
before do
|
|
1112
|
+
person.save
|
|
1113
|
+
end
|
|
1114
|
+
|
|
1115
|
+
it "persists the removal" do
|
|
1116
|
+
person.reload.pet.has_attribute?(:name).should be_false
|
|
1117
|
+
end
|
|
1118
|
+
end
|
|
1119
|
+
|
|
1120
|
+
end
|
|
1121
|
+
|
|
1122
|
+
context "when the attribute does not exist" do
|
|
1123
|
+
|
|
1124
|
+
let(:person) do
|
|
1125
|
+
Person.new
|
|
1126
|
+
end
|
|
1127
|
+
|
|
1128
|
+
before do
|
|
1129
|
+
person.remove_attribute(:title)
|
|
1130
|
+
end
|
|
1131
|
+
|
|
1132
|
+
it "does not fail" do
|
|
1133
|
+
person.title.should be_nil
|
|
1134
|
+
end
|
|
1135
|
+
end
|
|
1136
|
+
|
|
1137
|
+
context "when the document is new" do
|
|
1138
|
+
|
|
1139
|
+
let(:person) do
|
|
1140
|
+
Person.new(title: "sir")
|
|
1141
|
+
end
|
|
1142
|
+
|
|
1143
|
+
before do
|
|
1144
|
+
person.remove_attribute(:title)
|
|
1145
|
+
end
|
|
1146
|
+
|
|
1147
|
+
it "does not add a delayed unset operation" do
|
|
1148
|
+
person.delayed_atomic_unsets.should be_empty
|
|
1149
|
+
end
|
|
1150
|
+
end
|
|
1151
|
+
end
|
|
1152
|
+
|
|
1153
|
+
describe "#respond_to?" do
|
|
1154
|
+
|
|
1155
|
+
context "when allowing dynamic fields" do
|
|
1156
|
+
|
|
1157
|
+
let(:person) do
|
|
1158
|
+
Person.new
|
|
1159
|
+
end
|
|
1160
|
+
|
|
1161
|
+
before(:all) do
|
|
1162
|
+
Mongoid.allow_dynamic_fields = true
|
|
1163
|
+
end
|
|
1164
|
+
|
|
1165
|
+
context "when asking for the getter" do
|
|
1166
|
+
|
|
1167
|
+
context "when the attribute exists" do
|
|
1168
|
+
|
|
1169
|
+
before do
|
|
1170
|
+
person[:attr] = "test"
|
|
1171
|
+
end
|
|
1172
|
+
|
|
1173
|
+
it "returns true" do
|
|
1174
|
+
person.should respond_to(:attr)
|
|
1175
|
+
end
|
|
1176
|
+
end
|
|
1177
|
+
|
|
1178
|
+
context "when the attribute does not exist" do
|
|
1179
|
+
|
|
1180
|
+
it "returns false" do
|
|
1181
|
+
person.should_not respond_to(:attr)
|
|
1182
|
+
end
|
|
1183
|
+
end
|
|
1184
|
+
end
|
|
1185
|
+
|
|
1186
|
+
context "when asking for the setter" do
|
|
1187
|
+
|
|
1188
|
+
context "when the attribute exists" do
|
|
1189
|
+
|
|
1190
|
+
before do
|
|
1191
|
+
person[:attr] = "test"
|
|
1192
|
+
end
|
|
1193
|
+
|
|
1194
|
+
it "returns true" do
|
|
1195
|
+
person.should respond_to(:attr=)
|
|
1196
|
+
end
|
|
1197
|
+
end
|
|
1198
|
+
|
|
1199
|
+
context "when the attribute does not exist" do
|
|
1200
|
+
|
|
1201
|
+
it "returns false" do
|
|
1202
|
+
person.should_not respond_to(:attr=)
|
|
1203
|
+
end
|
|
1204
|
+
end
|
|
1205
|
+
end
|
|
1206
|
+
end
|
|
1207
|
+
|
|
1208
|
+
context "when not allowing dynamic fields" do
|
|
1209
|
+
|
|
1210
|
+
let(:person) do
|
|
1211
|
+
Person.new
|
|
1212
|
+
end
|
|
1213
|
+
|
|
1214
|
+
before(:all) do
|
|
1215
|
+
Mongoid.allow_dynamic_fields = false
|
|
1216
|
+
end
|
|
1217
|
+
|
|
1218
|
+
after(:all) do
|
|
1219
|
+
Mongoid.allow_dynamic_fields = true
|
|
1220
|
+
end
|
|
1221
|
+
|
|
1222
|
+
context "when asking for the getter" do
|
|
1223
|
+
|
|
1224
|
+
it "returns false" do
|
|
1225
|
+
person.should_not respond_to(:attr)
|
|
1226
|
+
end
|
|
1227
|
+
end
|
|
1228
|
+
|
|
1229
|
+
context "when asking for the setter" do
|
|
1230
|
+
|
|
1231
|
+
it "returns false" do
|
|
1232
|
+
person.should_not respond_to(:attr=)
|
|
1233
|
+
end
|
|
1234
|
+
end
|
|
1235
|
+
end
|
|
1236
|
+
end
|
|
1237
|
+
|
|
1238
|
+
describe "#write_attribute" do
|
|
1239
|
+
|
|
1240
|
+
context "when attribute does not exist" do
|
|
1241
|
+
|
|
1242
|
+
let(:person) do
|
|
1243
|
+
Person.new
|
|
1244
|
+
end
|
|
1245
|
+
|
|
1246
|
+
it "returns the default value" do
|
|
1247
|
+
person.age.should eq(100)
|
|
1248
|
+
end
|
|
1249
|
+
end
|
|
1250
|
+
|
|
1251
|
+
context "when setting an attribute that needs type casting" do
|
|
1252
|
+
let(:person) do
|
|
1253
|
+
Person.new(age: "old")
|
|
1254
|
+
end
|
|
1255
|
+
|
|
1256
|
+
it "should store the attribute before type cast" do
|
|
1257
|
+
person.age_before_type_cast.should eq("old")
|
|
1258
|
+
end
|
|
1259
|
+
end
|
|
1260
|
+
|
|
1261
|
+
context "when setting the attribute to nil" do
|
|
1262
|
+
|
|
1263
|
+
let(:person) do
|
|
1264
|
+
Person.new(age: nil)
|
|
1265
|
+
end
|
|
1266
|
+
|
|
1267
|
+
it "does not use the default value" do
|
|
1268
|
+
person.age.should be_nil
|
|
1269
|
+
end
|
|
1270
|
+
end
|
|
1271
|
+
|
|
1272
|
+
context "when field has a default value" do
|
|
1273
|
+
|
|
1274
|
+
let(:person) do
|
|
1275
|
+
Person.new
|
|
1276
|
+
end
|
|
1277
|
+
|
|
1278
|
+
before do
|
|
1279
|
+
person.terms = true
|
|
1280
|
+
end
|
|
1281
|
+
|
|
1282
|
+
it "allows overwriting of the default value" do
|
|
1283
|
+
person.terms.should be_true
|
|
1284
|
+
end
|
|
1285
|
+
end
|
|
1286
|
+
|
|
1287
|
+
context "when attribute has an aliased name" do
|
|
1288
|
+
|
|
1289
|
+
let(:person) do
|
|
1290
|
+
Person.new
|
|
1291
|
+
end
|
|
1292
|
+
|
|
1293
|
+
before(:each) do
|
|
1294
|
+
person.write_attribute(:test, "aliased field to test")
|
|
1295
|
+
end
|
|
1296
|
+
|
|
1297
|
+
it "allows the field name to be udpated" do
|
|
1298
|
+
person.t.should eq("aliased field to test")
|
|
1299
|
+
end
|
|
1300
|
+
end
|
|
1301
|
+
end
|
|
1302
|
+
|
|
1303
|
+
describe "#typed_value_for" do
|
|
1304
|
+
|
|
1305
|
+
let(:person) do
|
|
1306
|
+
Person.new
|
|
1307
|
+
end
|
|
1308
|
+
|
|
1309
|
+
context "when the key has been specified as a field" do
|
|
1310
|
+
|
|
1311
|
+
it "retuns the typed value" do
|
|
1312
|
+
person.send(:typed_value_for, "age", "51")
|
|
1313
|
+
end
|
|
1314
|
+
end
|
|
1315
|
+
|
|
1316
|
+
context "when the key has not been specified as a field" do
|
|
1317
|
+
|
|
1318
|
+
before do
|
|
1319
|
+
person.stub(:fields).and_return({})
|
|
1320
|
+
end
|
|
1321
|
+
|
|
1322
|
+
it "returns the value" do
|
|
1323
|
+
person.send(:typed_value_for, "age", "51").should eq("51")
|
|
1324
|
+
end
|
|
1325
|
+
end
|
|
1326
|
+
end
|
|
1327
|
+
|
|
1328
|
+
describe "#apply_default_attributes" do
|
|
1329
|
+
|
|
1330
|
+
let(:person) do
|
|
1331
|
+
Person.new
|
|
1332
|
+
end
|
|
1333
|
+
|
|
1334
|
+
it "typecasts proc values" do
|
|
1335
|
+
person.age.should eq(100)
|
|
1336
|
+
end
|
|
1337
|
+
end
|
|
1338
|
+
|
|
1339
|
+
[:attributes=, :write_attributes].each do |method|
|
|
1340
|
+
|
|
1341
|
+
describe "##{method}" do
|
|
1342
|
+
|
|
1343
|
+
context "when nested" do
|
|
1344
|
+
|
|
1345
|
+
let(:person) do
|
|
1346
|
+
Person.new
|
|
1347
|
+
end
|
|
1348
|
+
|
|
1349
|
+
before do
|
|
1350
|
+
person.send(method, { videos: [{title: "Fight Club"}] })
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1353
|
+
it "sets nested documents" do
|
|
1354
|
+
person.videos.first.title.should eq("Fight Club")
|
|
1355
|
+
end
|
|
1356
|
+
end
|
|
1357
|
+
|
|
1358
|
+
context "typecasting" do
|
|
1359
|
+
|
|
1360
|
+
let(:person) do
|
|
1361
|
+
Person.new
|
|
1362
|
+
end
|
|
1363
|
+
|
|
1364
|
+
let(:attributes) do
|
|
1365
|
+
{ age: "50" }
|
|
1366
|
+
end
|
|
1367
|
+
|
|
1368
|
+
context "when passing a hash" do
|
|
1369
|
+
|
|
1370
|
+
before do
|
|
1371
|
+
person.send(method, attributes)
|
|
1372
|
+
end
|
|
1373
|
+
|
|
1374
|
+
it "properly casts values" do
|
|
1375
|
+
person.age.should eq(50)
|
|
1376
|
+
end
|
|
1377
|
+
end
|
|
1378
|
+
|
|
1379
|
+
context "when passing nil" do
|
|
1380
|
+
|
|
1381
|
+
before do
|
|
1382
|
+
person.send(method, nil)
|
|
1383
|
+
end
|
|
1384
|
+
|
|
1385
|
+
it "does not set anything" do
|
|
1386
|
+
person.age.should eq(100)
|
|
1387
|
+
end
|
|
1388
|
+
end
|
|
1389
|
+
end
|
|
1390
|
+
|
|
1391
|
+
context "on a parent document" do
|
|
1392
|
+
|
|
1393
|
+
context "when the parent has a has many through a has one" do
|
|
1394
|
+
|
|
1395
|
+
let(:owner) do
|
|
1396
|
+
PetOwner.new(title: "Mr")
|
|
1397
|
+
end
|
|
1398
|
+
|
|
1399
|
+
let(:pet) do
|
|
1400
|
+
Pet.new(name: "Fido")
|
|
1401
|
+
end
|
|
1402
|
+
|
|
1403
|
+
let(:vet_visit) do
|
|
1404
|
+
VetVisit.new(date: Date.today)
|
|
1405
|
+
end
|
|
1406
|
+
|
|
1407
|
+
before do
|
|
1408
|
+
owner.pet = pet
|
|
1409
|
+
pet.vet_visits = [ vet_visit ]
|
|
1410
|
+
owner.send(method, { pet: { name: "Bingo" } })
|
|
1411
|
+
end
|
|
1412
|
+
|
|
1413
|
+
it "does not overwrite child attributes if not in the hash" do
|
|
1414
|
+
owner.pet.name.should eq("Bingo")
|
|
1415
|
+
owner.pet.vet_visits.size.should eq(1)
|
|
1416
|
+
end
|
|
1417
|
+
end
|
|
1418
|
+
|
|
1419
|
+
context "when parent destroy all child on setter" do
|
|
1420
|
+
|
|
1421
|
+
let(:owner) do
|
|
1422
|
+
PetOwner.create!(title: "Mr")
|
|
1423
|
+
end
|
|
1424
|
+
|
|
1425
|
+
let(:pet) do
|
|
1426
|
+
Pet.create!(name: "Kika", pet_owner: owner)
|
|
1427
|
+
end
|
|
1428
|
+
|
|
1429
|
+
let!(:vet_visit) do
|
|
1430
|
+
pet.vet_visits.create!(date: Date.today)
|
|
1431
|
+
end
|
|
1432
|
+
|
|
1433
|
+
before do
|
|
1434
|
+
pet.send(method, { visits_count: 3 })
|
|
1435
|
+
pet.save!
|
|
1436
|
+
end
|
|
1437
|
+
|
|
1438
|
+
it "has 3 new entries" do
|
|
1439
|
+
pet.vet_visits.count.should eq(3)
|
|
1440
|
+
end
|
|
1441
|
+
|
|
1442
|
+
it "persists the changes" do
|
|
1443
|
+
pet.reload.vet_visits.count.should eq(3)
|
|
1444
|
+
end
|
|
1445
|
+
end
|
|
1446
|
+
|
|
1447
|
+
context "when the parent has an empty embeds_many" do
|
|
1448
|
+
|
|
1449
|
+
let(:person) do
|
|
1450
|
+
Person.new
|
|
1451
|
+
end
|
|
1452
|
+
|
|
1453
|
+
let(:attributes) do
|
|
1454
|
+
{ services: [] }
|
|
1455
|
+
end
|
|
1456
|
+
|
|
1457
|
+
it "does not raise an error" do
|
|
1458
|
+
person.send(method, attributes)
|
|
1459
|
+
end
|
|
1460
|
+
end
|
|
1461
|
+
end
|
|
1462
|
+
|
|
1463
|
+
context "on a child document" do
|
|
1464
|
+
|
|
1465
|
+
context "when child is part of a has one" do
|
|
1466
|
+
|
|
1467
|
+
let(:person) do
|
|
1468
|
+
Person.new(title: "Sir", age: 30)
|
|
1469
|
+
end
|
|
1470
|
+
|
|
1471
|
+
let(:name) do
|
|
1472
|
+
Name.new(first_name: "Test", last_name: "User")
|
|
1473
|
+
end
|
|
1474
|
+
|
|
1475
|
+
before do
|
|
1476
|
+
person.name = name
|
|
1477
|
+
name.send(method, first_name: "Test2", last_name: "User2")
|
|
1478
|
+
end
|
|
1479
|
+
|
|
1480
|
+
it "sets the child attributes on the parent" do
|
|
1481
|
+
name.attributes.should eq(
|
|
1482
|
+
{ "_id" => "Test-User", "first_name" => "Test2", "last_name" => "User2" }
|
|
1483
|
+
)
|
|
1484
|
+
end
|
|
1485
|
+
end
|
|
1486
|
+
|
|
1487
|
+
context "when child is part of a has many" do
|
|
1488
|
+
|
|
1489
|
+
let(:person) do
|
|
1490
|
+
Person.new(title: "Sir")
|
|
1491
|
+
end
|
|
1492
|
+
|
|
1493
|
+
let(:address) do
|
|
1494
|
+
Address.new(street: "Test")
|
|
1495
|
+
end
|
|
1496
|
+
|
|
1497
|
+
before do
|
|
1498
|
+
person.addresses << address
|
|
1499
|
+
address.send(method, "street" => "Test2")
|
|
1500
|
+
end
|
|
1501
|
+
|
|
1502
|
+
it "updates the child attributes on the parent" do
|
|
1503
|
+
address.attributes.should eq(
|
|
1504
|
+
{ "_id" => "test", "street" => "Test2" }
|
|
1505
|
+
)
|
|
1506
|
+
end
|
|
1507
|
+
end
|
|
1508
|
+
end
|
|
1509
|
+
end
|
|
1510
|
+
end
|
|
1511
|
+
|
|
1512
|
+
describe "#alias_attribute" do
|
|
1513
|
+
|
|
1514
|
+
let(:product) do
|
|
1515
|
+
Product.new
|
|
1516
|
+
end
|
|
1517
|
+
|
|
1518
|
+
context "when checking against the alias" do
|
|
1519
|
+
|
|
1520
|
+
before do
|
|
1521
|
+
product.cost = 500
|
|
1522
|
+
end
|
|
1523
|
+
|
|
1524
|
+
it "aliases the getter" do
|
|
1525
|
+
product.cost.should eq(500)
|
|
1526
|
+
end
|
|
1527
|
+
|
|
1528
|
+
it "aliases the existance check" do
|
|
1529
|
+
product.cost?.should be_true
|
|
1530
|
+
end
|
|
1531
|
+
|
|
1532
|
+
it "aliases *_changed?" do
|
|
1533
|
+
product.cost_changed?.should be_true
|
|
1534
|
+
end
|
|
1535
|
+
|
|
1536
|
+
it "aliases *_change" do
|
|
1537
|
+
product.cost_change.should eq([ nil, 500 ])
|
|
1538
|
+
end
|
|
1539
|
+
|
|
1540
|
+
it "aliases *_will_change!" do
|
|
1541
|
+
product.should respond_to(:cost_will_change!)
|
|
1542
|
+
end
|
|
1543
|
+
|
|
1544
|
+
it "aliases *_was" do
|
|
1545
|
+
product.cost_was.should be_nil
|
|
1546
|
+
end
|
|
1547
|
+
|
|
1548
|
+
it "aliases reset_*!" do
|
|
1549
|
+
product.reset_cost!
|
|
1550
|
+
product.cost.should be_nil
|
|
1551
|
+
end
|
|
1552
|
+
|
|
1553
|
+
it "aliases *_before_type_cast" do
|
|
1554
|
+
product.cost = "expensive"
|
|
1555
|
+
product.cost_before_type_cast.should eq("expensive")
|
|
1556
|
+
end
|
|
1557
|
+
end
|
|
1558
|
+
|
|
1559
|
+
context "when checking against the original" do
|
|
1560
|
+
|
|
1561
|
+
before do
|
|
1562
|
+
product.price = 500
|
|
1563
|
+
end
|
|
1564
|
+
|
|
1565
|
+
it "aliases the getter" do
|
|
1566
|
+
product.price.should eq(500)
|
|
1567
|
+
end
|
|
1568
|
+
|
|
1569
|
+
it "aliases the existance check" do
|
|
1570
|
+
product.price?.should be_true
|
|
1571
|
+
end
|
|
1572
|
+
|
|
1573
|
+
it "aliases *_changed?" do
|
|
1574
|
+
product.price_changed?.should be_true
|
|
1575
|
+
end
|
|
1576
|
+
|
|
1577
|
+
it "aliases *_change" do
|
|
1578
|
+
product.price_change.should eq([ nil, 500 ])
|
|
1579
|
+
end
|
|
1580
|
+
|
|
1581
|
+
it "aliases *_will_change!" do
|
|
1582
|
+
product.should respond_to(:price_will_change!)
|
|
1583
|
+
end
|
|
1584
|
+
|
|
1585
|
+
it "aliases *_was" do
|
|
1586
|
+
product.price_was.should be_nil
|
|
1587
|
+
end
|
|
1588
|
+
|
|
1589
|
+
it "aliases reset_*!" do
|
|
1590
|
+
product.reset_price!
|
|
1591
|
+
product.price.should be_nil
|
|
1592
|
+
end
|
|
1593
|
+
end
|
|
1594
|
+
end
|
|
1595
|
+
|
|
1596
|
+
context "when persisting nil attributes" do
|
|
1597
|
+
|
|
1598
|
+
let!(:person) do
|
|
1599
|
+
Person.create(score: nil)
|
|
1600
|
+
end
|
|
1601
|
+
|
|
1602
|
+
it "has an entry in the attributes" do
|
|
1603
|
+
person.reload.attributes.should have_key("score")
|
|
1604
|
+
end
|
|
1605
|
+
end
|
|
1606
|
+
|
|
1607
|
+
context "with a default last_drink_taken_at" do
|
|
1608
|
+
|
|
1609
|
+
let(:person) do
|
|
1610
|
+
Person.new
|
|
1611
|
+
end
|
|
1612
|
+
|
|
1613
|
+
it "saves the default" do
|
|
1614
|
+
expect { person.save }.to_not raise_error
|
|
1615
|
+
person.last_drink_taken_at.should eq(1.day.ago.in_time_zone("Alaska").to_date)
|
|
1616
|
+
end
|
|
1617
|
+
end
|
|
1618
|
+
|
|
1619
|
+
context "when default values are defined" do
|
|
1620
|
+
|
|
1621
|
+
context "when no value exists in the database" do
|
|
1622
|
+
|
|
1623
|
+
let(:person) do
|
|
1624
|
+
Person.create
|
|
1625
|
+
end
|
|
1626
|
+
|
|
1627
|
+
it "applies the default value" do
|
|
1628
|
+
person.last_drink_taken_at.should eq(1.day.ago.in_time_zone("Alaska").to_date)
|
|
1629
|
+
end
|
|
1630
|
+
end
|
|
1631
|
+
|
|
1632
|
+
context "when a value exists in the database" do
|
|
1633
|
+
|
|
1634
|
+
context "when the value is not nil" do
|
|
1635
|
+
|
|
1636
|
+
let!(:person) do
|
|
1637
|
+
Person.create(age: 50)
|
|
1638
|
+
end
|
|
1639
|
+
|
|
1640
|
+
let(:from_db) do
|
|
1641
|
+
Person.find(person.id)
|
|
1642
|
+
end
|
|
1643
|
+
|
|
1644
|
+
it "does not set the default" do
|
|
1645
|
+
from_db.age.should eq(50)
|
|
1646
|
+
end
|
|
1647
|
+
end
|
|
1648
|
+
|
|
1649
|
+
context "when the value is explicitly nil" do
|
|
1650
|
+
|
|
1651
|
+
let!(:person) do
|
|
1652
|
+
Person.create(age: nil)
|
|
1653
|
+
end
|
|
1654
|
+
|
|
1655
|
+
let(:from_db) do
|
|
1656
|
+
Person.find(person.id)
|
|
1657
|
+
end
|
|
1658
|
+
|
|
1659
|
+
it "does not set the default" do
|
|
1660
|
+
from_db.age.should be_nil
|
|
1661
|
+
end
|
|
1662
|
+
end
|
|
1663
|
+
|
|
1664
|
+
context "when the default is a proc" do
|
|
1665
|
+
|
|
1666
|
+
let!(:account) do
|
|
1667
|
+
Account.create(name: "savings", balance: "100")
|
|
1668
|
+
end
|
|
1669
|
+
|
|
1670
|
+
let(:from_db) do
|
|
1671
|
+
Account.find(account.id)
|
|
1672
|
+
end
|
|
1673
|
+
|
|
1674
|
+
it "applies the defaults after all attributes are set" do
|
|
1675
|
+
from_db.should be_balanced
|
|
1676
|
+
end
|
|
1677
|
+
end
|
|
1678
|
+
end
|
|
1679
|
+
end
|
|
1680
|
+
|
|
1681
|
+
context "when dynamic fields are not allowed" do
|
|
1682
|
+
|
|
1683
|
+
before do
|
|
1684
|
+
Mongoid.configure.allow_dynamic_fields = false
|
|
1685
|
+
end
|
|
1686
|
+
|
|
1687
|
+
after do
|
|
1688
|
+
Mongoid.configure.allow_dynamic_fields = true
|
|
1689
|
+
end
|
|
1690
|
+
|
|
1691
|
+
context "when an embedded document has been persisted" do
|
|
1692
|
+
|
|
1693
|
+
context "when the field is no longer recognized" do
|
|
1694
|
+
|
|
1695
|
+
before do
|
|
1696
|
+
Person.collection.insert 'pet' => { 'unrecognized_field' => true }
|
|
1697
|
+
end
|
|
1698
|
+
|
|
1699
|
+
it "allows access to the legacy data" do
|
|
1700
|
+
Person.first.pet.read_attribute(:unrecognized_field).should be_true
|
|
1701
|
+
end
|
|
1702
|
+
end
|
|
1703
|
+
end
|
|
1704
|
+
end
|
|
1705
|
+
end
|