ibm_db 3.0.0-x86-mingw32 → 3.0.1-x86-mingw32
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/CHANGES +4 -0
- data/MANIFEST +14 -14
- data/README +225 -225
- data/ext/Makefile.nt32 +181 -181
- data/ext/Makefile.nt32.191 +212 -212
- data/ext/OLD/extconf.rb +264 -0
- data/ext/{extconf_MacOS.rb → OLD/extconf_MacOS.rb} +269 -269
- data/ext/extconf.rb +291 -264
- data/ext/ibm_db.c +2 -2
- data/ext/ruby_ibm_db.h +241 -241
- data/ext/ruby_ibm_db_cli.h +500 -500
- data/init.rb +41 -41
- data/lib/IBM_DB.rb +27 -27
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4 -4
- data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
- data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
- data/lib/mswin32/ibm_db.rb +115 -115
- data/test/active_record/connection_adapters/fake_adapter.rb +46 -0
- data/test/assets/example.log +1 -0
- data/test/assets/flowers.jpg +0 -0
- data/test/assets/test.txt +1 -0
- data/test/cases/adapter_test.rb +261 -207
- data/test/cases/aggregations_test.rb +158 -0
- data/test/cases/ar_schema_test.rb +161 -0
- data/test/cases/associations/association_scope_test.rb +21 -0
- data/test/cases/associations/belongs_to_associations_test.rb +1029 -711
- data/test/cases/associations/callbacks_test.rb +192 -0
- data/test/cases/associations/cascaded_eager_loading_test.rb +188 -181
- data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -0
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
- data/test/cases/associations/eager_load_nested_include_test.rb +128 -0
- data/test/cases/associations/eager_singularization_test.rb +148 -0
- data/test/cases/associations/eager_test.rb +1411 -0
- data/test/cases/associations/extension_test.rb +82 -0
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +932 -851
- data/test/cases/associations/has_many_associations_test.rb +2162 -0
- data/test/cases/associations/has_many_through_associations_test.rb +1204 -0
- data/test/cases/associations/has_one_associations_test.rb +610 -0
- data/test/cases/associations/has_one_through_associations_test.rb +380 -0
- data/test/cases/associations/inner_join_association_test.rb +139 -0
- data/test/cases/associations/inverse_associations_test.rb +693 -0
- data/test/cases/associations/join_model_test.rb +754 -743
- data/test/cases/associations/nested_through_associations_test.rb +579 -0
- data/test/cases/associations/required_test.rb +82 -0
- data/test/cases/associations_test.rb +380 -0
- data/test/cases/attribute_decorators_test.rb +125 -0
- data/test/cases/attribute_methods/read_test.rb +60 -0
- data/test/cases/attribute_methods/serialization_test.rb +29 -0
- data/test/cases/attribute_methods_test.rb +952 -822
- data/test/cases/attribute_set_test.rb +200 -0
- data/test/cases/attribute_test.rb +180 -0
- data/test/cases/attributes_test.rb +136 -0
- data/test/cases/autosave_association_test.rb +1595 -0
- data/test/cases/base_test.rb +1638 -2133
- data/test/cases/batches_test.rb +212 -0
- data/test/cases/binary_test.rb +52 -0
- data/test/cases/bind_parameter_test.rb +100 -0
- data/test/cases/calculations_test.rb +646 -482
- data/test/cases/callbacks_test.rb +543 -0
- data/test/cases/clone_test.rb +40 -0
- data/test/cases/coders/yaml_column_test.rb +63 -0
- data/test/cases/column_alias_test.rb +17 -0
- data/test/cases/column_definition_test.rb +123 -0
- data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -0
- data/test/cases/connection_adapters/connection_handler_test.rb +53 -0
- data/test/cases/connection_adapters/connection_specification_test.rb +12 -0
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -0
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -0
- data/test/cases/connection_adapters/quoting_test.rb +13 -0
- data/test/cases/connection_adapters/schema_cache_test.rb +56 -0
- data/test/cases/connection_adapters/type_lookup_test.rb +110 -0
- data/test/cases/connection_management_test.rb +122 -0
- data/test/cases/connection_pool_test.rb +346 -0
- data/test/cases/connection_specification/resolver_test.rb +116 -0
- data/test/cases/core_test.rb +112 -0
- data/test/cases/counter_cache_test.rb +209 -0
- data/test/cases/custom_locking_test.rb +17 -0
- data/test/cases/database_statements_test.rb +19 -0
- data/test/cases/date_time_test.rb +61 -0
- data/test/cases/defaults_test.rb +223 -0
- data/test/cases/dirty_test.rb +775 -0
- data/test/cases/disconnected_test.rb +28 -0
- data/test/cases/dup_test.rb +157 -0
- data/test/cases/enum_test.rb +290 -0
- data/test/cases/explain_subscriber_test.rb +64 -0
- data/test/cases/explain_test.rb +76 -0
- data/test/cases/finder_respond_to_test.rb +60 -0
- data/test/cases/finder_test.rb +1166 -0
- data/test/cases/fixture_set/file_test.rb +138 -0
- data/test/cases/fixtures_test.rb +897 -0
- data/test/cases/forbidden_attributes_protection_test.rb +99 -0
- data/test/cases/habtm_destroy_order_test.rb +61 -0
- data/test/cases/helper.rb +210 -0
- data/test/cases/hot_compatibility_test.rb +54 -0
- data/test/cases/i18n_test.rb +45 -0
- data/test/cases/inheritance_test.rb +375 -0
- data/test/cases/integration_test.rb +139 -0
- data/test/cases/invalid_connection_test.rb +22 -0
- data/test/cases/invalid_date_test.rb +32 -0
- data/test/cases/invertible_migration_test.rb +295 -0
- data/test/cases/json_serialization_test.rb +302 -0
- data/test/cases/locking_test.rb +477 -0
- data/test/cases/log_subscriber_test.rb +136 -0
- data/test/cases/migration/change_schema_test - Copy.rb +448 -0
- data/test/cases/migration/change_schema_test.rb +472 -0
- data/test/cases/migration/change_table_test.rb +224 -0
- data/test/cases/migration/column_attributes_test.rb +192 -0
- data/test/cases/migration/column_positioning_test.rb +56 -0
- data/test/cases/migration/columns_test.rb +304 -0
- data/test/cases/migration/command_recorder_test.rb +305 -0
- data/test/cases/migration/create_join_table_test.rb +148 -0
- data/test/cases/migration/foreign_key_test - Changed.rb +325 -0
- data/test/cases/migration/foreign_key_test.rb +360 -0
- data/test/cases/migration/helper.rb +39 -0
- data/test/cases/migration/index_test.rb +216 -0
- data/test/cases/migration/logger_test.rb +36 -0
- data/test/cases/migration/pending_migrations_test.rb +53 -0
- data/test/cases/migration/references_foreign_key_test.rb +214 -0
- data/test/cases/migration/references_index_test.rb +101 -0
- data/test/cases/migration/references_statements_test.rb +116 -0
- data/test/cases/migration/rename_table_test.rb +93 -0
- data/test/cases/migration/table_and_index_test.rb +24 -0
- data/test/cases/migration_test.rb +959 -2408
- data/test/cases/migrator_test.rb +388 -0
- data/test/cases/mixin_test.rb +70 -0
- data/test/cases/modules_test.rb +173 -0
- data/test/cases/multiparameter_attributes_test.rb +350 -0
- data/test/cases/multiple_db_test.rb +115 -0
- data/test/cases/nested_attributes_test.rb +1057 -0
- data/test/cases/nested_attributes_with_callbacks_test.rb +144 -0
- data/test/cases/persistence_test.rb +909 -642
- data/test/cases/pooled_connections_test.rb +81 -0
- data/test/cases/primary_keys_test.rb +237 -0
- data/test/cases/query_cache_test.rb +326 -257
- data/test/cases/quoting_test.rb +156 -0
- data/test/cases/readonly_test.rb +118 -0
- data/test/cases/reaper_test.rb +85 -0
- data/test/cases/reflection_test.rb +454 -0
- data/test/cases/relation/delegation_test.rb +68 -0
- data/test/cases/relation/merging_test.rb +161 -0
- data/test/cases/relation/mutation_test.rb +165 -0
- data/test/cases/relation/predicate_builder_test.rb +14 -0
- data/test/cases/relation/where_chain_test.rb +181 -0
- data/test/cases/relation/where_test.rb +300 -0
- data/test/cases/relation/where_test2.rb +36 -0
- data/test/cases/relation_test.rb +297 -0
- data/test/cases/relations_test.rb +1815 -1182
- data/test/cases/reload_models_test.rb +22 -0
- data/test/cases/result_test.rb +80 -0
- data/test/cases/sanitize_test.rb +83 -0
- data/test/cases/schema_dumper_test.rb +463 -256
- data/test/cases/scoping/default_scoping_test.rb +454 -0
- data/test/cases/scoping/named_scoping_test.rb +524 -0
- data/test/cases/scoping/relation_scoping_test.rb +357 -0
- data/test/cases/serialization_test.rb +104 -0
- data/test/cases/serialized_attribute_test.rb +277 -0
- data/test/cases/statement_cache_test.rb +98 -0
- data/test/cases/store_test.rb +194 -0
- data/test/cases/tasks/database_tasks_test.rb +396 -0
- data/test/cases/tasks/mysql_rake_test.rb +311 -0
- data/test/cases/tasks/postgresql_rake_test.rb +245 -0
- data/test/cases/tasks/sqlite_rake_test.rb +193 -0
- data/test/cases/test_case.rb +123 -0
- data/test/cases/timestamp_test.rb +468 -0
- data/test/cases/transaction_callbacks_test.rb +452 -300
- data/test/cases/transaction_isolation_test.rb +106 -0
- data/test/cases/transactions_test.rb +817 -0
- data/test/cases/type/decimal_test.rb +51 -0
- data/test/cases/type/integer_test.rb +121 -0
- data/test/cases/type/string_test.rb +36 -0
- data/test/cases/type/type_map_test.rb +177 -0
- data/test/cases/type/unsigned_integer_test.rb +18 -0
- data/test/cases/types_test.rb +141 -0
- data/test/cases/unconnected_test.rb +33 -0
- data/test/cases/validations/association_validation_test.rb +86 -0
- data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -0
- data/test/cases/validations/i18n_validation_test.rb +90 -0
- data/test/cases/validations/length_validation_test.rb +47 -0
- data/test/cases/validations/presence_validation_test.rb +68 -0
- data/test/cases/validations/uniqueness_validation_test.rb +434 -299
- data/test/cases/validations_repair_helper.rb +23 -0
- data/test/cases/validations_test.rb +165 -0
- data/test/cases/view_test.rb +113 -0
- data/test/cases/xml_serialization_test.rb +457 -408
- data/test/cases/yaml_serialization_test.rb +86 -0
- data/test/config.rb +5 -0
- data/test/config.yml +154 -154
- data/test/connections/native_ibm_db/connection.rb +43 -43
- data/test/fixtures/accounts.yml +29 -0
- data/test/fixtures/admin/accounts.yml +2 -0
- data/test/fixtures/admin/randomly_named_a9.yml +7 -0
- data/test/fixtures/admin/randomly_named_b0.yml +7 -0
- data/test/fixtures/admin/users.yml +10 -0
- data/test/fixtures/all/admin +1 -0
- data/test/fixtures/all/developers.yml +0 -0
- data/test/fixtures/all/people.yml +0 -0
- data/test/fixtures/all/tasks.yml +0 -0
- data/test/fixtures/author_addresses.yml +18 -0
- data/test/fixtures/author_favorites.yml +4 -0
- data/test/fixtures/authors.yml +23 -0
- data/test/fixtures/binaries.yml +133 -0
- data/test/fixtures/books.yml +11 -0
- data/test/fixtures/bulbs.yml +5 -0
- data/test/fixtures/cars.yml +9 -0
- data/test/fixtures/categories.yml +19 -0
- data/test/fixtures/categories/special_categories.yml +9 -0
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
- data/test/fixtures/categories_ordered.yml +7 -0
- data/test/fixtures/categories_posts.yml +31 -0
- data/test/fixtures/categorizations.yml +23 -0
- data/test/fixtures/clubs.yml +8 -0
- data/test/fixtures/collections.yml +3 -0
- data/test/fixtures/colleges.yml +3 -0
- data/test/fixtures/comments.yml +65 -0
- data/test/fixtures/companies.yml +67 -0
- data/test/fixtures/computers.yml +10 -0
- data/test/fixtures/courses.yml +8 -0
- data/test/fixtures/customers.yml +26 -0
- data/test/fixtures/dashboards.yml +6 -0
- data/test/fixtures/developers.yml +22 -0
- data/test/fixtures/developers_projects.yml +17 -0
- data/test/fixtures/dog_lovers.yml +7 -0
- data/test/fixtures/dogs.yml +4 -0
- data/test/fixtures/doubloons.yml +3 -0
- data/test/fixtures/edges.yml +5 -0
- data/test/fixtures/entrants.yml +14 -0
- data/test/fixtures/essays.yml +6 -0
- data/test/fixtures/faces.yml +11 -0
- data/test/fixtures/fk_test_has_fk.yml +3 -0
- data/test/fixtures/fk_test_has_pk.yml +2 -0
- data/test/fixtures/friendships.yml +4 -0
- data/test/fixtures/funny_jokes.yml +10 -0
- data/test/fixtures/interests.yml +33 -0
- data/test/fixtures/items.yml +3 -0
- data/test/fixtures/jobs.yml +7 -0
- data/test/fixtures/legacy_things.yml +3 -0
- data/test/fixtures/mateys.yml +4 -0
- data/test/fixtures/member_details.yml +8 -0
- data/test/fixtures/member_types.yml +6 -0
- data/test/fixtures/members.yml +11 -0
- data/test/fixtures/memberships.yml +34 -0
- data/test/fixtures/men.yml +5 -0
- data/test/fixtures/minimalistics.yml +2 -0
- data/test/fixtures/minivans.yml +5 -0
- data/test/fixtures/mixed_case_monkeys.yml +6 -0
- data/test/fixtures/mixins.yml +29 -0
- data/test/fixtures/movies.yml +7 -0
- data/test/fixtures/naked/csv/accounts.csv +1 -0
- data/test/fixtures/naked/yml/accounts.yml +1 -0
- data/test/fixtures/naked/yml/companies.yml +1 -0
- data/test/fixtures/naked/yml/courses.yml +1 -0
- data/test/fixtures/organizations.yml +5 -0
- data/test/fixtures/other_topics.yml +42 -0
- data/test/fixtures/owners.yml +9 -0
- data/test/fixtures/parrots.yml +27 -0
- data/test/fixtures/parrots_pirates.yml +7 -0
- data/test/fixtures/people.yml +24 -0
- data/test/fixtures/peoples_treasures.yml +3 -0
- data/test/fixtures/pets.yml +19 -0
- data/test/fixtures/pirates.yml +12 -0
- data/test/fixtures/posts.yml +80 -0
- data/test/fixtures/price_estimates.yml +7 -0
- data/test/fixtures/products.yml +4 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/randomly_named_a9.yml +7 -0
- data/test/fixtures/ratings.yml +14 -0
- data/test/fixtures/readers.yml +11 -0
- data/test/fixtures/references.yml +17 -0
- data/test/fixtures/reserved_words/distinct.yml +5 -0
- data/test/fixtures/reserved_words/distinct_select.yml +11 -0
- data/test/fixtures/reserved_words/group.yml +14 -0
- data/test/fixtures/reserved_words/select.yml +8 -0
- data/test/fixtures/reserved_words/values.yml +7 -0
- data/test/fixtures/ships.yml +6 -0
- data/test/fixtures/speedometers.yml +8 -0
- data/test/fixtures/sponsors.yml +12 -0
- data/test/fixtures/string_key_objects.yml +7 -0
- data/test/fixtures/subscribers.yml +11 -0
- data/test/fixtures/subscriptions.yml +12 -0
- data/test/fixtures/taggings.yml +78 -0
- data/test/fixtures/tags.yml +11 -0
- data/test/fixtures/tasks.yml +7 -0
- data/test/fixtures/teapots.yml +3 -0
- data/test/fixtures/to_be_linked/accounts.yml +2 -0
- data/test/fixtures/to_be_linked/users.yml +10 -0
- data/test/fixtures/topics.yml +49 -0
- data/test/fixtures/toys.yml +14 -0
- data/test/fixtures/traffic_lights.yml +10 -0
- data/test/fixtures/treasures.yml +10 -0
- data/test/fixtures/uuid_children.yml +3 -0
- data/test/fixtures/uuid_parents.yml +2 -0
- data/test/fixtures/variants.yml +4 -0
- data/test/fixtures/vegetables.yml +20 -0
- data/test/fixtures/vertices.yml +4 -0
- data/test/fixtures/warehouse_things.yml +3 -0
- data/test/fixtures/zines.yml +5 -0
- data/test/ibm_db_test.rb +24 -24
- data/test/migrations/10_urban/9_add_expressions.rb +11 -0
- data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
- data/test/migrations/magic/1_currencies_have_symbols.rb +12 -0
- data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
- data/test/migrations/missing/1_people_have_last_names.rb +9 -0
- data/test/migrations/missing/3_we_need_reminders.rb +12 -0
- data/test/migrations/missing/4_innocent_jointable.rb +12 -0
- data/test/migrations/rename/1_we_need_things.rb +11 -0
- data/test/migrations/rename/2_rename_things.rb +9 -0
- data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -0
- data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -0
- data/test/migrations/to_copy2/1_create_articles.rb +7 -0
- data/test/migrations/to_copy2/2_create_comments.rb +7 -0
- data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -0
- data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -0
- data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -0
- data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -0
- data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -0
- data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -0
- data/test/migrations/valid/2_we_need_reminders.rb +12 -0
- data/test/migrations/valid/3_innocent_jointable.rb +12 -0
- data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -0
- data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -0
- data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -0
- data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -0
- data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -0
- data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -0
- data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -0
- data/test/models/admin.rb +5 -0
- data/test/models/admin/account.rb +3 -0
- data/test/models/admin/randomly_named_c1.rb +3 -0
- data/test/models/admin/user.rb +40 -0
- data/test/models/aircraft.rb +4 -0
- data/test/models/arunit2_model.rb +3 -0
- data/test/models/author.rb +212 -0
- data/test/models/auto_id.rb +4 -0
- data/test/models/autoloadable/extra_firm.rb +2 -0
- data/test/models/binary.rb +2 -0
- data/test/models/bird.rb +12 -0
- data/test/models/book.rb +18 -0
- data/test/models/boolean.rb +2 -0
- data/test/models/bulb.rb +51 -0
- data/test/models/cake_designer.rb +3 -0
- data/test/models/car.rb +26 -0
- data/test/models/carrier.rb +2 -0
- data/test/models/categorization.rb +19 -0
- data/test/models/category.rb +35 -0
- data/test/models/chef.rb +3 -0
- data/test/models/citation.rb +3 -0
- data/test/models/club.rb +23 -0
- data/test/models/college.rb +10 -0
- data/test/models/column.rb +3 -0
- data/test/models/column_name.rb +3 -0
- data/test/models/comment.rb +64 -0
- data/test/models/company.rb +225 -0
- data/test/models/company_in_module.rb +98 -0
- data/test/models/computer.rb +3 -0
- data/test/models/contact.rb +41 -0
- data/test/models/contract.rb +20 -0
- data/test/models/country.rb +7 -0
- data/test/models/course.rb +6 -0
- data/test/models/customer.rb +77 -0
- data/test/models/customer_carrier.rb +14 -0
- data/test/models/dashboard.rb +3 -0
- data/test/models/default.rb +2 -0
- data/test/models/department.rb +4 -0
- data/test/models/developer.rb +252 -0
- data/test/models/dog.rb +5 -0
- data/test/models/dog_lover.rb +5 -0
- data/test/models/doubloon.rb +12 -0
- data/test/models/drink_designer.rb +3 -0
- data/test/models/edge.rb +5 -0
- data/test/models/electron.rb +5 -0
- data/test/models/engine.rb +4 -0
- data/test/models/entrant.rb +3 -0
- data/test/models/essay.rb +5 -0
- data/test/models/event.rb +3 -0
- data/test/models/eye.rb +37 -0
- data/test/models/face.rb +9 -0
- data/test/models/friendship.rb +6 -0
- data/test/models/guid.rb +2 -0
- data/test/models/hotel.rb +6 -0
- data/test/models/image.rb +3 -0
- data/test/models/interest.rb +5 -0
- data/test/models/invoice.rb +4 -0
- data/test/models/item.rb +7 -0
- data/test/models/job.rb +7 -0
- data/test/models/joke.rb +7 -0
- data/test/models/keyboard.rb +3 -0
- data/test/models/legacy_thing.rb +3 -0
- data/test/models/lesson.rb +11 -0
- data/test/models/line_item.rb +3 -0
- data/test/models/liquid.rb +4 -0
- data/test/models/man.rb +11 -0
- data/test/models/matey.rb +4 -0
- data/test/models/member.rb +41 -0
- data/test/models/member_detail.rb +7 -0
- data/test/models/member_type.rb +3 -0
- data/test/models/membership.rb +35 -0
- data/test/models/minimalistic.rb +2 -0
- data/test/models/minivan.rb +9 -0
- data/test/models/mixed_case_monkey.rb +3 -0
- data/test/models/molecule.rb +6 -0
- data/test/models/movie.rb +5 -0
- data/test/models/order.rb +4 -0
- data/test/models/organization.rb +14 -0
- data/test/models/owner.rb +34 -0
- data/test/models/parrot.rb +29 -0
- data/test/models/person.rb +143 -0
- data/test/models/personal_legacy_thing.rb +4 -0
- data/test/models/pet.rb +15 -0
- data/test/models/pirate.rb +92 -0
- data/test/models/possession.rb +3 -0
- data/test/models/post.rb +264 -0
- data/test/models/price_estimate.rb +4 -0
- data/test/models/professor.rb +5 -0
- data/test/models/project.rb +29 -0
- data/test/models/publisher.rb +2 -0
- data/test/models/publisher/article.rb +4 -0
- data/test/models/publisher/magazine.rb +3 -0
- data/test/models/randomly_named_c1.rb +3 -0
- data/test/models/rating.rb +4 -0
- data/test/models/reader.rb +23 -0
- data/test/models/record.rb +2 -0
- data/test/models/reference.rb +22 -0
- data/test/models/reply.rb +61 -0
- data/test/models/ship.rb +33 -0
- data/test/models/ship_part.rb +8 -0
- data/test/models/shop.rb +17 -0
- data/test/models/shop_account.rb +6 -0
- data/test/models/speedometer.rb +6 -0
- data/test/models/sponsor.rb +7 -0
- data/test/models/string_key_object.rb +3 -0
- data/test/models/student.rb +4 -0
- data/test/models/subject.rb +16 -0
- data/test/models/subscriber.rb +8 -0
- data/test/models/subscription.rb +4 -0
- data/test/models/tag.rb +7 -0
- data/test/models/tagging.rb +13 -0
- data/test/models/task.rb +5 -0
- data/test/models/topic.rb +124 -0
- data/test/models/toy.rb +6 -0
- data/test/models/traffic_light.rb +4 -0
- data/test/models/treasure.rb +14 -0
- data/test/models/treaty.rb +7 -0
- data/test/models/tyre.rb +11 -0
- data/test/models/uuid_child.rb +3 -0
- data/test/models/uuid_parent.rb +3 -0
- data/test/models/vegetables.rb +24 -0
- data/test/models/vehicle.rb +7 -0
- data/test/models/vertex.rb +9 -0
- data/test/models/warehouse_thing.rb +5 -5
- data/test/models/wheel.rb +3 -0
- data/test/models/without_table.rb +3 -0
- data/test/models/zine.rb +3 -0
- data/test/schema/mysql2_specific_schema.rb +58 -0
- data/test/schema/mysql_specific_schema.rb +70 -0
- data/test/schema/oracle_specific_schema.rb +43 -0
- data/test/schema/postgresql_specific_schema.rb +202 -0
- data/test/schema/schema.rb +938 -751
- data/test/schema/sqlite_specific_schema.rb +22 -0
- data/test/support/config.rb +43 -0
- data/test/support/connection.rb +22 -0
- data/test/support/connection_helper.rb +14 -0
- data/test/support/ddl_helper.rb +8 -0
- data/test/support/schema_dumping_helper.rb +20 -0
- metadata +444 -18
@@ -0,0 +1,33 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
|
3
|
+
class TestRecord < ActiveRecord::Base
|
4
|
+
end
|
5
|
+
|
6
|
+
class TestUnconnectedAdapter < ActiveRecord::TestCase
|
7
|
+
self.use_transactional_fixtures = false
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@underlying = ActiveRecord::Base.connection
|
11
|
+
@specification = ActiveRecord::Base.remove_connection
|
12
|
+
end
|
13
|
+
|
14
|
+
teardown do
|
15
|
+
@underlying = nil
|
16
|
+
ActiveRecord::Base.establish_connection(@specification)
|
17
|
+
load_schema if in_memory_db?
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_connection_no_longer_established
|
21
|
+
assert_raise(ActiveRecord::ConnectionNotEstablished) do
|
22
|
+
TestRecord.find(1)
|
23
|
+
end
|
24
|
+
|
25
|
+
assert_raise(ActiveRecord::ConnectionNotEstablished) do
|
26
|
+
TestRecord.new.save
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_underlying_adapter_no_longer_active
|
31
|
+
assert !@underlying.active?, "Removed adapter should no longer be active"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/topic'
|
3
|
+
require 'models/reply'
|
4
|
+
require 'models/man'
|
5
|
+
require 'models/interest'
|
6
|
+
|
7
|
+
class AssociationValidationTest < ActiveRecord::TestCase
|
8
|
+
fixtures :topics
|
9
|
+
|
10
|
+
repair_validations(Topic, Reply)
|
11
|
+
|
12
|
+
def test_validates_associated_many
|
13
|
+
Topic.validates_associated(:replies)
|
14
|
+
Reply.validates_presence_of(:content)
|
15
|
+
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
16
|
+
t.replies << [r = Reply.new("title" => "A reply"), r2 = Reply.new("title" => "Another reply", "content" => "non-empty"), r3 = Reply.new("title" => "Yet another reply"), r4 = Reply.new("title" => "The last reply", "content" => "non-empty")]
|
17
|
+
assert !t.valid?
|
18
|
+
assert t.errors[:replies].any?
|
19
|
+
assert_equal 1, r.errors.count # make sure all associated objects have been validated
|
20
|
+
assert_equal 0, r2.errors.count
|
21
|
+
assert_equal 1, r3.errors.count
|
22
|
+
assert_equal 0, r4.errors.count
|
23
|
+
r.content = r3.content = "non-empty"
|
24
|
+
assert t.valid?
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_validates_associated_one
|
28
|
+
Reply.validates :topic, :associated => true
|
29
|
+
Topic.validates_presence_of( :content )
|
30
|
+
r = Reply.new("title" => "A reply", "content" => "with content!")
|
31
|
+
r.topic = Topic.create("title" => "uhohuhoh")
|
32
|
+
assert !r.valid?
|
33
|
+
assert r.errors[:topic].any?
|
34
|
+
r.topic.content = "non-empty"
|
35
|
+
assert r.valid?
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_validates_associated_marked_for_destruction
|
39
|
+
Topic.validates_associated(:replies)
|
40
|
+
Reply.validates_presence_of(:content)
|
41
|
+
t = Topic.new
|
42
|
+
t.replies << Reply.new
|
43
|
+
assert t.invalid?
|
44
|
+
t.replies.first.mark_for_destruction
|
45
|
+
assert t.valid?
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_validates_associated_with_custom_message_using_quotes
|
49
|
+
Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
|
50
|
+
Topic.validates_presence_of :content
|
51
|
+
r = Reply.create("title" => "A reply", "content" => "with content!")
|
52
|
+
r.topic = Topic.create("title" => "uhohuhoh")
|
53
|
+
assert !r.valid?
|
54
|
+
assert_equal ["This string contains 'single' and \"double\" quotes"], r.errors[:topic]
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_validates_associated_missing
|
58
|
+
Reply.validates_presence_of(:topic)
|
59
|
+
r = Reply.create("title" => "A reply", "content" => "with content!")
|
60
|
+
assert !r.valid?
|
61
|
+
assert r.errors[:topic].any?
|
62
|
+
|
63
|
+
r.topic = Topic.first
|
64
|
+
assert r.valid?
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_validates_presence_of_belongs_to_association__parent_is_new_record
|
68
|
+
repair_validations(Interest) do
|
69
|
+
# Note that Interest and Man have the :inverse_of option set
|
70
|
+
Interest.validates_presence_of(:man)
|
71
|
+
man = Man.new(:name => 'John')
|
72
|
+
interest = man.interests.build(:topic => 'Airplanes')
|
73
|
+
assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_validates_presence_of_belongs_to_association__existing_parent
|
78
|
+
repair_validations(Interest) do
|
79
|
+
Interest.validates_presence_of(:man)
|
80
|
+
man = Man.create!(:name => 'John')
|
81
|
+
interest = man.interests.build(:topic => 'Airplanes')
|
82
|
+
assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/topic'
|
3
|
+
|
4
|
+
class I18nGenerateMessageValidationTest < ActiveRecord::TestCase
|
5
|
+
def setup
|
6
|
+
Topic.clear_validators!
|
7
|
+
@topic = Topic.new
|
8
|
+
I18n.backend = I18n::Backend::Simple.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def reset_i18n_load_path
|
12
|
+
@old_load_path, @old_backend = I18n.load_path.dup, I18n.backend
|
13
|
+
I18n.load_path.clear
|
14
|
+
I18n.backend = I18n::Backend::Simple.new
|
15
|
+
yield
|
16
|
+
ensure
|
17
|
+
I18n.load_path.replace @old_load_path
|
18
|
+
I18n.backend = @old_backend
|
19
|
+
end
|
20
|
+
|
21
|
+
# validates_associated: generate_message(attr_name, :invalid, :message => custom_message, :value => value)
|
22
|
+
def test_generate_message_invalid_with_default_message
|
23
|
+
assert_equal 'is invalid', @topic.errors.generate_message(:title, :invalid, :value => 'title')
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_generate_message_invalid_with_custom_message
|
27
|
+
assert_equal 'custom message title', @topic.errors.generate_message(:title, :invalid, :message => 'custom message %{value}', :value => 'title')
|
28
|
+
end
|
29
|
+
|
30
|
+
# validates_uniqueness_of: generate_message(attr_name, :taken, :message => custom_message)
|
31
|
+
def test_generate_message_taken_with_default_message
|
32
|
+
assert_equal "has already been taken", @topic.errors.generate_message(:title, :taken, :value => 'title')
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_generate_message_taken_with_custom_message
|
36
|
+
assert_equal 'custom message title', @topic.errors.generate_message(:title, :taken, :message => 'custom message %{value}', :value => 'title')
|
37
|
+
end
|
38
|
+
|
39
|
+
# ActiveRecord#RecordInvalid exception
|
40
|
+
|
41
|
+
test "RecordInvalid exception can be localized" do
|
42
|
+
topic = Topic.new
|
43
|
+
topic.errors.add(:title, :invalid)
|
44
|
+
topic.errors.add(:title, :blank)
|
45
|
+
assert_equal "Validation failed: Title is invalid, Title can't be blank", ActiveRecord::RecordInvalid.new(topic).message
|
46
|
+
end
|
47
|
+
|
48
|
+
test "RecordInvalid exception translation falls back to the :errors namespace" do
|
49
|
+
reset_i18n_load_path do
|
50
|
+
I18n.backend.store_translations 'en', :errors => {:messages => {:record_invalid => 'fallback message'}}
|
51
|
+
topic = Topic.new
|
52
|
+
topic.errors.add(:title, :blank)
|
53
|
+
assert_equal "fallback message", ActiveRecord::RecordInvalid.new(topic).message
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
test "translation for 'taken' can be overridden" do
|
58
|
+
reset_i18n_load_path do
|
59
|
+
I18n.backend.store_translations "en", {errors: {attributes: {title: {taken: "Custom taken message" }}}}
|
60
|
+
assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
test "translation for 'taken' can be overridden in activerecord scope" do
|
65
|
+
reset_i18n_load_path do
|
66
|
+
I18n.backend.store_translations "en", {activerecord: {errors: {messages: {taken: "Custom taken message" }}}}
|
67
|
+
assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
test "translation for 'taken' can be overridden in activerecord model scope" do
|
72
|
+
reset_i18n_load_path do
|
73
|
+
I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {taken: "Custom taken message" }}}}}
|
74
|
+
assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
test "translation for 'taken' can be overridden in activerecord attributes scope" do
|
79
|
+
reset_i18n_load_path do
|
80
|
+
I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {attributes: {title: {taken: "Custom taken message" }}}}}}}
|
81
|
+
assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/topic'
|
3
|
+
require 'models/reply'
|
4
|
+
|
5
|
+
class I18nValidationTest < ActiveRecord::TestCase
|
6
|
+
repair_validations(Topic, Reply)
|
7
|
+
|
8
|
+
def setup
|
9
|
+
repair_validations(Topic, Reply)
|
10
|
+
Reply.validates_presence_of(:title)
|
11
|
+
@topic = Topic.new
|
12
|
+
@old_load_path, @old_backend = I18n.load_path.dup, I18n.backend
|
13
|
+
I18n.load_path.clear
|
14
|
+
I18n.backend = I18n::Backend::Simple.new
|
15
|
+
I18n.backend.store_translations('en', :errors => {:messages => {:custom => nil}})
|
16
|
+
end
|
17
|
+
|
18
|
+
teardown do
|
19
|
+
I18n.load_path.replace @old_load_path
|
20
|
+
I18n.backend = @old_backend
|
21
|
+
end
|
22
|
+
|
23
|
+
def unique_topic
|
24
|
+
@unique ||= Topic.create :title => 'unique!'
|
25
|
+
end
|
26
|
+
|
27
|
+
def replied_topic
|
28
|
+
@replied_topic ||= begin
|
29
|
+
topic = Topic.create(:title => "topic")
|
30
|
+
topic.replies << Reply.new
|
31
|
+
topic
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# A set of common cases for ActiveModel::Validations message generation that
|
36
|
+
# are used to generate tests to keep things DRY
|
37
|
+
#
|
38
|
+
COMMON_CASES = [
|
39
|
+
# [ case, validation_options, generate_message_options]
|
40
|
+
[ "given no options", {}, {}],
|
41
|
+
[ "given custom message", {:message => "custom"}, {:message => "custom"}],
|
42
|
+
[ "given if condition", {:if => lambda { true }}, {}],
|
43
|
+
[ "given unless condition", {:unless => lambda { false }}, {}],
|
44
|
+
[ "given option that is not reserved", {:format => "jpg"}, {:format => "jpg" }]
|
45
|
+
# TODO Add :on case, but below doesn't work, because then the validation isn't run for some reason
|
46
|
+
# even when using .save instead .valid?
|
47
|
+
# [ "given on condition", {on: :save}, {}]
|
48
|
+
]
|
49
|
+
|
50
|
+
# validates_uniqueness_of w/ mocha
|
51
|
+
|
52
|
+
COMMON_CASES.each do |name, validation_options, generate_message_options|
|
53
|
+
test "validates_uniqueness_of on generated message #{name}" do
|
54
|
+
Topic.validates_uniqueness_of :title, validation_options
|
55
|
+
@topic.title = unique_topic.title
|
56
|
+
@topic.errors.expects(:generate_message).with(:title, :taken, generate_message_options.merge(:value => 'unique!'))
|
57
|
+
@topic.valid?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# validates_associated w/ mocha
|
62
|
+
|
63
|
+
COMMON_CASES.each do |name, validation_options, generate_message_options|
|
64
|
+
test "validates_associated on generated message #{name}" do
|
65
|
+
Topic.validates_associated :replies, validation_options
|
66
|
+
replied_topic.errors.expects(:generate_message).with(:replies, :invalid, generate_message_options.merge(:value => replied_topic.replies))
|
67
|
+
replied_topic.save
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# validates_associated w/o mocha
|
72
|
+
|
73
|
+
def test_validates_associated_finds_custom_model_key_translation
|
74
|
+
I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:replies => {:invalid => 'custom message'}}}}}}
|
75
|
+
I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
|
76
|
+
|
77
|
+
Topic.validates_associated :replies
|
78
|
+
replied_topic.valid?
|
79
|
+
assert_equal ['custom message'], replied_topic.errors[:replies].uniq
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_validates_associated_finds_global_default_translation
|
83
|
+
I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
|
84
|
+
|
85
|
+
Topic.validates_associated :replies
|
86
|
+
replied_topic.valid?
|
87
|
+
assert_equal ['global message'], replied_topic.errors[:replies]
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require "cases/helper"
|
3
|
+
require 'models/owner'
|
4
|
+
require 'models/pet'
|
5
|
+
|
6
|
+
class LengthValidationTest < ActiveRecord::TestCase
|
7
|
+
fixtures :owners
|
8
|
+
repair_validations(Owner)
|
9
|
+
|
10
|
+
def test_validates_size_of_association
|
11
|
+
repair_validations Owner do
|
12
|
+
assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
|
13
|
+
o = Owner.new('name' => 'nopets')
|
14
|
+
assert !o.save
|
15
|
+
assert o.errors[:pets].any?
|
16
|
+
o.pets.build('name' => 'apet')
|
17
|
+
assert o.valid?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_validates_size_of_association_using_within
|
22
|
+
repair_validations Owner do
|
23
|
+
assert_nothing_raised { Owner.validates_size_of :pets, :within => 1..2 }
|
24
|
+
o = Owner.new('name' => 'nopets')
|
25
|
+
assert !o.save
|
26
|
+
assert o.errors[:pets].any?
|
27
|
+
|
28
|
+
o.pets.build('name' => 'apet')
|
29
|
+
assert o.valid?
|
30
|
+
|
31
|
+
2.times { o.pets.build('name' => 'apet') }
|
32
|
+
assert !o.save
|
33
|
+
assert o.errors[:pets].any?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_validates_size_of_association_utf8
|
38
|
+
repair_validations Owner do
|
39
|
+
assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
|
40
|
+
o = Owner.new('name' => 'あいうえおかきくけこ')
|
41
|
+
assert !o.save
|
42
|
+
assert o.errors[:pets].any?
|
43
|
+
o.pets.build('name' => 'あいうえおかきくけこ')
|
44
|
+
assert o.valid?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "cases/helper"
|
3
|
+
require 'models/man'
|
4
|
+
require 'models/face'
|
5
|
+
require 'models/interest'
|
6
|
+
require 'models/speedometer'
|
7
|
+
require 'models/dashboard'
|
8
|
+
|
9
|
+
class PresenceValidationTest < ActiveRecord::TestCase
|
10
|
+
class Boy < Man; end
|
11
|
+
|
12
|
+
repair_validations(Boy)
|
13
|
+
|
14
|
+
def test_validates_presence_of_non_association
|
15
|
+
Boy.validates_presence_of(:name)
|
16
|
+
b = Boy.new
|
17
|
+
assert b.invalid?
|
18
|
+
|
19
|
+
b.name = "Alex"
|
20
|
+
assert b.valid?
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_validates_presence_of_has_one
|
24
|
+
Boy.validates_presence_of(:face)
|
25
|
+
b = Boy.new
|
26
|
+
assert b.invalid?, "should not be valid if has_one association missing"
|
27
|
+
assert_equal 1, b.errors[:face].size, "validates_presence_of should only add one error"
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_validates_presence_of_has_one_marked_for_destruction
|
31
|
+
Boy.validates_presence_of(:face)
|
32
|
+
b = Boy.new
|
33
|
+
f = Face.new
|
34
|
+
b.face = f
|
35
|
+
assert b.valid?
|
36
|
+
|
37
|
+
f.mark_for_destruction
|
38
|
+
assert b.invalid?
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_validates_presence_of_has_many_marked_for_destruction
|
42
|
+
Boy.validates_presence_of(:interests)
|
43
|
+
b = Boy.new
|
44
|
+
b.interests << [i1 = Interest.new, i2 = Interest.new]
|
45
|
+
assert b.valid?
|
46
|
+
|
47
|
+
i1.mark_for_destruction
|
48
|
+
assert b.valid?
|
49
|
+
|
50
|
+
i2.mark_for_destruction
|
51
|
+
assert b.invalid?
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_validates_presence_doesnt_convert_to_array
|
55
|
+
speedometer = Class.new(Speedometer)
|
56
|
+
speedometer.validates_presence_of :dashboard
|
57
|
+
|
58
|
+
dash = Dashboard.new
|
59
|
+
|
60
|
+
# dashboard has to_a method
|
61
|
+
def dash.to_a; ['(/)', '(\)']; end
|
62
|
+
|
63
|
+
s = speedometer.new
|
64
|
+
s.dashboard = dash
|
65
|
+
|
66
|
+
assert_nothing_raised { s.valid? }
|
67
|
+
end
|
68
|
+
end
|
@@ -1,299 +1,434 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "cases/helper"
|
3
|
-
require 'models/topic'
|
4
|
-
require 'models/reply'
|
5
|
-
require 'models/warehouse_thing'
|
6
|
-
require 'models/guid'
|
7
|
-
require 'models/event'
|
8
|
-
|
9
|
-
class Wizard < ActiveRecord::Base
|
10
|
-
self.abstract_class = true
|
11
|
-
|
12
|
-
validates_uniqueness_of :name
|
13
|
-
end
|
14
|
-
|
15
|
-
class IneptWizard < Wizard
|
16
|
-
validates_uniqueness_of :city
|
17
|
-
end
|
18
|
-
|
19
|
-
class Conjurer < IneptWizard
|
20
|
-
end
|
21
|
-
|
22
|
-
class Thaumaturgist < IneptWizard
|
23
|
-
end
|
24
|
-
|
25
|
-
class
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
t
|
68
|
-
|
69
|
-
|
70
|
-
assert
|
71
|
-
|
72
|
-
|
73
|
-
assert !
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
t2
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
assert
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
Topic.
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
assert
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
assert
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
assert
|
173
|
-
|
174
|
-
|
175
|
-
assert
|
176
|
-
end
|
177
|
-
|
178
|
-
def
|
179
|
-
Topic.
|
180
|
-
|
181
|
-
|
182
|
-
assert
|
183
|
-
|
184
|
-
|
185
|
-
assert
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
assert
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
assert
|
209
|
-
|
210
|
-
|
211
|
-
assert
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
assert
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
assert
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
end
|
257
|
-
|
258
|
-
def
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
end
|
270
|
-
|
271
|
-
def
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
assert
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
assert
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
assert
|
296
|
-
assert
|
297
|
-
|
298
|
-
|
299
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
require "cases/helper"
|
3
|
+
require 'models/topic'
|
4
|
+
require 'models/reply'
|
5
|
+
require 'models/warehouse_thing'
|
6
|
+
require 'models/guid'
|
7
|
+
require 'models/event'
|
8
|
+
|
9
|
+
class Wizard < ActiveRecord::Base
|
10
|
+
self.abstract_class = true
|
11
|
+
|
12
|
+
validates_uniqueness_of :name
|
13
|
+
end
|
14
|
+
|
15
|
+
class IneptWizard < Wizard
|
16
|
+
validates_uniqueness_of :city
|
17
|
+
end
|
18
|
+
|
19
|
+
class Conjurer < IneptWizard
|
20
|
+
end
|
21
|
+
|
22
|
+
class Thaumaturgist < IneptWizard
|
23
|
+
end
|
24
|
+
|
25
|
+
class ReplyTitle; end
|
26
|
+
|
27
|
+
class ReplyWithTitleObject < Reply
|
28
|
+
validates_uniqueness_of :content, :scope => :title
|
29
|
+
|
30
|
+
def title; ReplyTitle.new; end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Employee < ActiveRecord::Base
|
34
|
+
self.table_name = 'postgresql_arrays'
|
35
|
+
validates_uniqueness_of :nicknames
|
36
|
+
end
|
37
|
+
|
38
|
+
class TopicWithUniqEvent < Topic
|
39
|
+
belongs_to :event, foreign_key: :parent_id
|
40
|
+
validates :event, uniqueness: true
|
41
|
+
end
|
42
|
+
|
43
|
+
class BigIntTest < ActiveRecord::Base
|
44
|
+
INT_MAX_VALUE = 2147483647
|
45
|
+
self.table_name = 'cars'
|
46
|
+
validates :engines_count, uniqueness: true, inclusion: { in: 0..INT_MAX_VALUE }
|
47
|
+
end
|
48
|
+
|
49
|
+
class BigIntReverseTest < ActiveRecord::Base
|
50
|
+
INT_MAX_VALUE = 2147483647
|
51
|
+
self.table_name = 'cars'
|
52
|
+
validates :engines_count, inclusion: { in: 0..INT_MAX_VALUE }
|
53
|
+
validates :engines_count, uniqueness: true
|
54
|
+
end
|
55
|
+
|
56
|
+
class UniquenessValidationTest < ActiveRecord::TestCase
|
57
|
+
INT_MAX_VALUE = 2147483647
|
58
|
+
|
59
|
+
fixtures :topics, 'warehouse_things'
|
60
|
+
|
61
|
+
repair_validations(Topic, Reply)
|
62
|
+
|
63
|
+
def test_validate_uniqueness
|
64
|
+
Topic.validates_uniqueness_of(:title)
|
65
|
+
|
66
|
+
t = Topic.new("title" => "I'm uniqué!")
|
67
|
+
assert t.save, "Should save t as unique"
|
68
|
+
|
69
|
+
t.content = "Remaining unique"
|
70
|
+
assert t.save, "Should still save t as unique"
|
71
|
+
|
72
|
+
t2 = Topic.new("title" => "I'm uniqué!")
|
73
|
+
assert !t2.valid?, "Shouldn't be valid"
|
74
|
+
assert !t2.save, "Shouldn't save t2 as unique"
|
75
|
+
assert_equal ["has already been taken"], t2.errors[:title]
|
76
|
+
|
77
|
+
t2.title = "Now I am really also unique"
|
78
|
+
assert t2.save, "Should now save t2 as unique"
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_validate_uniqueness_with_alias_attribute
|
82
|
+
Topic.alias_attribute :new_title, :title
|
83
|
+
Topic.validates_uniqueness_of(:new_title)
|
84
|
+
|
85
|
+
topic = Topic.new(new_title: 'abc')
|
86
|
+
assert topic.valid?
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_validates_uniqueness_with_nil_value
|
90
|
+
Topic.validates_uniqueness_of(:title)
|
91
|
+
|
92
|
+
t = Topic.new("title" => nil)
|
93
|
+
assert t.save, "Should save t as unique"
|
94
|
+
|
95
|
+
t2 = Topic.new("title" => nil)
|
96
|
+
assert !t2.valid?, "Shouldn't be valid"
|
97
|
+
assert !t2.save, "Shouldn't save t2 as unique"
|
98
|
+
assert_equal ["has already been taken"], t2.errors[:title]
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_validates_uniqueness_with_validates
|
102
|
+
Topic.validates :title, :uniqueness => true
|
103
|
+
Topic.create!('title' => 'abc')
|
104
|
+
|
105
|
+
t2 = Topic.new('title' => 'abc')
|
106
|
+
assert !t2.valid?
|
107
|
+
assert t2.errors[:title]
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_validate_uniqueness_when_integer_out_of_range
|
111
|
+
entry = BigIntTest.create(engines_count: INT_MAX_VALUE + 1)
|
112
|
+
assert_equal entry.errors[:engines_count], ['is not included in the list']
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_validate_uniqueness_when_integer_out_of_range_show_order_does_not_matter
|
116
|
+
entry = BigIntReverseTest.create(engines_count: INT_MAX_VALUE + 1)
|
117
|
+
assert_equal entry.errors[:engines_count], ['is not included in the list']
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_validates_uniqueness_with_newline_chars
|
121
|
+
Topic.validates_uniqueness_of(:title, :case_sensitive => false)
|
122
|
+
|
123
|
+
t = Topic.new("title" => "new\nline")
|
124
|
+
assert t.save, "Should save t as unique"
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_validate_uniqueness_with_scope
|
128
|
+
Reply.validates_uniqueness_of(:content, :scope => "parent_id")
|
129
|
+
|
130
|
+
t = Topic.create("title" => "I'm unique!")
|
131
|
+
|
132
|
+
r1 = t.replies.create "title" => "r1", "content" => "hello world"
|
133
|
+
assert r1.valid?, "Saving r1"
|
134
|
+
|
135
|
+
r2 = t.replies.create "title" => "r2", "content" => "hello world"
|
136
|
+
assert !r2.valid?, "Saving r2 first time"
|
137
|
+
|
138
|
+
r2.content = "something else"
|
139
|
+
assert r2.save, "Saving r2 second time"
|
140
|
+
|
141
|
+
t2 = Topic.create("title" => "I'm unique too!")
|
142
|
+
r3 = t2.replies.create "title" => "r3", "content" => "hello world"
|
143
|
+
assert r3.valid?, "Saving r3"
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_validate_uniqueness_with_object_scope
|
147
|
+
Reply.validates_uniqueness_of(:content, :scope => :topic)
|
148
|
+
|
149
|
+
t = Topic.create("title" => "I'm unique!")
|
150
|
+
|
151
|
+
r1 = t.replies.create "title" => "r1", "content" => "hello world"
|
152
|
+
assert r1.valid?, "Saving r1"
|
153
|
+
|
154
|
+
r2 = t.replies.create "title" => "r2", "content" => "hello world"
|
155
|
+
assert !r2.valid?, "Saving r2 first time"
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_validate_uniqueness_with_composed_attribute_scope
|
159
|
+
r1 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
|
160
|
+
assert r1.valid?, "Saving r1"
|
161
|
+
|
162
|
+
r2 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
|
163
|
+
assert !r2.valid?, "Saving r2 first time"
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_validate_uniqueness_with_object_arg
|
167
|
+
Reply.validates_uniqueness_of(:topic)
|
168
|
+
|
169
|
+
t = Topic.create("title" => "I'm unique!")
|
170
|
+
|
171
|
+
r1 = t.replies.create "title" => "r1", "content" => "hello world"
|
172
|
+
assert r1.valid?, "Saving r1"
|
173
|
+
|
174
|
+
r2 = t.replies.create "title" => "r2", "content" => "hello world"
|
175
|
+
assert !r2.valid?, "Saving r2 first time"
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_validate_uniqueness_scoped_to_defining_class
|
179
|
+
t = Topic.create("title" => "What, me worry?")
|
180
|
+
|
181
|
+
r1 = t.unique_replies.create "title" => "r1", "content" => "a barrel of fun"
|
182
|
+
assert r1.valid?, "Saving r1"
|
183
|
+
|
184
|
+
r2 = t.silly_unique_replies.create "title" => "r2", "content" => "a barrel of fun"
|
185
|
+
assert !r2.valid?, "Saving r2"
|
186
|
+
|
187
|
+
# Should succeed as validates_uniqueness_of only applies to
|
188
|
+
# UniqueReply and its subclasses
|
189
|
+
r3 = t.replies.create "title" => "r2", "content" => "a barrel of fun"
|
190
|
+
assert r3.valid?, "Saving r3"
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_validate_uniqueness_with_scope_array
|
194
|
+
Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
|
195
|
+
|
196
|
+
t = Topic.create("title" => "The earth is actually flat!")
|
197
|
+
|
198
|
+
r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
|
199
|
+
assert r1.valid?, "Saving r1"
|
200
|
+
|
201
|
+
r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
|
202
|
+
assert !r2.valid?, "Saving r2. Double reply by same author."
|
203
|
+
|
204
|
+
r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
|
205
|
+
assert r2.save, "Saving r2 the second time."
|
206
|
+
|
207
|
+
r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
|
208
|
+
assert !r3.valid?, "Saving r3"
|
209
|
+
|
210
|
+
r3.author_name = "jj"
|
211
|
+
assert r3.save, "Saving r3 the second time."
|
212
|
+
|
213
|
+
r3.author_name = "jeremy"
|
214
|
+
assert !r3.save, "Saving r3 the third time."
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_validate_case_insensitive_uniqueness
|
218
|
+
Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
|
219
|
+
|
220
|
+
t = Topic.new("title" => "I'm unique!", :parent_id => 2)
|
221
|
+
assert t.save, "Should save t as unique"
|
222
|
+
|
223
|
+
t.content = "Remaining unique"
|
224
|
+
assert t.save, "Should still save t as unique"
|
225
|
+
|
226
|
+
t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
|
227
|
+
assert !t2.valid?, "Shouldn't be valid"
|
228
|
+
assert !t2.save, "Shouldn't save t2 as unique"
|
229
|
+
assert t2.errors[:title].any?
|
230
|
+
assert t2.errors[:parent_id].any?
|
231
|
+
assert_equal ["has already been taken"], t2.errors[:title]
|
232
|
+
|
233
|
+
t2.title = "I'm truly UNIQUE!"
|
234
|
+
assert !t2.valid?, "Shouldn't be valid"
|
235
|
+
assert !t2.save, "Shouldn't save t2 as unique"
|
236
|
+
assert t2.errors[:title].empty?
|
237
|
+
assert t2.errors[:parent_id].any?
|
238
|
+
|
239
|
+
t2.parent_id = 4
|
240
|
+
assert t2.save, "Should now save t2 as unique"
|
241
|
+
|
242
|
+
t2.parent_id = nil
|
243
|
+
t2.title = nil
|
244
|
+
assert t2.valid?, "should validate with nil"
|
245
|
+
assert t2.save, "should save with nil"
|
246
|
+
|
247
|
+
t_utf8 = Topic.new("title" => "Я тоже уникальный!")
|
248
|
+
assert t_utf8.save, "Should save t_utf8 as unique"
|
249
|
+
|
250
|
+
# If database hasn't UTF-8 character set, this test fails
|
251
|
+
if Topic.all.merge!(:select => 'LOWER(title) AS title').find(t_utf8.id).title == "я тоже уникальный!"
|
252
|
+
t2_utf8 = Topic.new("title" => "я тоже УНИКАЛЬНЫЙ!")
|
253
|
+
assert !t2_utf8.valid?, "Shouldn't be valid"
|
254
|
+
assert !t2_utf8.save, "Shouldn't save t2_utf8 as unique"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_validate_case_sensitive_uniqueness_with_special_sql_like_chars
|
259
|
+
Topic.validates_uniqueness_of(:title, :case_sensitive => true)
|
260
|
+
|
261
|
+
t = Topic.new("title" => "I'm unique!")
|
262
|
+
assert t.save, "Should save t as unique"
|
263
|
+
|
264
|
+
t2 = Topic.new("title" => "I'm %")
|
265
|
+
assert t2.save, "Should save t2 as unique"
|
266
|
+
|
267
|
+
t3 = Topic.new("title" => "I'm uniqu_!")
|
268
|
+
assert t3.save, "Should save t3 as unique"
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_validate_case_insensitive_uniqueness_with_special_sql_like_chars
|
272
|
+
Topic.validates_uniqueness_of(:title, :case_sensitive => false)
|
273
|
+
|
274
|
+
t = Topic.new("title" => "I'm unique!")
|
275
|
+
assert t.save, "Should save t as unique"
|
276
|
+
|
277
|
+
t2 = Topic.new("title" => "I'm %")
|
278
|
+
assert t2.save, "Should save t2 as unique"
|
279
|
+
|
280
|
+
t3 = Topic.new("title" => "I'm uniqu_!")
|
281
|
+
assert t3.save, "Should save t3 as unique"
|
282
|
+
end
|
283
|
+
|
284
|
+
def test_validate_case_sensitive_uniqueness
|
285
|
+
Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
|
286
|
+
|
287
|
+
t = Topic.new("title" => "I'm unique!")
|
288
|
+
assert t.save, "Should save t as unique"
|
289
|
+
|
290
|
+
t.content = "Remaining unique"
|
291
|
+
assert t.save, "Should still save t as unique"
|
292
|
+
|
293
|
+
t2 = Topic.new("title" => "I'M UNIQUE!")
|
294
|
+
assert t2.valid?, "Should be valid"
|
295
|
+
assert t2.save, "Should save t2 as unique"
|
296
|
+
assert t2.errors[:title].empty?
|
297
|
+
assert t2.errors[:parent_id].empty?
|
298
|
+
assert_not_equal ["has already been taken"], t2.errors[:title]
|
299
|
+
|
300
|
+
t3 = Topic.new("title" => "I'M uNiQUe!")
|
301
|
+
assert t3.valid?, "Should be valid"
|
302
|
+
assert t3.save, "Should save t2 as unique"
|
303
|
+
assert t3.errors[:title].empty?
|
304
|
+
assert t3.errors[:parent_id].empty?
|
305
|
+
assert_not_equal ["has already been taken"], t3.errors[:title]
|
306
|
+
end
|
307
|
+
|
308
|
+
def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
|
309
|
+
Topic.validates_uniqueness_of(:title, :case_sensitive => true)
|
310
|
+
Topic.create!('title' => 101)
|
311
|
+
|
312
|
+
t2 = Topic.new('title' => 101)
|
313
|
+
assert !t2.valid?
|
314
|
+
assert t2.errors[:title]
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_validate_uniqueness_with_non_standard_table_names
|
318
|
+
i1 = WarehouseThing.create(:value => 1000)
|
319
|
+
assert !i1.valid?, "i1 should not be valid"
|
320
|
+
assert i1.errors[:value].any?, "Should not be empty"
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_validates_uniqueness_inside_scoping
|
324
|
+
Topic.validates_uniqueness_of(:title)
|
325
|
+
|
326
|
+
Topic.where(:author_name => "David").scoping do
|
327
|
+
t1 = Topic.new("title" => "I'm unique!", "author_name" => "Mary")
|
328
|
+
assert t1.save
|
329
|
+
t2 = Topic.new("title" => "I'm unique!", "author_name" => "David")
|
330
|
+
assert !t2.valid?
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_validate_uniqueness_with_columns_which_are_sql_keywords
|
335
|
+
repair_validations(Guid) do
|
336
|
+
Guid.validates_uniqueness_of :key
|
337
|
+
g = Guid.new
|
338
|
+
g.key = "foo"
|
339
|
+
assert_nothing_raised { !g.valid? }
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_validate_uniqueness_with_limit
|
344
|
+
# Event.title is limited to 5 characters
|
345
|
+
e1 = Event.create(:title => "abcde")
|
346
|
+
assert e1.valid?, "Could not create an event with a unique, 5 character title"
|
347
|
+
e2 = Event.create(:title => "abcdefgh")
|
348
|
+
assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
|
349
|
+
end
|
350
|
+
|
351
|
+
def test_validate_uniqueness_with_limit_and_utf8
|
352
|
+
unless current_adapter?(:IBM_DBAdapter)
|
353
|
+
# Limit for the varchar field is number of bytes and not characters for DB2. Hence the below test cases is expected to fail.
|
354
|
+
# Event.title is limited to 5 characters
|
355
|
+
e1 = Event.create(:title => "一二三四五")
|
356
|
+
assert e1.valid?, "Could not create an event with a unique, 5 character title"
|
357
|
+
e2 = Event.create(:title => "一二三四五六七八")
|
358
|
+
assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_validate_straight_inheritance_uniqueness
|
363
|
+
w1 = IneptWizard.create(:name => "Rincewind", :city => "Ankh-Morpork")
|
364
|
+
assert w1.valid?, "Saving w1"
|
365
|
+
|
366
|
+
# Should use validation from base class (which is abstract)
|
367
|
+
w2 = IneptWizard.new(:name => "Rincewind", :city => "Quirm")
|
368
|
+
assert !w2.valid?, "w2 shouldn't be valid"
|
369
|
+
assert w2.errors[:name].any?, "Should have errors for name"
|
370
|
+
assert_equal ["has already been taken"], w2.errors[:name], "Should have uniqueness message for name"
|
371
|
+
|
372
|
+
w3 = Conjurer.new(:name => "Rincewind", :city => "Quirm")
|
373
|
+
assert !w3.valid?, "w3 shouldn't be valid"
|
374
|
+
assert w3.errors[:name].any?, "Should have errors for name"
|
375
|
+
assert_equal ["has already been taken"], w3.errors[:name], "Should have uniqueness message for name"
|
376
|
+
|
377
|
+
w4 = Conjurer.create(:name => "The Amazing Bonko", :city => "Quirm")
|
378
|
+
assert w4.valid?, "Saving w4"
|
379
|
+
|
380
|
+
w5 = Thaumaturgist.new(:name => "The Amazing Bonko", :city => "Lancre")
|
381
|
+
assert !w5.valid?, "w5 shouldn't be valid"
|
382
|
+
assert w5.errors[:name].any?, "Should have errors for name"
|
383
|
+
assert_equal ["has already been taken"], w5.errors[:name], "Should have uniqueness message for name"
|
384
|
+
|
385
|
+
w6 = Thaumaturgist.new(:name => "Mustrum Ridcully", :city => "Quirm")
|
386
|
+
assert !w6.valid?, "w6 shouldn't be valid"
|
387
|
+
assert w6.errors[:city].any?, "Should have errors for city"
|
388
|
+
assert_equal ["has already been taken"], w6.errors[:city], "Should have uniqueness message for city"
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_validate_uniqueness_with_conditions
|
392
|
+
Topic.validates_uniqueness_of :title, conditions: -> { where(approved: true) }
|
393
|
+
Topic.create("title" => "I'm a topic", "approved" => true)
|
394
|
+
Topic.create("title" => "I'm an unapproved topic", "approved" => false)
|
395
|
+
|
396
|
+
t3 = Topic.new("title" => "I'm a topic", "approved" => true)
|
397
|
+
assert !t3.valid?, "t3 shouldn't be valid"
|
398
|
+
|
399
|
+
t4 = Topic.new("title" => "I'm an unapproved topic", "approved" => false)
|
400
|
+
assert t4.valid?, "t4 should be valid"
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_validate_uniqueness_with_non_callable_conditions_is_not_supported
|
404
|
+
assert_raises(ArgumentError) {
|
405
|
+
Topic.validates_uniqueness_of :title, conditions: Topic.where(approved: true)
|
406
|
+
}
|
407
|
+
end
|
408
|
+
|
409
|
+
if current_adapter? :PostgreSQLAdapter
|
410
|
+
def test_validate_uniqueness_with_array_column
|
411
|
+
e1 = Employee.create("nicknames" => ["john", "johnny"], "commission_by_quarter" => [1000, 1200])
|
412
|
+
assert e1.persisted?, "Saving e1"
|
413
|
+
|
414
|
+
e2 = Employee.create("nicknames" => ["john", "johnny"], "commission_by_quarter" => [2200])
|
415
|
+
assert !e2.persisted?, "e2 shouldn't be valid"
|
416
|
+
assert e2.errors[:nicknames].any?, "Should have errors for nicknames"
|
417
|
+
assert_equal ["has already been taken"], e2.errors[:nicknames], "Should have uniqueness message for nicknames"
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
def test_validate_uniqueness_on_existing_relation
|
422
|
+
event = Event.create
|
423
|
+
assert TopicWithUniqEvent.create(event: event).valid?
|
424
|
+
|
425
|
+
topic = TopicWithUniqEvent.new(event: event)
|
426
|
+
assert_not topic.valid?
|
427
|
+
assert_equal ['has already been taken'], topic.errors[:event]
|
428
|
+
end
|
429
|
+
|
430
|
+
def test_validate_uniqueness_on_empty_relation
|
431
|
+
topic = TopicWithUniqEvent.new
|
432
|
+
assert topic.valid?
|
433
|
+
end
|
434
|
+
end
|