ibm_db 5.6.1-arm64-darwin-24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGES +299 -0
- data/LICENSE +55 -0
- data/MANIFEST +14 -0
- data/ParameterizedQueries README +39 -0
- data/README +210 -0
- data/ext/Makefile +270 -0
- data/ext/Makefile.nt32 +181 -0
- data/ext/Makefile.nt32.191 +212 -0
- data/ext/extconf.rb +320 -0
- data/ext/gil_release_version.h +3 -0
- data/ext/ibm_db.bundle +0 -0
- data/ext/ibm_db.c +11865 -0
- data/ext/ibm_db.o +0 -0
- data/ext/mkmf.log +98 -0
- data/ext/ruby_ibm_db.h +241 -0
- data/ext/ruby_ibm_db_cli.c +867 -0
- data/ext/ruby_ibm_db_cli.h +508 -0
- data/ext/ruby_ibm_db_cli.o +0 -0
- data/ext/unicode_support_version.h +3 -0
- data/init.rb +42 -0
- data/lib/IBM_DB.rb +27 -0
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4407 -0
- data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1965 -0
- data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -0
- data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -0
- data/lib/ibm_db.bundle +0 -0
- data/test/active_record/connection_adapters/fake_adapter.rb +52 -0
- data/test/activejob/destroy_association_async_test.rb +305 -0
- data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
- data/test/activejob/helper.rb +15 -0
- data/test/assets/example.log +1 -0
- data/test/assets/flowers.jpg +0 -0
- data/test/assets/schema_dump_5_1.yml +345 -0
- data/test/assets/test.txt +1 -0
- data/test/cases/adapter_prevent_writes_test.rb +334 -0
- data/test/cases/adapter_test.rb +565 -0
- data/test/cases/adapters/mysql2/active_schema_test.rb +203 -0
- data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
- data/test/cases/adapters/mysql2/bind_parameter_test.rb +52 -0
- data/test/cases/adapters/mysql2/boolean_test.rb +102 -0
- data/test/cases/adapters/mysql2/case_sensitivity_test.rb +65 -0
- data/test/cases/adapters/mysql2/charset_collation_test.rb +57 -0
- data/test/cases/adapters/mysql2/connection_test.rb +208 -0
- data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
- data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +49 -0
- data/test/cases/adapters/mysql2/enum_test.rb +47 -0
- data/test/cases/adapters/mysql2/explain_test.rb +23 -0
- data/test/cases/adapters/mysql2/json_test.rb +24 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +238 -0
- data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
- data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
- data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
- data/test/cases/adapters/mysql2/schema_migrations_test.rb +64 -0
- data/test/cases/adapters/mysql2/schema_test.rb +128 -0
- data/test/cases/adapters/mysql2/set_test.rb +32 -0
- data/test/cases/adapters/mysql2/sp_test.rb +38 -0
- data/test/cases/adapters/mysql2/sql_types_test.rb +16 -0
- data/test/cases/adapters/mysql2/table_options_test.rb +125 -0
- data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
- data/test/cases/adapters/mysql2/unsigned_type_test.rb +68 -0
- data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +113 -0
- data/test/cases/adapters/postgresql/array_test.rb +394 -0
- data/test/cases/adapters/postgresql/bit_string_test.rb +84 -0
- data/test/cases/adapters/postgresql/bytea_test.rb +135 -0
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +27 -0
- data/test/cases/adapters/postgresql/change_schema_test.rb +40 -0
- data/test/cases/adapters/postgresql/cidr_test.rb +27 -0
- data/test/cases/adapters/postgresql/citext_test.rb +78 -0
- data/test/cases/adapters/postgresql/collation_test.rb +55 -0
- data/test/cases/adapters/postgresql/composite_test.rb +134 -0
- data/test/cases/adapters/postgresql/connection_test.rb +245 -0
- data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
- data/test/cases/adapters/postgresql/datatype_test.rb +89 -0
- data/test/cases/adapters/postgresql/date_test.rb +42 -0
- data/test/cases/adapters/postgresql/domain_test.rb +49 -0
- data/test/cases/adapters/postgresql/enum_test.rb +93 -0
- data/test/cases/adapters/postgresql/explain_test.rb +22 -0
- data/test/cases/adapters/postgresql/extension_migration_test.rb +64 -0
- data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
- data/test/cases/adapters/postgresql/full_text_test.rb +46 -0
- data/test/cases/adapters/postgresql/geometric_test.rb +372 -0
- data/test/cases/adapters/postgresql/hstore_test.rb +390 -0
- data/test/cases/adapters/postgresql/infinity_test.rb +108 -0
- data/test/cases/adapters/postgresql/integer_test.rb +27 -0
- data/test/cases/adapters/postgresql/interval_test.rb +99 -0
- data/test/cases/adapters/postgresql/json_test.rb +52 -0
- data/test/cases/adapters/postgresql/ltree_test.rb +51 -0
- data/test/cases/adapters/postgresql/money_test.rb +127 -0
- data/test/cases/adapters/postgresql/network_test.rb +102 -0
- data/test/cases/adapters/postgresql/numbers_test.rb +51 -0
- data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
- data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +447 -0
- data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
- data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
- data/test/cases/adapters/postgresql/quoting_test.rb +50 -0
- data/test/cases/adapters/postgresql/range_test.rb +457 -0
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +112 -0
- data/test/cases/adapters/postgresql/rename_table_test.rb +35 -0
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +110 -0
- data/test/cases/adapters/postgresql/schema_test.rb +713 -0
- data/test/cases/adapters/postgresql/serial_test.rb +156 -0
- data/test/cases/adapters/postgresql/statement_pool_test.rb +61 -0
- data/test/cases/adapters/postgresql/timestamp_test.rb +92 -0
- data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
- data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
- data/test/cases/adapters/postgresql/type_lookup_test.rb +35 -0
- data/test/cases/adapters/postgresql/utils_test.rb +64 -0
- data/test/cases/adapters/postgresql/uuid_test.rb +411 -0
- data/test/cases/adapters/postgresql/xml_test.rb +50 -0
- data/test/cases/adapters/sqlite3/collation_test.rb +64 -0
- data/test/cases/adapters/sqlite3/copy_table_test.rb +101 -0
- data/test/cases/adapters/sqlite3/explain_test.rb +23 -0
- data/test/cases/adapters/sqlite3/json_test.rb +29 -0
- data/test/cases/adapters/sqlite3/quoting_test.rb +79 -0
- data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +628 -0
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +21 -0
- data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
- data/test/cases/aggregations_test.rb +170 -0
- data/test/cases/annotate_test.rb +46 -0
- data/test/cases/ar_schema_test.rb +213 -0
- data/test/cases/arel/attributes/attribute_test.rb +1145 -0
- data/test/cases/arel/attributes/math_test.rb +83 -0
- data/test/cases/arel/attributes_test.rb +27 -0
- data/test/cases/arel/collectors/bind_test.rb +40 -0
- data/test/cases/arel/collectors/composite_test.rb +47 -0
- data/test/cases/arel/collectors/sql_string_test.rb +41 -0
- data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
- data/test/cases/arel/crud_test.rb +65 -0
- data/test/cases/arel/delete_manager_test.rb +53 -0
- data/test/cases/arel/factory_methods_test.rb +46 -0
- data/test/cases/arel/helper.rb +45 -0
- data/test/cases/arel/insert_manager_test.rb +241 -0
- data/test/cases/arel/nodes/and_test.rb +30 -0
- data/test/cases/arel/nodes/as_test.rb +36 -0
- data/test/cases/arel/nodes/ascending_test.rb +46 -0
- data/test/cases/arel/nodes/bin_test.rb +35 -0
- data/test/cases/arel/nodes/binary_test.rb +29 -0
- data/test/cases/arel/nodes/bind_param_test.rb +22 -0
- data/test/cases/arel/nodes/case_test.rb +96 -0
- data/test/cases/arel/nodes/casted_test.rb +18 -0
- data/test/cases/arel/nodes/comment_test.rb +22 -0
- data/test/cases/arel/nodes/count_test.rb +35 -0
- data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
- data/test/cases/arel/nodes/descending_test.rb +46 -0
- data/test/cases/arel/nodes/distinct_test.rb +21 -0
- data/test/cases/arel/nodes/equality_test.rb +62 -0
- data/test/cases/arel/nodes/extract_test.rb +43 -0
- data/test/cases/arel/nodes/false_test.rb +21 -0
- data/test/cases/arel/nodes/grouping_test.rb +26 -0
- data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
- data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
- data/test/cases/arel/nodes/named_function_test.rb +48 -0
- data/test/cases/arel/nodes/node_test.rb +22 -0
- data/test/cases/arel/nodes/not_test.rb +31 -0
- data/test/cases/arel/nodes/or_test.rb +36 -0
- data/test/cases/arel/nodes/over_test.rb +69 -0
- data/test/cases/arel/nodes/select_core_test.rb +79 -0
- data/test/cases/arel/nodes/select_statement_test.rb +51 -0
- data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
- data/test/cases/arel/nodes/sum_test.rb +35 -0
- data/test/cases/arel/nodes/table_alias_test.rb +29 -0
- data/test/cases/arel/nodes/true_test.rb +21 -0
- data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
- data/test/cases/arel/nodes/update_statement_test.rb +60 -0
- data/test/cases/arel/nodes/window_test.rb +81 -0
- data/test/cases/arel/nodes_test.rb +34 -0
- data/test/cases/arel/select_manager_test.rb +1238 -0
- data/test/cases/arel/support/fake_record.rb +135 -0
- data/test/cases/arel/table_test.rb +216 -0
- data/test/cases/arel/update_manager_test.rb +126 -0
- data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
- data/test/cases/arel/visitors/dot_test.rb +90 -0
- data/test/cases/arel/visitors/mysql_test.rb +157 -0
- data/test/cases/arel/visitors/postgres_test.rb +366 -0
- data/test/cases/arel/visitors/sqlite_test.rb +75 -0
- data/test/cases/arel/visitors/to_sql_test.rb +750 -0
- data/test/cases/associations/association_scope_test.rb +16 -0
- data/test/cases/associations/belongs_to_associations_test.rb +1493 -0
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +43 -0
- data/test/cases/associations/callbacks_test.rb +208 -0
- data/test/cases/associations/cascaded_eager_loading_test.rb +245 -0
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +156 -0
- data/test/cases/associations/eager_load_nested_include_test.rb +127 -0
- data/test/cases/associations/eager_singularization_test.rb +148 -0
- data/test/cases/associations/eager_test.rb +1658 -0
- data/test/cases/associations/extension_test.rb +93 -0
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1025 -0
- data/test/cases/associations/has_many_associations_test.rb +3074 -0
- data/test/cases/associations/has_many_through_associations_test.rb +1580 -0
- data/test/cases/associations/has_one_associations_test.rb +872 -0
- data/test/cases/associations/has_one_through_associations_test.rb +429 -0
- data/test/cases/associations/inner_join_association_test.rb +215 -0
- data/test/cases/associations/inverse_associations_test.rb +941 -0
- data/test/cases/associations/join_model_test.rb +787 -0
- data/test/cases/associations/left_outer_join_association_test.rb +123 -0
- data/test/cases/associations/nested_through_associations_test.rb +636 -0
- data/test/cases/associations/required_test.rb +127 -0
- data/test/cases/associations_test.rb +516 -0
- data/test/cases/attribute_decorators_test.rb +126 -0
- data/test/cases/attribute_methods/read_test.rb +60 -0
- data/test/cases/attribute_methods_test.rb +1124 -0
- data/test/cases/attribute_set_test.rb +270 -0
- data/test/cases/attribute_test.rb +246 -0
- data/test/cases/attributes_test.rb +371 -0
- data/test/cases/autosave_association_test.rb +1953 -0
- data/test/cases/base_prevent_writes_test.rb +229 -0
- data/test/cases/base_test.rb +1770 -0
- data/test/cases/batches_test.rb +695 -0
- data/test/cases/binary_test.rb +39 -0
- data/test/cases/bind_parameter_test.rb +283 -0
- data/test/cases/boolean_test.rb +52 -0
- data/test/cases/cache_key_test.rb +131 -0
- data/test/cases/calculations_test.rb +1361 -0
- data/test/cases/callbacks_test.rb +503 -0
- data/test/cases/clone_test.rb +45 -0
- data/test/cases/coders/json_test.rb +17 -0
- data/test/cases/coders/yaml_column_test.rb +66 -0
- data/test/cases/collection_cache_key_test.rb +272 -0
- data/test/cases/column_alias_test.rb +19 -0
- data/test/cases/column_definition_test.rb +34 -0
- data/test/cases/comment_test.rb +204 -0
- data/test/cases/connection_adapters/adapter_leasing_test.rb +60 -0
- data/test/cases/connection_adapters/connection_handler_test.rb +467 -0
- data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
- data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
- data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
- data/test/cases/connection_adapters/connection_specification_test.rb +12 -0
- data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
- data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
- data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +436 -0
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +81 -0
- data/test/cases/connection_adapters/quoting_test.rb +13 -0
- data/test/cases/connection_adapters/schema_cache_test.rb +294 -0
- data/test/cases/connection_adapters/type_lookup_test.rb +119 -0
- data/test/cases/connection_management_test.rb +114 -0
- data/test/cases/connection_pool_test.rb +754 -0
- data/test/cases/connection_specification/resolver_test.rb +131 -0
- data/test/cases/core_test.rb +136 -0
- data/test/cases/counter_cache_test.rb +368 -0
- data/test/cases/custom_locking_test.rb +19 -0
- data/test/cases/database_configurations/hash_config_test.rb +74 -0
- data/test/cases/database_configurations/resolver_test.rb +150 -0
- data/test/cases/database_configurations_test.rb +145 -0
- data/test/cases/database_selector_test.rb +296 -0
- data/test/cases/database_statements_test.rb +36 -0
- data/test/cases/date_test.rb +36 -0
- data/test/cases/date_time_precision_test.rb +129 -0
- data/test/cases/date_time_test.rb +76 -0
- data/test/cases/defaults_test.rb +254 -0
- data/test/cases/delegated_type_test.rb +57 -0
- data/test/cases/dirty_test.rb +959 -0
- data/test/cases/disconnected_test.rb +30 -0
- data/test/cases/dup_test.rb +184 -0
- data/test/cases/enum_test.rb +823 -0
- data/test/cases/errors_test.rb +16 -0
- data/test/cases/explain_subscriber_test.rb +66 -0
- data/test/cases/explain_test.rb +79 -0
- data/test/cases/filter_attributes_test.rb +153 -0
- data/test/cases/finder_respond_to_test.rb +60 -0
- data/test/cases/finder_test.rb +1676 -0
- data/test/cases/fixture_set/file_test.rb +152 -0
- data/test/cases/fixtures_test.rb +1645 -0
- data/test/cases/forbidden_attributes_protection_test.rb +130 -0
- data/test/cases/habtm_destroy_order_test.rb +61 -0
- data/test/cases/helper.rb +233 -0
- data/test/cases/hot_compatibility_test.rb +143 -0
- data/test/cases/i18n_test.rb +46 -0
- data/test/cases/inheritance_test.rb +671 -0
- data/test/cases/insert_all_test.rb +489 -0
- data/test/cases/instrumentation_test.rb +101 -0
- data/test/cases/integration_test.rb +243 -0
- data/test/cases/invalid_connection_test.rb +26 -0
- data/test/cases/invertible_migration_test.rb +527 -0
- data/test/cases/json_attribute_test.rb +35 -0
- data/test/cases/json_serialization_test.rb +310 -0
- data/test/cases/json_shared_test_cases.rb +290 -0
- data/test/cases/locking_test.rb +787 -0
- data/test/cases/log_subscriber_test.rb +267 -0
- data/test/cases/marshal_serialization_test.rb +39 -0
- data/test/cases/migration/change_schema_test.rb +504 -0
- data/test/cases/migration/change_table_test.rb +364 -0
- data/test/cases/migration/check_constraint_test.rb +162 -0
- data/test/cases/migration/column_attributes_test.rb +186 -0
- data/test/cases/migration/column_positioning_test.rb +68 -0
- data/test/cases/migration/columns_test.rb +326 -0
- data/test/cases/migration/command_recorder_test.rb +437 -0
- data/test/cases/migration/compatibility_test.rb +673 -0
- data/test/cases/migration/create_join_table_test.rb +167 -0
- data/test/cases/migration/foreign_key_test.rb +581 -0
- data/test/cases/migration/helper.rb +40 -0
- data/test/cases/migration/index_test.rb +267 -0
- data/test/cases/migration/logger_test.rb +39 -0
- data/test/cases/migration/pending_migrations_test.rb +106 -0
- data/test/cases/migration/references_foreign_key_test.rb +235 -0
- data/test/cases/migration/references_index_test.rb +120 -0
- data/test/cases/migration/references_statements_test.rb +137 -0
- data/test/cases/migration/rename_table_test.rb +116 -0
- data/test/cases/migration_test.rb +1525 -0
- data/test/cases/migrator_test.rb +527 -0
- data/test/cases/mixin_test.rb +64 -0
- data/test/cases/modules_test.rb +174 -0
- data/test/cases/multi_db_migrator_test.rb +223 -0
- data/test/cases/multiparameter_attributes_test.rb +399 -0
- data/test/cases/multiple_db_test.rb +116 -0
- data/test/cases/nested_attributes_test.rb +1119 -0
- data/test/cases/nested_attributes_with_callbacks_test.rb +146 -0
- data/test/cases/null_relation_test.rb +84 -0
- data/test/cases/numeric_data_test.rb +93 -0
- data/test/cases/persistence_test.rb +1093 -0
- data/test/cases/pooled_connections_test.rb +73 -0
- data/test/cases/prepared_statement_status_test.rb +48 -0
- data/test/cases/primary_keys_test.rb +482 -0
- data/test/cases/query_cache_test.rb +915 -0
- data/test/cases/quoting_test.rb +303 -0
- data/test/cases/readonly_test.rb +120 -0
- data/test/cases/reaper_test.rb +199 -0
- data/test/cases/reflection_test.rb +520 -0
- data/test/cases/relation/delegation_test.rb +76 -0
- data/test/cases/relation/delete_all_test.rb +117 -0
- data/test/cases/relation/merging_test.rb +434 -0
- data/test/cases/relation/mutation_test.rb +145 -0
- data/test/cases/relation/or_test.rb +192 -0
- data/test/cases/relation/predicate_builder_test.rb +31 -0
- data/test/cases/relation/record_fetch_warning_test.rb +42 -0
- data/test/cases/relation/select_test.rb +67 -0
- data/test/cases/relation/update_all_test.rb +317 -0
- data/test/cases/relation/where_chain_test.rb +141 -0
- data/test/cases/relation/where_clause_test.rb +257 -0
- data/test/cases/relation/where_test.rb +429 -0
- data/test/cases/relation_test.rb +482 -0
- data/test/cases/relations_test.rb +2251 -0
- data/test/cases/reload_models_test.rb +26 -0
- data/test/cases/reserved_word_test.rb +141 -0
- data/test/cases/result_test.rb +141 -0
- data/test/cases/sanitize_test.rb +192 -0
- data/test/cases/schema_dumper_test.rb +550 -0
- data/test/cases/schema_loading_test.rb +53 -0
- data/test/cases/scoping/default_scoping_test.rb +569 -0
- data/test/cases/scoping/named_scoping_test.rb +649 -0
- data/test/cases/scoping/relation_scoping_test.rb +522 -0
- data/test/cases/secure_token_test.rb +47 -0
- data/test/cases/serialization_test.rb +106 -0
- data/test/cases/serialized_attribute_test.rb +455 -0
- data/test/cases/signed_id_test.rb +168 -0
- data/test/cases/statement_cache_test.rb +153 -0
- data/test/cases/statement_invalid_test.rb +42 -0
- data/test/cases/store_test.rb +320 -0
- data/test/cases/strict_loading_test.rb +473 -0
- data/test/cases/suppressor_test.rb +77 -0
- data/test/cases/tasks/database_tasks_test.rb +1526 -0
- data/test/cases/tasks/mysql_rake_test.rb +417 -0
- data/test/cases/tasks/postgresql_rake_test.rb +534 -0
- data/test/cases/tasks/sqlite_rake_test.rb +267 -0
- data/test/cases/test_case.rb +142 -0
- data/test/cases/test_databases_test.rb +79 -0
- data/test/cases/test_fixtures_test.rb +96 -0
- data/test/cases/time_precision_test.rb +125 -0
- data/test/cases/timestamp_test.rb +504 -0
- data/test/cases/touch_later_test.rb +123 -0
- data/test/cases/transaction_callbacks_test.rb +772 -0
- data/test/cases/transaction_isolation_test.rb +106 -0
- data/test/cases/transactions_test.rb +1285 -0
- data/test/cases/type/adapter_specific_registry_test.rb +145 -0
- data/test/cases/type/date_time_test.rb +16 -0
- data/test/cases/type/integer_test.rb +29 -0
- data/test/cases/type/string_test.rb +24 -0
- data/test/cases/type/time_test.rb +28 -0
- data/test/cases/type/type_map_test.rb +178 -0
- data/test/cases/type/unsigned_integer_test.rb +19 -0
- data/test/cases/type_test.rb +41 -0
- data/test/cases/types_test.rb +26 -0
- data/test/cases/unconnected_test.rb +46 -0
- data/test/cases/unsafe_raw_sql_test.rb +274 -0
- data/test/cases/validations/absence_validation_test.rb +75 -0
- data/test/cases/validations/association_validation_test.rb +99 -0
- data/test/cases/validations/i18n_generate_message_validation_test.rb +102 -0
- data/test/cases/validations/i18n_validation_test.rb +87 -0
- data/test/cases/validations/length_validation_test.rb +80 -0
- data/test/cases/validations/numericality_validation_test.rb +181 -0
- data/test/cases/validations/presence_validation_test.rb +105 -0
- data/test/cases/validations/uniqueness_validation_test.rb +618 -0
- data/test/cases/validations_repair_helper.rb +21 -0
- data/test/cases/validations_test.rb +229 -0
- data/test/cases/view_test.rb +222 -0
- data/test/cases/yaml_serialization_test.rb +166 -0
- data/test/config.example.yml +97 -0
- data/test/config.rb +7 -0
- data/test/config.yml +220 -0
- data/test/connections/native_ibm_db/connection.rb +44 -0
- 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/namespaced/accounts.yml +2 -0
- data/test/fixtures/all/people.yml +0 -0
- data/test/fixtures/all/tasks.yml +0 -0
- data/test/fixtures/author_addresses.yml +11 -0
- data/test/fixtures/author_favorites.yml +4 -0
- data/test/fixtures/authors.yml +17 -0
- data/test/fixtures/bad_posts.yml +9 -0
- data/test/fixtures/binaries.yml +137 -0
- data/test/fixtures/books.yml +38 -0
- data/test/fixtures/bulbs.yml +5 -0
- data/test/fixtures/cars.yml +9 -0
- data/test/fixtures/categories/special_categories.yml +9 -0
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
- data/test/fixtures/categories.yml +19 -0
- data/test/fixtures/categories_ordered.yml +7 -0
- data/test/fixtures/categories_posts.yml +34 -0
- data/test/fixtures/categorizations.yml +23 -0
- data/test/fixtures/citations.yml +5 -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 +72 -0
- data/test/fixtures/companies.yml +72 -0
- data/test/fixtures/computers.yml +12 -0
- data/test/fixtures/content.yml +3 -0
- data/test/fixtures/content_positions.yml +3 -0
- data/test/fixtures/courses.yml +8 -0
- data/test/fixtures/customers.yml +35 -0
- data/test/fixtures/dashboards.yml +6 -0
- data/test/fixtures/dead_parrots.yml +5 -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 +16 -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/humans.yml +5 -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/live_parrots.yml +4 -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 +41 -0
- data/test/fixtures/men.yml +5 -0
- data/test/fixtures/minimalistics.yml +5 -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/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/naked/yml/courses_with_invalid_key.yml +3 -0
- data/test/fixtures/naked/yml/parrots.yml +3 -0
- data/test/fixtures/naked/yml/trees.yml +3 -0
- data/test/fixtures/nodes.yml +29 -0
- data/test/fixtures/organizations.yml +5 -0
- data/test/fixtures/other_books.yml +26 -0
- data/test/fixtures/other_comments.yml +6 -0
- data/test/fixtures/other_dogs.yml +2 -0
- data/test/fixtures/other_posts.yml +8 -0
- data/test/fixtures/other_topics.yml +42 -0
- data/test/fixtures/owners.yml +9 -0
- data/test/fixtures/parrots.yml +33 -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 +15 -0
- data/test/fixtures/posts.yml +88 -0
- data/test/fixtures/price_estimates.yml +16 -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 +17 -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 +15 -0
- data/test/fixtures/strict_zines.yml +2 -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/trees.yml +3 -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/warehouse_things.yml +3 -0
- data/test/fixtures/zines.yml +5 -0
- data/test/ibm_db_test.rb +25 -0
- data/test/migrations/10_urban/9_add_expressions.rb +13 -0
- data/test/migrations/decimal/1_give_me_big_numbers.rb +17 -0
- data/test/migrations/magic/1_currencies_have_symbols.rb +13 -0
- data/test/migrations/missing/1000_people_have_middle_names.rb +11 -0
- data/test/migrations/missing/1_people_have_last_names.rb +11 -0
- data/test/migrations/missing/3_we_need_reminders.rb +14 -0
- data/test/migrations/missing/4_innocent_jointable.rb +14 -0
- data/test/migrations/rename/1_we_need_things.rb +13 -0
- data/test/migrations/rename/2_rename_things.rb +11 -0
- data/test/migrations/to_copy/1_people_have_hobbies.rb +11 -0
- data/test/migrations/to_copy/2_people_have_descriptions.rb +11 -0
- data/test/migrations/to_copy2/1_create_articles.rb +9 -0
- data/test/migrations/to_copy2/2_create_comments.rb +9 -0
- data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +11 -0
- data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +11 -0
- data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +11 -0
- data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +9 -0
- data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +9 -0
- data/test/migrations/valid/1_valid_people_have_last_names.rb +11 -0
- data/test/migrations/valid/2_we_need_reminders.rb +14 -0
- data/test/migrations/valid/3_innocent_jointable.rb +14 -0
- data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +11 -0
- data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +14 -0
- data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +14 -0
- data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +11 -0
- data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +14 -0
- data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +14 -0
- data/test/migrations/version_check/20131219224947_migration_version_check.rb +10 -0
- data/test/models/account.rb +46 -0
- data/test/models/admin/account.rb +5 -0
- data/test/models/admin/randomly_named_c1.rb +9 -0
- data/test/models/admin/user.rb +48 -0
- data/test/models/admin.rb +7 -0
- data/test/models/aircraft.rb +7 -0
- data/test/models/arunit2_model.rb +5 -0
- data/test/models/author.rb +260 -0
- data/test/models/auto_id.rb +6 -0
- data/test/models/autoloadable/extra_firm.rb +4 -0
- data/test/models/binary.rb +4 -0
- data/test/models/binary_field.rb +6 -0
- data/test/models/bird.rb +24 -0
- data/test/models/book.rb +33 -0
- data/test/models/book_destroy_async.rb +24 -0
- data/test/models/boolean.rb +7 -0
- data/test/models/bulb.rb +61 -0
- data/test/models/cake_designer.rb +5 -0
- data/test/models/car.rb +36 -0
- data/test/models/carrier.rb +4 -0
- data/test/models/cart.rb +5 -0
- data/test/models/cat.rb +12 -0
- data/test/models/categorization.rb +21 -0
- data/test/models/category.rb +47 -0
- data/test/models/chef.rb +10 -0
- data/test/models/citation.rb +7 -0
- data/test/models/club.rb +28 -0
- data/test/models/college.rb +12 -0
- data/test/models/column.rb +5 -0
- data/test/models/column_name.rb +5 -0
- data/test/models/comment.rb +98 -0
- data/test/models/company.rb +226 -0
- data/test/models/company_in_module.rb +99 -0
- data/test/models/computer.rb +5 -0
- data/test/models/contact.rb +43 -0
- data/test/models/content.rb +42 -0
- data/test/models/contract.rb +38 -0
- data/test/models/country.rb +5 -0
- data/test/models/course.rb +8 -0
- data/test/models/customer.rb +85 -0
- data/test/models/customer_carrier.rb +16 -0
- data/test/models/dashboard.rb +5 -0
- data/test/models/default.rb +4 -0
- data/test/models/department.rb +6 -0
- data/test/models/destroy_async_parent.rb +15 -0
- data/test/models/destroy_async_parent_soft_delete.rb +20 -0
- data/test/models/developer.rb +341 -0
- data/test/models/dl_keyed_belongs_to.rb +13 -0
- data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
- data/test/models/dl_keyed_has_many.rb +5 -0
- data/test/models/dl_keyed_has_many_through.rb +5 -0
- data/test/models/dl_keyed_has_one.rb +5 -0
- data/test/models/dl_keyed_join.rb +10 -0
- data/test/models/dog.rb +7 -0
- data/test/models/dog_lover.rb +7 -0
- data/test/models/doubloon.rb +14 -0
- data/test/models/drink_designer.rb +20 -0
- data/test/models/edge.rb +7 -0
- data/test/models/electron.rb +7 -0
- data/test/models/engine.rb +5 -0
- data/test/models/entrant.rb +5 -0
- data/test/models/entry.rb +5 -0
- data/test/models/essay.rb +8 -0
- data/test/models/essay_destroy_async.rb +12 -0
- data/test/models/event.rb +5 -0
- data/test/models/eye.rb +39 -0
- data/test/models/face.rb +17 -0
- data/test/models/family.rb +6 -0
- data/test/models/family_tree.rb +6 -0
- data/test/models/friendship.rb +8 -0
- data/test/models/frog.rb +8 -0
- data/test/models/guid.rb +4 -0
- data/test/models/guitar.rb +6 -0
- data/test/models/hotel.rb +13 -0
- data/test/models/human.rb +39 -0
- data/test/models/image.rb +5 -0
- data/test/models/interest.rb +16 -0
- data/test/models/invoice.rb +6 -0
- data/test/models/item.rb +9 -0
- data/test/models/job.rb +9 -0
- data/test/models/joke.rb +9 -0
- data/test/models/keyboard.rb +5 -0
- data/test/models/legacy_thing.rb +5 -0
- data/test/models/lesson.rb +13 -0
- data/test/models/line_item.rb +5 -0
- data/test/models/liquid.rb +6 -0
- data/test/models/man.rb +11 -0
- data/test/models/matey.rb +6 -0
- data/test/models/measurement.rb +4 -0
- data/test/models/member.rb +45 -0
- data/test/models/member_detail.rb +11 -0
- data/test/models/member_type.rb +5 -0
- data/test/models/membership.rb +38 -0
- data/test/models/mentor.rb +5 -0
- data/test/models/message.rb +5 -0
- data/test/models/minimalistic.rb +4 -0
- data/test/models/minivan.rb +10 -0
- data/test/models/mixed_case_monkey.rb +5 -0
- data/test/models/mocktail_designer.rb +2 -0
- data/test/models/molecule.rb +8 -0
- data/test/models/mouse.rb +6 -0
- data/test/models/movie.rb +7 -0
- data/test/models/node.rb +7 -0
- data/test/models/non_primary_key.rb +4 -0
- data/test/models/notification.rb +5 -0
- data/test/models/numeric_data.rb +12 -0
- data/test/models/order.rb +6 -0
- data/test/models/organization.rb +16 -0
- data/test/models/other_dog.rb +7 -0
- data/test/models/owner.rb +39 -0
- data/test/models/parrot.rb +36 -0
- data/test/models/person.rb +147 -0
- data/test/models/personal_legacy_thing.rb +6 -0
- data/test/models/pet.rb +20 -0
- data/test/models/pet_treasure.rb +8 -0
- data/test/models/pirate.rb +116 -0
- data/test/models/possession.rb +5 -0
- data/test/models/post.rb +371 -0
- data/test/models/price_estimate.rb +14 -0
- data/test/models/professor.rb +7 -0
- data/test/models/project.rb +42 -0
- data/test/models/publisher/article.rb +6 -0
- data/test/models/publisher/magazine.rb +5 -0
- data/test/models/publisher.rb +4 -0
- data/test/models/randomly_named_c1.rb +5 -0
- data/test/models/rating.rb +8 -0
- data/test/models/reader.rb +25 -0
- data/test/models/recipe.rb +5 -0
- data/test/models/record.rb +4 -0
- data/test/models/reference.rb +25 -0
- data/test/models/reply.rb +79 -0
- data/test/models/room.rb +6 -0
- data/test/models/section.rb +6 -0
- data/test/models/seminar.rb +6 -0
- data/test/models/session.rb +6 -0
- data/test/models/ship.rb +42 -0
- data/test/models/ship_part.rb +10 -0
- data/test/models/shop.rb +19 -0
- data/test/models/shop_account.rb +8 -0
- data/test/models/speedometer.rb +8 -0
- data/test/models/sponsor.rb +10 -0
- data/test/models/squeak.rb +6 -0
- data/test/models/strict_zine.rb +7 -0
- data/test/models/string_key_object.rb +5 -0
- data/test/models/student.rb +6 -0
- data/test/models/subject.rb +16 -0
- data/test/models/subscriber.rb +10 -0
- data/test/models/subscription.rb +8 -0
- data/test/models/tag.rb +16 -0
- data/test/models/tagging.rb +20 -0
- data/test/models/task.rb +7 -0
- data/test/models/topic.rb +153 -0
- data/test/models/toy.rb +10 -0
- data/test/models/traffic_light.rb +6 -0
- data/test/models/treasure.rb +16 -0
- data/test/models/treaty.rb +5 -0
- data/test/models/tree.rb +5 -0
- data/test/models/tuning_peg.rb +6 -0
- data/test/models/tyre.rb +13 -0
- data/test/models/user.rb +22 -0
- data/test/models/uuid_child.rb +5 -0
- data/test/models/uuid_item.rb +8 -0
- data/test/models/uuid_parent.rb +5 -0
- data/test/models/vegetables.rb +33 -0
- data/test/models/vehicle.rb +7 -0
- data/test/models/vertex.rb +11 -0
- data/test/models/warehouse_thing.rb +7 -0
- data/test/models/wheel.rb +5 -0
- data/test/models/without_table.rb +5 -0
- data/test/models/zine.rb +5 -0
- data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
- data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
- data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
- data/test/schema/mysql2_specific_schema.rb +82 -0
- data/test/schema/oracle_specific_schema.rb +38 -0
- data/test/schema/postgresql_specific_schema.rb +125 -0
- data/test/schema/schema.rb +1237 -0
- data/test/schema/schema.rb.original +1057 -0
- data/test/schema/sqlite_specific_schema.rb +11 -0
- data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
- data/test/support/config.rb +43 -0
- data/test/support/connection.rb +29 -0
- data/test/support/connection_helper.rb +16 -0
- data/test/support/ddl_helper.rb +10 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
- data/test/support/schema_dumping_helper.rb +22 -0
- data/test/support/stubs/strong_parameters.rb +40 -0
- data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
- data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
- data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
- data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
- metadata +876 -0
@@ -0,0 +1,959 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cases/helper"
|
4
|
+
require "models/topic" # For booleans
|
5
|
+
require "models/pirate" # For timestamps
|
6
|
+
require "models/parrot"
|
7
|
+
require "models/person" # For optimistic locking
|
8
|
+
require "models/aircraft"
|
9
|
+
require "models/numeric_data"
|
10
|
+
|
11
|
+
class DirtyTest < ActiveRecord::TestCase
|
12
|
+
include InTimeZone
|
13
|
+
|
14
|
+
# Dummy to force column loads so query counts are clean.
|
15
|
+
def setup
|
16
|
+
Person.create first_name: "foo"
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
Person.delete_by(first_name: "foo")
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_attribute_changes
|
24
|
+
# New record - no changes.
|
25
|
+
pirate = Pirate.new
|
26
|
+
assert_equal false, pirate.catchphrase_changed?
|
27
|
+
assert_equal false, pirate.non_validated_parrot_id_changed?
|
28
|
+
|
29
|
+
# Change catchphrase.
|
30
|
+
pirate.catchphrase = "arrr"
|
31
|
+
assert_predicate pirate, :catchphrase_changed?
|
32
|
+
assert_nil pirate.catchphrase_was
|
33
|
+
assert_equal [nil, "arrr"], pirate.catchphrase_change
|
34
|
+
|
35
|
+
# Saved - no changes.
|
36
|
+
pirate.save!
|
37
|
+
assert_not_predicate pirate, :catchphrase_changed?
|
38
|
+
assert_nil pirate.catchphrase_change
|
39
|
+
|
40
|
+
# Same value - no changes.
|
41
|
+
pirate.catchphrase = "arrr"
|
42
|
+
assert_not_predicate pirate, :catchphrase_changed?
|
43
|
+
assert_nil pirate.catchphrase_change
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_time_attributes_changes_with_time_zone
|
47
|
+
in_time_zone "Paris" do
|
48
|
+
target = Class.new(ActiveRecord::Base)
|
49
|
+
target.table_name = "pirates"
|
50
|
+
|
51
|
+
# New record - no changes.
|
52
|
+
pirate = target.new
|
53
|
+
assert_not_predicate pirate, :created_on_changed?
|
54
|
+
assert_nil pirate.created_on_change
|
55
|
+
|
56
|
+
# Saved - no changes.
|
57
|
+
pirate.catchphrase = "arrrr, time zone!!"
|
58
|
+
pirate.save!
|
59
|
+
assert_not_predicate pirate, :created_on_changed?
|
60
|
+
assert_nil pirate.created_on_change
|
61
|
+
|
62
|
+
# Change created_on.
|
63
|
+
old_created_on = pirate.created_on
|
64
|
+
pirate.created_on = Time.now - 1.day
|
65
|
+
assert_predicate pirate, :created_on_changed?
|
66
|
+
assert_kind_of ActiveSupport::TimeWithZone, pirate.created_on_was
|
67
|
+
assert_equal old_created_on, pirate.created_on_was
|
68
|
+
pirate.created_on = old_created_on
|
69
|
+
assert_not_predicate pirate, :created_on_changed?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_setting_time_attributes_with_time_zone_field_to_itself_should_not_be_marked_as_a_change
|
74
|
+
in_time_zone "Paris" do
|
75
|
+
target = Class.new(ActiveRecord::Base)
|
76
|
+
target.table_name = "pirates"
|
77
|
+
|
78
|
+
pirate = target.create!
|
79
|
+
pirate.created_on = pirate.created_on
|
80
|
+
assert_not_predicate pirate, :created_on_changed?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_time_attributes_changes_without_time_zone_by_skip
|
85
|
+
in_time_zone "Paris" do
|
86
|
+
target = Class.new(ActiveRecord::Base)
|
87
|
+
target.table_name = "pirates"
|
88
|
+
|
89
|
+
target.skip_time_zone_conversion_for_attributes = [:created_on]
|
90
|
+
|
91
|
+
# New record - no changes.
|
92
|
+
pirate = target.new
|
93
|
+
assert_not_predicate pirate, :created_on_changed?
|
94
|
+
assert_nil pirate.created_on_change
|
95
|
+
|
96
|
+
# Saved - no changes.
|
97
|
+
pirate.catchphrase = "arrrr, time zone!!"
|
98
|
+
pirate.save!
|
99
|
+
assert_not_predicate pirate, :created_on_changed?
|
100
|
+
assert_nil pirate.created_on_change
|
101
|
+
|
102
|
+
# Change created_on.
|
103
|
+
old_created_on = pirate.created_on
|
104
|
+
pirate.created_on = Time.now + 1.day
|
105
|
+
assert_predicate pirate, :created_on_changed?
|
106
|
+
# kind_of does not work because
|
107
|
+
# ActiveSupport::TimeWithZone.name == 'Time'
|
108
|
+
assert_instance_of Time, pirate.created_on_was
|
109
|
+
assert_equal old_created_on, pirate.created_on_was
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_time_attributes_changes_without_time_zone
|
114
|
+
with_timezone_config aware_attributes: false do
|
115
|
+
target = Class.new(ActiveRecord::Base)
|
116
|
+
target.table_name = "pirates"
|
117
|
+
|
118
|
+
# New record - no changes.
|
119
|
+
pirate = target.new
|
120
|
+
assert_not_predicate pirate, :created_on_changed?
|
121
|
+
assert_nil pirate.created_on_change
|
122
|
+
|
123
|
+
# Saved - no changes.
|
124
|
+
pirate.catchphrase = "arrrr, time zone!!"
|
125
|
+
pirate.save!
|
126
|
+
assert_not_predicate pirate, :created_on_changed?
|
127
|
+
assert_nil pirate.created_on_change
|
128
|
+
|
129
|
+
# Change created_on.
|
130
|
+
old_created_on = pirate.created_on
|
131
|
+
pirate.created_on = Time.now + 1.day
|
132
|
+
assert_predicate pirate, :created_on_changed?
|
133
|
+
# kind_of does not work because
|
134
|
+
# ActiveSupport::TimeWithZone.name == 'Time'
|
135
|
+
assert_instance_of Time, pirate.created_on_was
|
136
|
+
assert_equal old_created_on, pirate.created_on_was
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_aliased_attribute_changes
|
141
|
+
# the actual attribute here is name, title is an
|
142
|
+
# alias setup via alias_attribute
|
143
|
+
parrot = Parrot.new
|
144
|
+
assert_not_predicate parrot, :title_changed?
|
145
|
+
assert_nil parrot.title_change
|
146
|
+
|
147
|
+
parrot.name = "Sam"
|
148
|
+
assert_predicate parrot, :title_changed?
|
149
|
+
assert_nil parrot.title_was
|
150
|
+
assert_equal parrot.name_change, parrot.title_change
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_restore_attribute!
|
154
|
+
pirate = Pirate.create!(catchphrase: "Yar!")
|
155
|
+
pirate.catchphrase = "Ahoy!"
|
156
|
+
|
157
|
+
assert_equal "Ahoy!", pirate.catchphrase
|
158
|
+
assert_equal ["Yar!", "Ahoy!"], pirate.catchphrase_change
|
159
|
+
|
160
|
+
pirate.restore_catchphrase!
|
161
|
+
|
162
|
+
assert_nil pirate.catchphrase_change
|
163
|
+
assert_equal "Yar!", pirate.catchphrase
|
164
|
+
assert_equal Hash.new, pirate.changes
|
165
|
+
assert_not_predicate pirate, :catchphrase_changed?
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_clear_attribute_change
|
169
|
+
pirate = Pirate.create!(catchphrase: "Yar!")
|
170
|
+
pirate.catchphrase = "Ahoy!"
|
171
|
+
|
172
|
+
assert_equal "Ahoy!", pirate.catchphrase
|
173
|
+
assert_equal ["Yar!", "Ahoy!"], pirate.catchphrase_change
|
174
|
+
|
175
|
+
pirate.clear_catchphrase_change
|
176
|
+
|
177
|
+
assert_nil pirate.catchphrase_change
|
178
|
+
assert_equal "Ahoy!", pirate.catchphrase
|
179
|
+
assert_equal Hash.new, pirate.changes
|
180
|
+
assert_not_predicate pirate, :catchphrase_changed?
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_nullable_number_not_marked_as_changed_if_new_value_is_blank
|
184
|
+
pirate = Pirate.new
|
185
|
+
|
186
|
+
["", nil].each do |value|
|
187
|
+
pirate.parrot_id = value
|
188
|
+
assert_not_predicate pirate, :parrot_id_changed?
|
189
|
+
assert_nil pirate.parrot_id_change
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_nullable_decimal_not_marked_as_changed_if_new_value_is_blank
|
194
|
+
numeric_data = NumericData.new
|
195
|
+
|
196
|
+
["", nil].each do |value|
|
197
|
+
numeric_data.bank_balance = value
|
198
|
+
assert_not_predicate numeric_data, :bank_balance_changed?
|
199
|
+
assert_nil numeric_data.bank_balance_change
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_nullable_float_not_marked_as_changed_if_new_value_is_blank
|
204
|
+
numeric_data = NumericData.new
|
205
|
+
|
206
|
+
["", nil].each do |value|
|
207
|
+
numeric_data.temperature = value
|
208
|
+
assert_not_predicate numeric_data, :temperature_changed?
|
209
|
+
assert_nil numeric_data.temperature_change
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_nullable_datetime_not_marked_as_changed_if_new_value_is_blank
|
214
|
+
in_time_zone "Edinburgh" do
|
215
|
+
target = Class.new(ActiveRecord::Base)
|
216
|
+
target.table_name = "topics"
|
217
|
+
|
218
|
+
topic = target.create
|
219
|
+
assert_nil topic.written_on
|
220
|
+
|
221
|
+
["", nil].each do |value|
|
222
|
+
topic.written_on = value
|
223
|
+
assert_nil topic.written_on
|
224
|
+
assert_not_predicate topic, :written_on_changed?
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_integer_zero_to_string_zero_not_marked_as_changed
|
230
|
+
pirate = Pirate.new
|
231
|
+
pirate.parrot_id = 0
|
232
|
+
pirate.catchphrase = "arrr"
|
233
|
+
assert pirate.save!
|
234
|
+
|
235
|
+
assert_not_predicate pirate, :changed?
|
236
|
+
|
237
|
+
pirate.parrot_id = "0"
|
238
|
+
assert_not_predicate pirate, :changed?
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_integer_zero_to_integer_zero_not_marked_as_changed
|
242
|
+
pirate = Pirate.new
|
243
|
+
pirate.parrot_id = 0
|
244
|
+
pirate.catchphrase = "arrr"
|
245
|
+
assert pirate.save!
|
246
|
+
|
247
|
+
assert_not_predicate pirate, :changed?
|
248
|
+
|
249
|
+
pirate.parrot_id = 0
|
250
|
+
assert_not_predicate pirate, :changed?
|
251
|
+
end
|
252
|
+
|
253
|
+
def test_float_zero_to_string_zero_not_marked_as_changed
|
254
|
+
data = NumericData.new temperature: 0.0
|
255
|
+
data.save!
|
256
|
+
|
257
|
+
assert_not_predicate data, :changed?
|
258
|
+
|
259
|
+
data.temperature = "0"
|
260
|
+
assert_empty data.changes
|
261
|
+
|
262
|
+
data.temperature = "0.0"
|
263
|
+
assert_empty data.changes
|
264
|
+
|
265
|
+
data.temperature = "0.00"
|
266
|
+
assert_empty data.changes
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_zero_to_blank_marked_as_changed
|
270
|
+
pirate = Pirate.new
|
271
|
+
pirate.catchphrase = "Yarrrr, me hearties"
|
272
|
+
pirate.parrot_id = 1
|
273
|
+
pirate.save
|
274
|
+
|
275
|
+
# check the change from 1 to ''
|
276
|
+
pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
|
277
|
+
pirate.parrot_id = ""
|
278
|
+
assert_predicate pirate, :parrot_id_changed?
|
279
|
+
assert_equal([1, nil], pirate.parrot_id_change)
|
280
|
+
pirate.save
|
281
|
+
|
282
|
+
# check the change from nil to 0
|
283
|
+
pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
|
284
|
+
pirate.parrot_id = 0
|
285
|
+
assert_predicate pirate, :parrot_id_changed?
|
286
|
+
assert_equal([nil, 0], pirate.parrot_id_change)
|
287
|
+
pirate.save
|
288
|
+
|
289
|
+
# check the change from 0 to ''
|
290
|
+
pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
|
291
|
+
pirate.parrot_id = ""
|
292
|
+
assert_predicate pirate, :parrot_id_changed?
|
293
|
+
assert_equal([0, nil], pirate.parrot_id_change)
|
294
|
+
end
|
295
|
+
|
296
|
+
def test_object_should_be_changed_if_any_attribute_is_changed
|
297
|
+
pirate = Pirate.new
|
298
|
+
assert_not_predicate pirate, :changed?
|
299
|
+
assert_equal [], pirate.changed
|
300
|
+
assert_equal Hash.new, pirate.changes
|
301
|
+
|
302
|
+
pirate.catchphrase = "arrr"
|
303
|
+
assert_predicate pirate, :changed?
|
304
|
+
assert_nil pirate.catchphrase_was
|
305
|
+
assert_equal %w(catchphrase), pirate.changed
|
306
|
+
assert_equal({ "catchphrase" => [nil, "arrr"] }, pirate.changes)
|
307
|
+
|
308
|
+
pirate.save
|
309
|
+
assert_not_predicate pirate, :changed?
|
310
|
+
assert_equal [], pirate.changed
|
311
|
+
assert_equal Hash.new, pirate.changes
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_attribute_will_change!
|
315
|
+
pirate = Pirate.create!(catchphrase: "arr")
|
316
|
+
|
317
|
+
assert_not_predicate pirate, :catchphrase_changed?
|
318
|
+
assert pirate.catchphrase_will_change!
|
319
|
+
assert_predicate pirate, :catchphrase_changed?
|
320
|
+
assert_equal ["arr", "arr"], pirate.catchphrase_change
|
321
|
+
|
322
|
+
pirate.catchphrase << " matey!"
|
323
|
+
assert_predicate pirate, :catchphrase_changed?
|
324
|
+
assert_equal ["arr", "arr matey!"], pirate.catchphrase_change
|
325
|
+
end
|
326
|
+
|
327
|
+
def test_virtual_attribute_will_change
|
328
|
+
parrot = Parrot.create!(name: "Ruby")
|
329
|
+
parrot.send(:attribute_will_change!, :cancel_save_from_callback)
|
330
|
+
assert_predicate parrot, :has_changes_to_save?
|
331
|
+
end
|
332
|
+
|
333
|
+
def test_association_assignment_changes_foreign_key
|
334
|
+
pirate = Pirate.create!(catchphrase: "jarl")
|
335
|
+
pirate.parrot = Parrot.create!(name: "Lorre")
|
336
|
+
assert_predicate pirate, :changed?
|
337
|
+
assert_equal %w(parrot_id), pirate.changed
|
338
|
+
end
|
339
|
+
|
340
|
+
def test_attribute_should_be_compared_with_type_cast
|
341
|
+
topic = Topic.new
|
342
|
+
assert_predicate topic, :approved?
|
343
|
+
assert_not_predicate topic, :approved_changed?
|
344
|
+
|
345
|
+
# Coming from web form.
|
346
|
+
params = { topic: { approved: 1 } }
|
347
|
+
# In the controller.
|
348
|
+
topic.attributes = params[:topic]
|
349
|
+
assert_predicate topic, :approved?
|
350
|
+
assert_not_predicate topic, :approved_changed?
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_string_attribute_should_compare_with_typecast_symbol_after_update
|
354
|
+
pirate = Pirate.create!(catchphrase: :foo)
|
355
|
+
pirate.update_column :catchphrase, :foo
|
356
|
+
pirate.catchphrase
|
357
|
+
assert_not_predicate pirate, :catchphrase_changed?
|
358
|
+
end
|
359
|
+
|
360
|
+
def test_partial_update
|
361
|
+
pirate = Pirate.new(catchphrase: "foo")
|
362
|
+
old_updated_on = 1.hour.ago.beginning_of_day
|
363
|
+
|
364
|
+
with_partial_writes Pirate, false do
|
365
|
+
assert_queries(2) { 2.times { pirate.save! } }
|
366
|
+
Pirate.where(id: pirate.id).update_all(updated_on: old_updated_on)
|
367
|
+
end
|
368
|
+
|
369
|
+
with_partial_writes Pirate, true do
|
370
|
+
assert_no_queries { 2.times { pirate.save! } }
|
371
|
+
assert_equal old_updated_on, pirate.reload.updated_on
|
372
|
+
|
373
|
+
assert_queries(1) { pirate.catchphrase = "bar"; pirate.save! }
|
374
|
+
assert_not_equal old_updated_on, pirate.reload.updated_on
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
def test_partial_update_with_optimistic_locking
|
379
|
+
person = Person.new(first_name: "foo")
|
380
|
+
|
381
|
+
with_partial_writes Person, false do
|
382
|
+
assert_queries(2) { 2.times { person.save! } }
|
383
|
+
Person.where(id: person.id).update_all(first_name: "baz")
|
384
|
+
end
|
385
|
+
|
386
|
+
old_lock_version = person.lock_version + 1
|
387
|
+
|
388
|
+
with_partial_writes Person, true do
|
389
|
+
assert_no_queries { 2.times { person.save! } }
|
390
|
+
assert_equal old_lock_version, person.reload.lock_version
|
391
|
+
|
392
|
+
assert_queries(1) { person.first_name = "bar"; person.save! }
|
393
|
+
assert_not_equal old_lock_version, person.reload.lock_version
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
def test_changed_attributes_should_be_preserved_if_save_failure
|
398
|
+
pirate = Pirate.new
|
399
|
+
pirate.parrot_id = 1
|
400
|
+
assert_not pirate.save
|
401
|
+
check_pirate_after_save_failure(pirate)
|
402
|
+
|
403
|
+
pirate = Pirate.new
|
404
|
+
pirate.parrot_id = 1
|
405
|
+
assert_raise(ActiveRecord::RecordInvalid) { pirate.save! }
|
406
|
+
check_pirate_after_save_failure(pirate)
|
407
|
+
end
|
408
|
+
|
409
|
+
def test_reload_should_clear_changed_attributes
|
410
|
+
pirate = Pirate.create!(catchphrase: "shiver me timbers")
|
411
|
+
pirate.catchphrase = "*hic*"
|
412
|
+
assert_predicate pirate, :changed?
|
413
|
+
pirate.reload
|
414
|
+
assert_not_predicate pirate, :changed?
|
415
|
+
end
|
416
|
+
|
417
|
+
def test_dup_objects_should_not_copy_dirty_flag_from_creator
|
418
|
+
pirate = Pirate.create!(catchphrase: "shiver me timbers")
|
419
|
+
pirate_dup = pirate.dup
|
420
|
+
pirate_dup.restore_catchphrase!
|
421
|
+
pirate.catchphrase = "I love Rum"
|
422
|
+
assert_predicate pirate, :catchphrase_changed?
|
423
|
+
assert_not_predicate pirate_dup, :catchphrase_changed?
|
424
|
+
end
|
425
|
+
|
426
|
+
def test_reverted_changes_are_not_dirty
|
427
|
+
phrase = "shiver me timbers"
|
428
|
+
pirate = Pirate.create!(catchphrase: phrase)
|
429
|
+
pirate.catchphrase = "*hic*"
|
430
|
+
assert_predicate pirate, :changed?
|
431
|
+
pirate.catchphrase = phrase
|
432
|
+
assert_not_predicate pirate, :changed?
|
433
|
+
end
|
434
|
+
|
435
|
+
def test_reverted_changes_are_not_dirty_after_multiple_changes
|
436
|
+
phrase = "shiver me timbers"
|
437
|
+
pirate = Pirate.create!(catchphrase: phrase)
|
438
|
+
10.times do |i|
|
439
|
+
pirate.catchphrase = "*hic*" * i
|
440
|
+
assert_predicate pirate, :changed?
|
441
|
+
end
|
442
|
+
assert_predicate pirate, :changed?
|
443
|
+
pirate.catchphrase = phrase
|
444
|
+
assert_not_predicate pirate, :changed?
|
445
|
+
end
|
446
|
+
|
447
|
+
def test_reverted_changes_are_not_dirty_going_from_nil_to_value_and_back
|
448
|
+
pirate = Pirate.create!(catchphrase: "Yar!")
|
449
|
+
|
450
|
+
pirate.parrot_id = 1
|
451
|
+
assert_predicate pirate, :changed?
|
452
|
+
assert_predicate pirate, :parrot_id_changed?
|
453
|
+
assert_not_predicate pirate, :catchphrase_changed?
|
454
|
+
|
455
|
+
pirate.parrot_id = nil
|
456
|
+
assert_not_predicate pirate, :changed?
|
457
|
+
assert_not_predicate pirate, :parrot_id_changed?
|
458
|
+
assert_not_predicate pirate, :catchphrase_changed?
|
459
|
+
end
|
460
|
+
|
461
|
+
def test_save_should_store_serialized_attributes_even_with_partial_writes
|
462
|
+
with_partial_writes(Topic) do
|
463
|
+
topic = Topic.create!(content: { a: "a" })
|
464
|
+
|
465
|
+
assert_not_predicate topic, :changed?
|
466
|
+
|
467
|
+
topic.content[:b] = "b"
|
468
|
+
|
469
|
+
assert_predicate topic, :changed?
|
470
|
+
|
471
|
+
topic.save!
|
472
|
+
|
473
|
+
assert_not_predicate topic, :changed?
|
474
|
+
assert_equal "b", topic.content[:b]
|
475
|
+
|
476
|
+
topic.reload
|
477
|
+
|
478
|
+
assert_equal "b", topic.content[:b]
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
def test_save_always_should_update_timestamps_when_serialized_attributes_are_present
|
483
|
+
with_partial_writes(Topic) do
|
484
|
+
topic = Topic.create!(content: { a: "a" })
|
485
|
+
topic.save!
|
486
|
+
|
487
|
+
updated_at = topic.updated_at
|
488
|
+
travel(1.second) do
|
489
|
+
topic.content[:hello] = "world"
|
490
|
+
topic.save!
|
491
|
+
end
|
492
|
+
|
493
|
+
assert_not_equal updated_at, topic.updated_at
|
494
|
+
assert_equal "world", topic.content[:hello]
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
def test_save_should_not_save_serialized_attribute_with_partial_writes_if_not_present
|
499
|
+
with_partial_writes(Topic) do
|
500
|
+
topic = Topic.create!(author_name: "Bill", content: { a: "a" })
|
501
|
+
topic = Topic.select("id, author_name").find(topic.id)
|
502
|
+
topic.update_columns author_name: "John"
|
503
|
+
assert_not_nil topic.reload.content
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
def test_changes_to_save_should_not_mutate_array_of_hashes
|
508
|
+
topic = Topic.new(author_name: "Bill", content: [{ a: "a" }])
|
509
|
+
|
510
|
+
topic.changes_to_save
|
511
|
+
|
512
|
+
assert_equal [{ a: "a" }], topic.content
|
513
|
+
end
|
514
|
+
|
515
|
+
def test_previous_changes
|
516
|
+
# original values should be in previous_changes
|
517
|
+
pirate = Pirate.new
|
518
|
+
|
519
|
+
assert_equal Hash.new, pirate.previous_changes
|
520
|
+
pirate.catchphrase = "arrr"
|
521
|
+
pirate.save!
|
522
|
+
|
523
|
+
assert_equal 4, pirate.previous_changes.size
|
524
|
+
assert_equal [nil, "arrr"], pirate.previous_changes["catchphrase"]
|
525
|
+
assert_nil pirate.catchphrase_previously_was
|
526
|
+
assert_equal [nil, pirate.id], pirate.previous_changes["id"]
|
527
|
+
assert_nil pirate.previous_changes["updated_on"][0]
|
528
|
+
assert_not_nil pirate.previous_changes["updated_on"][1]
|
529
|
+
assert_nil pirate.previous_changes["created_on"][0]
|
530
|
+
assert_not_nil pirate.previous_changes["created_on"][1]
|
531
|
+
assert_not pirate.previous_changes.key?("parrot_id")
|
532
|
+
|
533
|
+
# original values should be in previous_changes
|
534
|
+
pirate = Pirate.new
|
535
|
+
|
536
|
+
assert_equal Hash.new, pirate.previous_changes
|
537
|
+
pirate.catchphrase = "arrr"
|
538
|
+
pirate.save
|
539
|
+
|
540
|
+
assert_equal 4, pirate.previous_changes.size
|
541
|
+
assert_equal [nil, "arrr"], pirate.previous_changes["catchphrase"]
|
542
|
+
assert_nil pirate.catchphrase_previously_was
|
543
|
+
assert_equal [nil, pirate.id], pirate.previous_changes["id"]
|
544
|
+
assert_includes pirate.previous_changes, "updated_on"
|
545
|
+
assert_includes pirate.previous_changes, "created_on"
|
546
|
+
assert_not pirate.previous_changes.key?("parrot_id")
|
547
|
+
|
548
|
+
pirate.catchphrase = "Yar!!"
|
549
|
+
pirate.reload
|
550
|
+
assert_equal Hash.new, pirate.previous_changes
|
551
|
+
|
552
|
+
pirate = Pirate.find_by_catchphrase("arrr")
|
553
|
+
|
554
|
+
travel(1.second)
|
555
|
+
|
556
|
+
pirate.catchphrase = "Me Maties!"
|
557
|
+
pirate.save!
|
558
|
+
|
559
|
+
assert_equal 2, pirate.previous_changes.size
|
560
|
+
assert_equal ["arrr", "Me Maties!"], pirate.previous_changes["catchphrase"]
|
561
|
+
assert_equal "arrr", pirate.catchphrase_previously_was
|
562
|
+
assert_not_nil pirate.previous_changes["updated_on"][0]
|
563
|
+
assert_not_nil pirate.previous_changes["updated_on"][1]
|
564
|
+
assert_not pirate.previous_changes.key?("parrot_id")
|
565
|
+
assert_not pirate.previous_changes.key?("created_on")
|
566
|
+
|
567
|
+
pirate = Pirate.find_by_catchphrase("Me Maties!")
|
568
|
+
|
569
|
+
travel(1.second)
|
570
|
+
|
571
|
+
pirate.catchphrase = "Thar She Blows!"
|
572
|
+
pirate.save
|
573
|
+
|
574
|
+
assert_equal 2, pirate.previous_changes.size
|
575
|
+
assert_equal ["Me Maties!", "Thar She Blows!"], pirate.previous_changes["catchphrase"]
|
576
|
+
assert_equal "Me Maties!", pirate.catchphrase_previously_was
|
577
|
+
assert_not_nil pirate.previous_changes["updated_on"][0]
|
578
|
+
assert_not_nil pirate.previous_changes["updated_on"][1]
|
579
|
+
assert_not pirate.previous_changes.key?("parrot_id")
|
580
|
+
assert_not pirate.previous_changes.key?("created_on")
|
581
|
+
|
582
|
+
travel(1.second)
|
583
|
+
|
584
|
+
pirate = Pirate.find_by_catchphrase("Thar She Blows!")
|
585
|
+
pirate.update(catchphrase: "Ahoy!")
|
586
|
+
|
587
|
+
assert_equal 2, pirate.previous_changes.size
|
588
|
+
assert_equal ["Thar She Blows!", "Ahoy!"], pirate.previous_changes["catchphrase"]
|
589
|
+
assert_equal "Thar She Blows!", pirate.catchphrase_previously_was
|
590
|
+
assert_not_nil pirate.previous_changes["updated_on"][0]
|
591
|
+
assert_not_nil pirate.previous_changes["updated_on"][1]
|
592
|
+
assert_not pirate.previous_changes.key?("parrot_id")
|
593
|
+
assert_not pirate.previous_changes.key?("created_on")
|
594
|
+
|
595
|
+
travel(1.second)
|
596
|
+
|
597
|
+
pirate = Pirate.find_by_catchphrase("Ahoy!")
|
598
|
+
pirate.update_attribute(:catchphrase, "Ninjas suck!")
|
599
|
+
|
600
|
+
assert_equal 2, pirate.previous_changes.size
|
601
|
+
assert_equal ["Ahoy!", "Ninjas suck!"], pirate.previous_changes["catchphrase"]
|
602
|
+
assert_equal "Ahoy!", pirate.catchphrase_previously_was
|
603
|
+
assert_not_nil pirate.previous_changes["updated_on"][0]
|
604
|
+
assert_not_nil pirate.previous_changes["updated_on"][1]
|
605
|
+
assert_not pirate.previous_changes.key?("parrot_id")
|
606
|
+
assert_not pirate.previous_changes.key?("created_on")
|
607
|
+
end
|
608
|
+
|
609
|
+
class Testings < ActiveRecord::Base; end
|
610
|
+
def test_field_named_field
|
611
|
+
ActiveRecord::Base.connection.create_table :testings do |t|
|
612
|
+
t.string :field
|
613
|
+
end
|
614
|
+
assert_nothing_raised do
|
615
|
+
Testings.new.attributes
|
616
|
+
end
|
617
|
+
ensure
|
618
|
+
ActiveRecord::Base.connection.drop_table :testings rescue nil
|
619
|
+
ActiveRecord::Base.clear_cache!
|
620
|
+
end
|
621
|
+
|
622
|
+
def test_datetime_attribute_can_be_updated_with_fractional_seconds
|
623
|
+
skip "Fractional seconds are not supported" unless supports_datetime_with_precision?
|
624
|
+
in_time_zone "Paris" do
|
625
|
+
target = Class.new(ActiveRecord::Base)
|
626
|
+
target.table_name = "topics"
|
627
|
+
|
628
|
+
written_on = Time.utc(2012, 12, 1, 12, 0, 0).in_time_zone("Paris")
|
629
|
+
|
630
|
+
topic = target.create(written_on: written_on)
|
631
|
+
topic.written_on += 0.3
|
632
|
+
|
633
|
+
assert topic.written_on_changed?, "Fractional second update not detected"
|
634
|
+
end
|
635
|
+
end
|
636
|
+
|
637
|
+
def test_datetime_attribute_doesnt_change_if_zone_is_modified_in_string
|
638
|
+
time_in_paris = Time.utc(2014, 1, 1, 12, 0, 0).in_time_zone("Paris")
|
639
|
+
pirate = Pirate.create!(catchphrase: "rrrr", created_on: time_in_paris)
|
640
|
+
|
641
|
+
pirate.created_on = pirate.created_on.in_time_zone("Tokyo").to_s
|
642
|
+
assert_not_predicate pirate, :created_on_changed?
|
643
|
+
end
|
644
|
+
|
645
|
+
test "partial insert" do
|
646
|
+
with_partial_writes Person do
|
647
|
+
jon = nil
|
648
|
+
assert_sql(/first_name/i) do
|
649
|
+
jon = Person.create! first_name: "Jon"
|
650
|
+
end
|
651
|
+
|
652
|
+
assert ActiveRecord::SQLCounter.log_all.none? { |sql| sql.include?("followers_count") }
|
653
|
+
|
654
|
+
jon.reload
|
655
|
+
assert_equal "Jon", jon.first_name
|
656
|
+
assert_equal 0, jon.followers_count
|
657
|
+
assert_not_nil jon.id
|
658
|
+
end
|
659
|
+
end
|
660
|
+
|
661
|
+
test "partial insert with empty values" do
|
662
|
+
with_partial_writes Aircraft do
|
663
|
+
a = Aircraft.create!
|
664
|
+
a.reload
|
665
|
+
assert_not_nil a.id
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
test "in place mutation detection" do
|
670
|
+
pirate = Pirate.create!(catchphrase: "arrrr")
|
671
|
+
pirate.catchphrase << " matey!"
|
672
|
+
|
673
|
+
assert_predicate pirate, :catchphrase_changed?
|
674
|
+
expected_changes = {
|
675
|
+
"catchphrase" => ["arrrr", "arrrr matey!"]
|
676
|
+
}
|
677
|
+
assert_equal(expected_changes, pirate.changes)
|
678
|
+
assert_equal("arrrr", pirate.catchphrase_was)
|
679
|
+
assert pirate.catchphrase_changed?(from: "arrrr")
|
680
|
+
assert_not pirate.catchphrase_changed?(from: "anything else")
|
681
|
+
assert_includes pirate.changed_attributes, :catchphrase
|
682
|
+
|
683
|
+
pirate.save!
|
684
|
+
pirate.reload
|
685
|
+
|
686
|
+
assert_equal "arrrr matey!", pirate.catchphrase
|
687
|
+
assert_not_predicate pirate, :changed?
|
688
|
+
end
|
689
|
+
|
690
|
+
test "in place mutation for binary" do
|
691
|
+
klass = Class.new(ActiveRecord::Base) do
|
692
|
+
self.table_name = :binaries
|
693
|
+
serialize :data
|
694
|
+
end
|
695
|
+
|
696
|
+
binary = klass.create!(data: "\\\\foo")
|
697
|
+
|
698
|
+
assert_not_predicate binary, :changed?
|
699
|
+
|
700
|
+
binary.data = binary.data.dup
|
701
|
+
|
702
|
+
assert_not_predicate binary, :changed?
|
703
|
+
|
704
|
+
binary = klass.last
|
705
|
+
|
706
|
+
assert_not_predicate binary, :changed?
|
707
|
+
|
708
|
+
binary.data << "bar"
|
709
|
+
|
710
|
+
assert_predicate binary, :changed?
|
711
|
+
end
|
712
|
+
|
713
|
+
test "changes is correct for subclass" do
|
714
|
+
foo = Class.new(Pirate) do
|
715
|
+
def catchphrase
|
716
|
+
super.upcase
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
720
|
+
pirate = foo.create!(catchphrase: "arrrr")
|
721
|
+
|
722
|
+
new_catchphrase = "arrrr matey!"
|
723
|
+
|
724
|
+
pirate.catchphrase = new_catchphrase
|
725
|
+
assert_predicate pirate, :catchphrase_changed?
|
726
|
+
|
727
|
+
expected_changes = {
|
728
|
+
"catchphrase" => ["arrrr", new_catchphrase]
|
729
|
+
}
|
730
|
+
|
731
|
+
assert_equal new_catchphrase.upcase, pirate.catchphrase
|
732
|
+
assert_equal expected_changes, pirate.changes
|
733
|
+
end
|
734
|
+
|
735
|
+
test "changes is correct if override attribute reader" do
|
736
|
+
pirate = Pirate.create!(catchphrase: "arrrr")
|
737
|
+
def pirate.catchphrase
|
738
|
+
super.upcase
|
739
|
+
end
|
740
|
+
|
741
|
+
new_catchphrase = "arrrr matey!"
|
742
|
+
|
743
|
+
pirate.catchphrase = new_catchphrase
|
744
|
+
assert_predicate pirate, :catchphrase_changed?
|
745
|
+
|
746
|
+
expected_changes = {
|
747
|
+
"catchphrase" => ["arrrr", new_catchphrase]
|
748
|
+
}
|
749
|
+
|
750
|
+
assert_equal new_catchphrase.upcase, pirate.catchphrase
|
751
|
+
assert_equal expected_changes, pirate.changes
|
752
|
+
end
|
753
|
+
|
754
|
+
test "attribute_changed? doesn't compute in-place changes for unrelated attributes" do
|
755
|
+
test_type_class = Class.new(ActiveRecord::Type::Value) do
|
756
|
+
define_method(:changed_in_place?) do |*|
|
757
|
+
raise
|
758
|
+
end
|
759
|
+
end
|
760
|
+
klass = Class.new(ActiveRecord::Base) do
|
761
|
+
self.table_name = "people"
|
762
|
+
attribute :foo, test_type_class.new
|
763
|
+
end
|
764
|
+
|
765
|
+
model = klass.new(first_name: "Jim")
|
766
|
+
assert_predicate model, :first_name_changed?
|
767
|
+
end
|
768
|
+
|
769
|
+
test "attribute_will_change! doesn't try to save non-persistable attributes" do
|
770
|
+
klass = Class.new(ActiveRecord::Base) do
|
771
|
+
self.table_name = "people"
|
772
|
+
attribute :non_persisted_attribute, :string
|
773
|
+
end
|
774
|
+
|
775
|
+
record = klass.new(first_name: "Sean")
|
776
|
+
record.non_persisted_attribute_will_change!
|
777
|
+
|
778
|
+
assert_predicate record, :non_persisted_attribute_changed?
|
779
|
+
assert record.save
|
780
|
+
end
|
781
|
+
|
782
|
+
test "virtual attributes are not written with partial_writes off" do
|
783
|
+
with_partial_writes(ActiveRecord::Base, false) do
|
784
|
+
klass = Class.new(ActiveRecord::Base) do
|
785
|
+
self.table_name = "people"
|
786
|
+
attribute :non_persisted_attribute, :string
|
787
|
+
end
|
788
|
+
|
789
|
+
record = klass.new(first_name: "Sean")
|
790
|
+
record.non_persisted_attribute_will_change!
|
791
|
+
|
792
|
+
assert record.save
|
793
|
+
|
794
|
+
record.non_persisted_attribute_will_change!
|
795
|
+
|
796
|
+
assert record.save
|
797
|
+
end
|
798
|
+
end
|
799
|
+
|
800
|
+
test "mutating and then assigning doesn't remove the change" do
|
801
|
+
pirate = Pirate.create!(catchphrase: "arrrr")
|
802
|
+
pirate.catchphrase << " matey!"
|
803
|
+
pirate.catchphrase = "arrrr matey!"
|
804
|
+
|
805
|
+
assert pirate.catchphrase_changed?(from: "arrrr", to: "arrrr matey!")
|
806
|
+
end
|
807
|
+
|
808
|
+
test "getters with side effects are allowed" do
|
809
|
+
klass = Class.new(Pirate) do
|
810
|
+
def catchphrase
|
811
|
+
if super.blank?
|
812
|
+
update_attribute(:catchphrase, "arr") # what could possibly go wrong?
|
813
|
+
end
|
814
|
+
super
|
815
|
+
end
|
816
|
+
end
|
817
|
+
|
818
|
+
pirate = klass.create!(catchphrase: "lol")
|
819
|
+
pirate.update_attribute(:catchphrase, nil)
|
820
|
+
|
821
|
+
assert_equal "arr", pirate.catchphrase
|
822
|
+
end
|
823
|
+
|
824
|
+
test "attributes assigned but not selected are dirty" do
|
825
|
+
person = Person.select(:id).first
|
826
|
+
assert_not_predicate person, :changed?
|
827
|
+
|
828
|
+
person.first_name = "Sean"
|
829
|
+
assert_predicate person, :changed?
|
830
|
+
|
831
|
+
person.first_name = nil
|
832
|
+
assert_predicate person, :changed?
|
833
|
+
end
|
834
|
+
|
835
|
+
test "attributes not selected are still missing after save" do
|
836
|
+
person = Person.select(:id).first
|
837
|
+
assert_raises(ActiveModel::MissingAttributeError) { person.first_name }
|
838
|
+
assert person.save # calls forget_attribute_assignments
|
839
|
+
assert_raises(ActiveModel::MissingAttributeError) { person.first_name }
|
840
|
+
end
|
841
|
+
|
842
|
+
test "saved_change_to_attribute? returns whether a change occurred in the last save" do
|
843
|
+
person = Person.create!(first_name: "Sean")
|
844
|
+
|
845
|
+
assert_predicate person, :saved_change_to_first_name?
|
846
|
+
assert_not_predicate person, :saved_change_to_gender?
|
847
|
+
assert person.saved_change_to_first_name?(from: nil, to: "Sean")
|
848
|
+
assert person.saved_change_to_first_name?(from: nil)
|
849
|
+
assert person.saved_change_to_first_name?(to: "Sean")
|
850
|
+
assert_not person.saved_change_to_first_name?(from: "Jim", to: "Sean")
|
851
|
+
assert_not person.saved_change_to_first_name?(from: "Jim")
|
852
|
+
assert_not person.saved_change_to_first_name?(to: "Jim")
|
853
|
+
end
|
854
|
+
|
855
|
+
test "saved_change_to_attribute returns the change that occurred in the last save" do
|
856
|
+
person = Person.create!(first_name: "Sean", gender: "M")
|
857
|
+
|
858
|
+
assert_equal [nil, "Sean"], person.saved_change_to_first_name
|
859
|
+
assert_equal [nil, "M"], person.saved_change_to_gender
|
860
|
+
|
861
|
+
person.update(first_name: "Jim")
|
862
|
+
|
863
|
+
assert_equal ["Sean", "Jim"], person.saved_change_to_first_name
|
864
|
+
assert_nil person.saved_change_to_gender
|
865
|
+
end
|
866
|
+
|
867
|
+
test "attribute_before_last_save returns the original value before saving" do
|
868
|
+
person = Person.create!(first_name: "Sean", gender: "M")
|
869
|
+
|
870
|
+
assert_nil person.first_name_before_last_save
|
871
|
+
assert_nil person.gender_before_last_save
|
872
|
+
|
873
|
+
person.first_name = "Jim"
|
874
|
+
|
875
|
+
assert_nil person.first_name_before_last_save
|
876
|
+
assert_nil person.gender_before_last_save
|
877
|
+
|
878
|
+
person.save
|
879
|
+
|
880
|
+
assert_equal "Sean", person.first_name_before_last_save
|
881
|
+
assert_equal "M", person.gender_before_last_save
|
882
|
+
end
|
883
|
+
|
884
|
+
test "saved_changes? returns whether the last call to save changed anything" do
|
885
|
+
person = Person.create!(first_name: "Sean")
|
886
|
+
|
887
|
+
assert_predicate person, :saved_changes?
|
888
|
+
|
889
|
+
person.save
|
890
|
+
|
891
|
+
assert_not_predicate person, :saved_changes?
|
892
|
+
end
|
893
|
+
|
894
|
+
test "saved_changes returns a hash of all the changes that occurred" do
|
895
|
+
person = Person.create!(first_name: "Sean", gender: "M")
|
896
|
+
|
897
|
+
assert_equal [nil, "Sean"], person.saved_changes[:first_name]
|
898
|
+
assert_equal [nil, "M"], person.saved_changes[:gender]
|
899
|
+
assert_equal %w(id first_name gender created_at updated_at).sort, person.saved_changes.keys.sort
|
900
|
+
|
901
|
+
travel(1.second) do
|
902
|
+
person.update(first_name: "Jim")
|
903
|
+
end
|
904
|
+
|
905
|
+
assert_equal ["Sean", "Jim"], person.saved_changes[:first_name]
|
906
|
+
assert_equal %w(first_name lock_version updated_at).sort, person.saved_changes.keys.sort
|
907
|
+
end
|
908
|
+
|
909
|
+
test "changed? in after callbacks returns false" do
|
910
|
+
klass = Class.new(ActiveRecord::Base) do
|
911
|
+
self.table_name = "people"
|
912
|
+
|
913
|
+
after_save do
|
914
|
+
raise "changed? should be false" if changed?
|
915
|
+
raise "has_changes_to_save? should be false" if has_changes_to_save?
|
916
|
+
raise "saved_changes? should be true" unless saved_changes?
|
917
|
+
raise "id_in_database should not be nil" if id_in_database.nil?
|
918
|
+
end
|
919
|
+
end
|
920
|
+
|
921
|
+
person = klass.create!(first_name: "Sean")
|
922
|
+
assert_not_predicate person, :changed?
|
923
|
+
end
|
924
|
+
|
925
|
+
test "changed? in around callbacks after yield returns false" do
|
926
|
+
klass = Class.new(ActiveRecord::Base) do
|
927
|
+
self.table_name = "people"
|
928
|
+
|
929
|
+
around_create :check_around
|
930
|
+
|
931
|
+
def check_around
|
932
|
+
yield
|
933
|
+
raise "changed? should be false" if changed?
|
934
|
+
raise "has_changes_to_save? should be false" if has_changes_to_save?
|
935
|
+
raise "saved_changes? should be true" unless saved_changes?
|
936
|
+
raise "id_in_database should not be nil" if id_in_database.nil?
|
937
|
+
end
|
938
|
+
end
|
939
|
+
|
940
|
+
person = klass.create!(first_name: "Sean")
|
941
|
+
assert_not_predicate person, :changed?
|
942
|
+
end
|
943
|
+
|
944
|
+
private
|
945
|
+
def with_partial_writes(klass, on = true)
|
946
|
+
old = klass.partial_writes?
|
947
|
+
klass.partial_writes = on
|
948
|
+
yield
|
949
|
+
ensure
|
950
|
+
klass.partial_writes = old
|
951
|
+
end
|
952
|
+
|
953
|
+
def check_pirate_after_save_failure(pirate)
|
954
|
+
assert_predicate pirate, :changed?
|
955
|
+
assert_predicate pirate, :parrot_id_changed?
|
956
|
+
assert_equal %w(parrot_id), pirate.changed
|
957
|
+
assert_nil pirate.parrot_id_was
|
958
|
+
end
|
959
|
+
end
|