ibm_db 3.0.5-x86-mingw32 → 5.0.5-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 +5 -5
- data/CHANGES +4 -0
- data/LICENSE +1 -1
- data/ParameterizedQueries README +6 -6
- data/README +38 -55
- data/ext/Makefile +269 -0
- data/ext/extconf.rb +34 -3
- data/ext/gil_release_version +3 -0
- data/ext/ibm_db-i386-mingw32.def +2 -0
- data/ext/ibm_db.c +100 -108
- data/ext/ibm_db.o +0 -0
- data/ext/ibm_db.so +0 -0
- data/ext/mkmf.log +110 -0
- data/ext/ruby_ibm_db_cli.o +0 -0
- data/ext/unicode_support_version +3 -0
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +923 -527
- data/lib/active_record/connection_adapters/ibmdb_adapter.rb +4 -1
- data/lib/mswin32/ibm_db.rb +7 -39
- data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
- data/test/active_record/connection_adapters/fake_adapter.rb +8 -5
- data/test/cases/adapter_test.rb +133 -58
- data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
- data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
- data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
- data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
- data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
- data/test/cases/adapters/mysql2/connection_test.rb +210 -0
- data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
- data/test/cases/adapters/mysql2/enum_test.rb +26 -0
- data/test/cases/adapters/mysql2/explain_test.rb +21 -0
- data/test/cases/adapters/mysql2/json_test.rb +195 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
- data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
- data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
- data/test/cases/adapters/mysql2/schema_test.rb +126 -0
- data/test/cases/adapters/mysql2/sp_test.rb +36 -0
- data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
- data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
- data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
- data/test/cases/adapters/postgresql/array_test.rb +339 -0
- data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
- data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
- data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
- data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
- data/test/cases/adapters/postgresql/citext_test.rb +78 -0
- data/test/cases/adapters/postgresql/collation_test.rb +53 -0
- data/test/cases/adapters/postgresql/composite_test.rb +132 -0
- data/test/cases/adapters/postgresql/connection_test.rb +257 -0
- data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
- data/test/cases/adapters/postgresql/domain_test.rb +47 -0
- data/test/cases/adapters/postgresql/enum_test.rb +91 -0
- data/test/cases/adapters/postgresql/explain_test.rb +20 -0
- data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
- data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
- data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
- data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
- data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
- data/test/cases/adapters/postgresql/integer_test.rb +25 -0
- data/test/cases/adapters/postgresql/json_test.rb +237 -0
- data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
- data/test/cases/adapters/postgresql/money_test.rb +96 -0
- data/test/cases/adapters/postgresql/network_test.rb +94 -0
- data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
- data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
- data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
- data/test/cases/adapters/postgresql/range_test.rb +343 -0
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
- data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
- data/test/cases/adapters/postgresql/schema_test.rb +597 -0
- data/test/cases/adapters/postgresql/serial_test.rb +154 -0
- data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
- data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
- data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
- data/test/cases/adapters/postgresql/utils_test.rb +62 -0
- data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
- data/test/cases/adapters/postgresql/xml_test.rb +54 -0
- data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
- data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
- data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
- data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
- data/test/cases/aggregations_test.rb +11 -1
- data/test/cases/ar_schema_test.rb +35 -50
- data/test/cases/associations/association_scope_test.rb +1 -6
- data/test/cases/associations/belongs_to_associations_test.rb +122 -10
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
- data/test/cases/associations/callbacks_test.rb +5 -7
- data/test/cases/associations/cascaded_eager_loading_test.rb +1 -1
- data/test/cases/associations/eager_load_nested_include_test.rb +1 -3
- data/test/cases/associations/eager_test.rb +158 -73
- data/test/cases/associations/extension_test.rb +7 -2
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +64 -32
- data/test/cases/associations/has_many_associations_test.rb +362 -43
- data/test/cases/associations/has_many_through_associations_test.rb +108 -41
- data/test/cases/associations/has_one_associations_test.rb +105 -8
- data/test/cases/associations/has_one_through_associations_test.rb +6 -3
- data/test/cases/associations/inner_join_association_test.rb +3 -3
- data/test/cases/associations/inverse_associations_test.rb +38 -11
- data/test/cases/associations/join_model_test.rb +59 -36
- data/test/cases/associations/left_outer_join_association_test.rb +88 -0
- data/test/cases/associations/nested_through_associations_test.rb +2 -2
- data/test/cases/associations/required_test.rb +25 -5
- data/test/cases/associations_test.rb +39 -34
- data/test/cases/attribute_decorators_test.rb +9 -8
- data/test/cases/attribute_methods/read_test.rb +5 -5
- data/test/cases/attribute_methods_test.rb +97 -40
- data/test/cases/attribute_set_test.rb +64 -4
- data/test/cases/attribute_test.rb +84 -18
- data/test/cases/attributes_test.rb +151 -34
- data/test/cases/autosave_association_test.rb +149 -36
- data/test/cases/base_test.rb +290 -241
- data/test/cases/batches_test.rb +299 -22
- data/test/cases/binary_test.rb +2 -10
- data/test/cases/bind_parameter_test.rb +76 -66
- data/test/cases/cache_key_test.rb +26 -0
- data/test/cases/calculations_test.rb +167 -15
- data/test/cases/callbacks_test.rb +161 -68
- data/test/cases/coders/json_test.rb +15 -0
- data/test/cases/collection_cache_key_test.rb +115 -0
- data/test/cases/column_definition_test.rb +26 -57
- data/test/cases/comment_test.rb +145 -0
- data/test/cases/connection_adapters/adapter_leasing_test.rb +5 -3
- data/test/cases/connection_adapters/connection_handler_test.rb +128 -21
- data/test/cases/connection_adapters/connection_specification_test.rb +1 -1
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +0 -38
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +5 -1
- data/test/cases/connection_adapters/schema_cache_test.rb +8 -3
- data/test/cases/connection_adapters/type_lookup_test.rb +15 -7
- data/test/cases/connection_management_test.rb +46 -56
- data/test/cases/connection_pool_test.rb +195 -20
- data/test/cases/connection_specification/resolver_test.rb +15 -0
- data/test/cases/counter_cache_test.rb +10 -5
- data/test/cases/custom_locking_test.rb +1 -1
- data/test/cases/database_statements_test.rb +18 -3
- data/test/cases/{invalid_date_test.rb → date_test.rb} +13 -1
- data/test/cases/date_time_precision_test.rb +107 -0
- data/test/cases/defaults_test.rb +85 -89
- data/test/cases/dirty_test.rb +30 -52
- data/test/cases/disconnected_test.rb +4 -2
- data/test/cases/enum_test.rb +178 -24
- data/test/cases/errors_test.rb +16 -0
- data/test/cases/explain_test.rb +32 -21
- data/test/cases/finder_test.rb +273 -148
- data/test/cases/fixture_set/file_test.rb +18 -0
- data/test/cases/fixtures_test.rb +112 -32
- data/test/cases/forbidden_attributes_protection_test.rb +69 -3
- data/test/cases/helper.rb +10 -16
- data/test/cases/hot_compatibility_test.rb +89 -1
- data/test/cases/inheritance_test.rb +284 -53
- data/test/cases/integration_test.rb +23 -7
- data/test/cases/invalid_connection_test.rb +4 -2
- data/test/cases/invertible_migration_test.rb +124 -32
- data/test/cases/json_serialization_test.rb +11 -2
- data/test/cases/locking_test.rb +22 -6
- data/test/cases/log_subscriber_test.rb +106 -17
- data/test/cases/migration/change_schema_test.rb +60 -114
- data/test/cases/migration/change_table_test.rb +34 -2
- data/test/cases/migration/column_attributes_test.rb +7 -23
- data/test/cases/migration/column_positioning_test.rb +8 -8
- data/test/cases/migration/columns_test.rb +17 -11
- data/test/cases/migration/command_recorder_test.rb +47 -2
- data/test/cases/migration/compatibility_test.rb +118 -0
- data/test/cases/migration/create_join_table_test.rb +21 -12
- data/test/cases/migration/foreign_key_test.rb +52 -18
- data/test/cases/migration/index_test.rb +14 -12
- data/test/cases/migration/logger_test.rb +1 -1
- data/test/cases/migration/pending_migrations_test.rb +0 -1
- data/test/cases/migration/references_foreign_key_test.rb +59 -7
- data/test/cases/migration/references_index_test.rb +4 -4
- data/test/cases/migration/references_statements_test.rb +26 -6
- data/test/cases/migration/rename_table_test.rb +25 -25
- data/test/cases/migration_test.rb +279 -81
- data/test/cases/migrator_test.rb +91 -8
- data/test/cases/mixin_test.rb +0 -2
- data/test/cases/modules_test.rb +3 -4
- data/test/cases/multiparameter_attributes_test.rb +24 -2
- data/test/cases/multiple_db_test.rb +11 -4
- data/test/cases/nested_attributes_test.rb +61 -33
- data/test/cases/persistence_test.rb +102 -10
- data/test/cases/pooled_connections_test.rb +3 -3
- data/test/cases/primary_keys_test.rb +170 -31
- data/test/cases/query_cache_test.rb +216 -96
- data/test/cases/quoting_test.rb +65 -19
- data/test/cases/readonly_test.rb +2 -1
- data/test/cases/reflection_test.rb +68 -22
- data/test/cases/relation/delegation_test.rb +3 -8
- data/test/cases/relation/merging_test.rb +10 -14
- data/test/cases/relation/mutation_test.rb +42 -24
- data/test/cases/relation/or_test.rb +92 -0
- data/test/cases/relation/predicate_builder_test.rb +4 -2
- data/test/cases/relation/record_fetch_warning_test.rb +40 -0
- data/test/cases/relation/where_chain_test.rb +23 -99
- data/test/cases/relation/where_clause_test.rb +182 -0
- data/test/cases/relation/where_test.rb +45 -23
- data/test/cases/relation_test.rb +67 -58
- data/test/cases/relations_test.rb +249 -38
- data/test/cases/result_test.rb +10 -0
- data/test/cases/sanitize_test.rb +108 -15
- data/test/cases/schema_dumper_test.rb +119 -125
- data/test/cases/schema_loading_test.rb +52 -0
- data/test/cases/scoping/default_scoping_test.rb +113 -39
- data/test/cases/scoping/named_scoping_test.rb +46 -9
- data/test/cases/scoping/relation_scoping_test.rb +47 -4
- data/test/cases/secure_token_test.rb +32 -0
- data/test/cases/serialization_test.rb +1 -1
- data/test/cases/serialized_attribute_test.rb +93 -6
- data/test/cases/statement_cache_test.rb +38 -0
- data/test/cases/store_test.rb +2 -1
- data/test/cases/suppressor_test.rb +63 -0
- data/test/cases/tasks/database_tasks_test.rb +73 -9
- data/test/cases/tasks/mysql_rake_test.rb +139 -118
- data/test/cases/tasks/postgresql_rake_test.rb +60 -6
- data/test/cases/tasks/sqlite_rake_test.rb +30 -3
- data/test/cases/test_case.rb +28 -20
- data/test/cases/test_fixtures_test.rb +36 -0
- data/test/cases/time_precision_test.rb +103 -0
- data/test/cases/timestamp_test.rb +44 -10
- data/test/cases/touch_later_test.rb +121 -0
- data/test/cases/transaction_callbacks_test.rb +128 -62
- data/test/cases/transaction_isolation_test.rb +2 -2
- data/test/cases/transactions_test.rb +61 -43
- data/test/cases/type/adapter_specific_registry_test.rb +133 -0
- data/test/cases/type/date_time_test.rb +14 -0
- data/test/cases/type/integer_test.rb +2 -96
- data/test/cases/type/string_test.rb +0 -14
- data/test/cases/type_test.rb +39 -0
- data/test/cases/types_test.rb +1 -118
- data/test/cases/unconnected_test.rb +1 -1
- data/test/cases/validations/absence_validation_test.rb +73 -0
- data/test/cases/validations/association_validation_test.rb +13 -2
- data/test/cases/validations/i18n_validation_test.rb +6 -10
- data/test/cases/validations/length_validation_test.rb +62 -30
- data/test/cases/validations/presence_validation_test.rb +36 -1
- data/test/cases/validations/uniqueness_validation_test.rb +128 -37
- data/test/cases/validations_repair_helper.rb +2 -6
- data/test/cases/validations_test.rb +36 -7
- data/test/cases/view_test.rb +102 -5
- data/test/cases/yaml_serialization_test.rb +21 -26
- data/test/config.example.yml +97 -0
- data/test/fixtures/bad_posts.yml +9 -0
- data/test/fixtures/books.yml +20 -0
- data/test/fixtures/content.yml +3 -0
- data/test/fixtures/content_positions.yml +3 -0
- data/test/fixtures/dead_parrots.yml +5 -0
- data/test/fixtures/live_parrots.yml +4 -0
- data/test/fixtures/naked/yml/parrots.yml +2 -0
- data/test/fixtures/naked/yml/trees.yml +3 -0
- data/test/fixtures/nodes.yml +29 -0
- data/test/fixtures/other_comments.yml +6 -0
- data/test/fixtures/other_dogs.yml +2 -0
- data/test/fixtures/other_posts.yml +7 -0
- data/test/fixtures/price_estimates.yml +10 -1
- data/test/fixtures/trees.yml +3 -0
- data/test/migrations/10_urban/9_add_expressions.rb +1 -1
- data/test/migrations/decimal/1_give_me_big_numbers.rb +1 -1
- data/test/migrations/magic/1_currencies_have_symbols.rb +1 -1
- data/test/migrations/missing/1000_people_have_middle_names.rb +2 -2
- data/test/migrations/missing/1_people_have_last_names.rb +2 -2
- data/test/migrations/missing/3_we_need_reminders.rb +2 -2
- data/test/migrations/missing/4_innocent_jointable.rb +2 -2
- data/test/migrations/rename/1_we_need_things.rb +2 -2
- data/test/migrations/rename/2_rename_things.rb +2 -2
- data/test/migrations/to_copy/1_people_have_hobbies.rb +1 -1
- data/test/migrations/to_copy/2_people_have_descriptions.rb +1 -1
- data/test/migrations/to_copy2/1_create_articles.rb +1 -1
- data/test/migrations/to_copy2/2_create_comments.rb +1 -1
- data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +1 -1
- data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +1 -1
- data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +1 -1
- data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +1 -1
- data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +1 -1
- data/test/migrations/valid/1_valid_people_have_last_names.rb +1 -1
- data/test/migrations/valid/2_we_need_reminders.rb +2 -2
- data/test/migrations/valid/3_innocent_jointable.rb +2 -2
- data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +1 -1
- data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -2
- data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +2 -2
- data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +1 -1
- data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +1 -1
- data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +1 -1
- data/test/migrations/version_check/20131219224947_migration_version_check.rb +1 -1
- data/test/models/admin/randomly_named_c1.rb +6 -2
- data/test/models/aircraft.rb +1 -0
- data/test/models/author.rb +4 -7
- data/test/models/bird.rb +1 -1
- data/test/models/book.rb +5 -0
- data/test/models/bulb.rb +2 -1
- data/test/models/car.rb +3 -0
- data/test/models/cat.rb +10 -0
- data/test/models/chef.rb +1 -0
- data/test/models/club.rb +2 -0
- data/test/models/comment.rb +17 -5
- data/test/models/company.rb +4 -2
- data/test/models/company_in_module.rb +1 -1
- data/test/models/contact.rb +1 -1
- data/test/models/content.rb +40 -0
- data/test/models/customer.rb +8 -2
- data/test/models/developer.rb +19 -0
- data/test/models/face.rb +1 -1
- data/test/models/guitar.rb +4 -0
- data/test/models/hotel.rb +2 -0
- data/test/models/member.rb +1 -0
- data/test/models/member_detail.rb +4 -3
- data/test/models/mentor.rb +3 -0
- data/test/models/mocktail_designer.rb +2 -0
- data/test/models/node.rb +5 -0
- data/test/models/non_primary_key.rb +2 -0
- data/test/models/notification.rb +3 -0
- data/test/models/other_dog.rb +5 -0
- data/test/models/owner.rb +4 -1
- data/test/models/parrot.rb +6 -7
- data/test/models/person.rb +0 -1
- data/test/models/pet.rb +3 -0
- data/test/models/pet_treasure.rb +6 -0
- data/test/models/pirate.rb +3 -3
- data/test/models/post.rb +18 -9
- data/test/models/project.rb +9 -0
- data/test/models/randomly_named_c1.rb +1 -1
- data/test/models/recipe.rb +3 -0
- data/test/models/ship.rb +8 -2
- data/test/models/tag.rb +6 -0
- data/test/models/topic.rb +2 -8
- data/test/models/tree.rb +3 -0
- data/test/models/tuning_peg.rb +4 -0
- data/test/models/user.rb +14 -0
- data/test/models/uuid_item.rb +6 -0
- data/test/schema/mysql2_specific_schema.rb +33 -23
- data/test/schema/oracle_specific_schema.rb +1 -4
- data/test/schema/postgresql_specific_schema.rb +36 -124
- data/test/schema/schema.rb +170 -65
- data/test/schema/schema.rb.original +1057 -0
- data/test/schema/sqlite_specific_schema.rb +1 -5
- data/test/support/connection.rb +1 -0
- data/test/support/schema_dumping_helper.rb +1 -1
- 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
- metadata +146 -30
- data/lib/mswin32/rb19x/ibm_db.so +0 -0
- data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
- data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
- data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
- data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
- data/test/cases/attribute_methods/serialization_test.rb +0 -29
- data/test/cases/migration/change_schema_test - Copy.rb +0 -448
- data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
- data/test/cases/migration/table_and_index_test.rb +0 -24
- data/test/cases/relation/where_test2.rb +0 -36
- data/test/cases/type/decimal_test.rb +0 -56
- data/test/cases/type/unsigned_integer_test.rb +0 -18
- data/test/cases/xml_serialization_test.rb +0 -457
- data/test/fixtures/naked/csv/accounts.csv +0 -1
- data/test/schema/mysql_specific_schema.rb +0 -70
@@ -29,7 +29,7 @@ module ActiveRecord
|
|
29
29
|
assert_equal :bar, attributes[:bar].name
|
30
30
|
end
|
31
31
|
|
32
|
-
test "duping creates a new hash
|
32
|
+
test "duping creates a new hash, but does not dup the attributes" do
|
33
33
|
builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::String.new)
|
34
34
|
attributes = builder.build_from_database(foo: 1, bar: 'foo')
|
35
35
|
|
@@ -41,6 +41,24 @@ module ActiveRecord
|
|
41
41
|
duped.write_from_database(:foo, 2)
|
42
42
|
duped[:bar].value << 'bar'
|
43
43
|
|
44
|
+
assert_equal 1, attributes[:foo].value
|
45
|
+
assert_equal 2, duped[:foo].value
|
46
|
+
assert_equal 'foobar', attributes[:bar].value
|
47
|
+
assert_equal 'foobar', duped[:bar].value
|
48
|
+
end
|
49
|
+
|
50
|
+
test "deep_duping creates a new hash and dups each attribute" do
|
51
|
+
builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::String.new)
|
52
|
+
attributes = builder.build_from_database(foo: 1, bar: 'foo')
|
53
|
+
|
54
|
+
# Ensure the type cast value is cached
|
55
|
+
attributes[:foo].value
|
56
|
+
attributes[:bar].value
|
57
|
+
|
58
|
+
duped = attributes.deep_dup
|
59
|
+
duped.write_from_database(:foo, 2)
|
60
|
+
duped[:bar].value << 'bar'
|
61
|
+
|
44
62
|
assert_equal 1, attributes[:foo].value
|
45
63
|
assert_equal 2, duped[:foo].value
|
46
64
|
assert_equal 'foo', attributes[:bar].value
|
@@ -142,7 +160,8 @@ module ActiveRecord
|
|
142
160
|
end
|
143
161
|
|
144
162
|
test "the primary_key is always initialized" do
|
145
|
-
|
163
|
+
defaults = { foo: Attribute.from_user(:foo, nil, nil) }
|
164
|
+
builder = AttributeSet::Builder.new({ foo: Type::Integer.new }, defaults)
|
146
165
|
attributes = builder.build_from_database
|
147
166
|
|
148
167
|
assert attributes.key?(:foo)
|
@@ -151,15 +170,18 @@ module ActiveRecord
|
|
151
170
|
end
|
152
171
|
|
153
172
|
class MyType
|
154
|
-
def
|
173
|
+
def cast(value)
|
155
174
|
return if value.nil?
|
156
175
|
value + " from user"
|
157
176
|
end
|
158
177
|
|
159
|
-
def
|
178
|
+
def deserialize(value)
|
160
179
|
return if value.nil?
|
161
180
|
value + " from database"
|
162
181
|
end
|
182
|
+
|
183
|
+
def assert_valid_value(*)
|
184
|
+
end
|
163
185
|
end
|
164
186
|
|
165
187
|
test "write_from_database sets the attribute with database typecasting" do
|
@@ -197,6 +219,44 @@ module ActiveRecord
|
|
197
219
|
assert_equal({ foo: "1" }, attributes.to_hash)
|
198
220
|
end
|
199
221
|
|
222
|
+
test "marshaling dump/load legacy materialized attribute hash" do
|
223
|
+
builder = AttributeSet::Builder.new(foo: Type::String.new)
|
224
|
+
attributes = builder.build_from_database(foo: "1")
|
225
|
+
|
226
|
+
attributes.instance_variable_get(:@attributes).instance_eval do
|
227
|
+
class << self
|
228
|
+
def marshal_dump
|
229
|
+
materialize
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
235
|
+
assert_equal({ foo: "1" }, attributes.to_hash)
|
236
|
+
end
|
237
|
+
|
238
|
+
test "#accessed_attributes returns only attributes which have been read" do
|
239
|
+
builder = AttributeSet::Builder.new(foo: Type::Value.new, bar: Type::Value.new)
|
240
|
+
attributes = builder.build_from_database(foo: "1", bar: "2")
|
241
|
+
|
242
|
+
assert_equal [], attributes.accessed
|
243
|
+
|
244
|
+
attributes.fetch_value(:foo)
|
245
|
+
|
246
|
+
assert_equal [:foo], attributes.accessed
|
247
|
+
end
|
248
|
+
|
249
|
+
test "#map returns a new attribute set with the changes applied" do
|
250
|
+
builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::Integer.new)
|
251
|
+
attributes = builder.build_from_database(foo: "1", bar: "2")
|
252
|
+
new_attributes = attributes.map do |attr|
|
253
|
+
attr.with_cast_value(attr.value + 1)
|
254
|
+
end
|
255
|
+
|
256
|
+
assert_equal 2, new_attributes.fetch_value(:foo)
|
257
|
+
assert_equal 3, new_attributes.fetch_value(:bar)
|
258
|
+
end
|
259
|
+
|
200
260
|
test "comparison for equality is correctly implemented" do
|
201
261
|
builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::Integer.new)
|
202
262
|
attributes = builder.build_from_database(foo: "1", bar: "2")
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'cases/helper'
|
2
|
-
require 'minitest/mock'
|
3
2
|
|
4
3
|
module ActiveRecord
|
5
4
|
class AttributeTest < ActiveRecord::TestCase
|
@@ -12,7 +11,7 @@ module ActiveRecord
|
|
12
11
|
end
|
13
12
|
|
14
13
|
test "from_database + read type casts from database" do
|
15
|
-
@type.expect(:
|
14
|
+
@type.expect(:deserialize, 'type cast from database', ['a value'])
|
16
15
|
attribute = Attribute.from_database(nil, 'a value', @type)
|
17
16
|
|
18
17
|
type_cast_value = attribute.value
|
@@ -21,7 +20,7 @@ module ActiveRecord
|
|
21
20
|
end
|
22
21
|
|
23
22
|
test "from_user + read type casts from user" do
|
24
|
-
@type.expect(:
|
23
|
+
@type.expect(:cast, 'type cast from user', ['a value'])
|
25
24
|
attribute = Attribute.from_user(nil, 'a value', @type)
|
26
25
|
|
27
26
|
type_cast_value = attribute.value
|
@@ -30,7 +29,7 @@ module ActiveRecord
|
|
30
29
|
end
|
31
30
|
|
32
31
|
test "reading memoizes the value" do
|
33
|
-
@type.expect(:
|
32
|
+
@type.expect(:deserialize, 'from the database', ['whatever'])
|
34
33
|
attribute = Attribute.from_database(nil, 'whatever', @type)
|
35
34
|
|
36
35
|
type_cast_value = attribute.value
|
@@ -41,7 +40,7 @@ module ActiveRecord
|
|
41
40
|
end
|
42
41
|
|
43
42
|
test "reading memoizes falsy values" do
|
44
|
-
@type.expect(:
|
43
|
+
@type.expect(:deserialize, false, ['whatever'])
|
45
44
|
attribute = Attribute.from_database(nil, 'whatever', @type)
|
46
45
|
|
47
46
|
attribute.value
|
@@ -57,27 +56,27 @@ module ActiveRecord
|
|
57
56
|
end
|
58
57
|
|
59
58
|
test "from_database + read_for_database type casts to and from database" do
|
60
|
-
@type.expect(:
|
61
|
-
@type.expect(:
|
59
|
+
@type.expect(:deserialize, 'read from database', ['whatever'])
|
60
|
+
@type.expect(:serialize, 'ready for database', ['read from database'])
|
62
61
|
attribute = Attribute.from_database(nil, 'whatever', @type)
|
63
62
|
|
64
|
-
|
63
|
+
serialize = attribute.value_for_database
|
65
64
|
|
66
|
-
assert_equal 'ready for database',
|
65
|
+
assert_equal 'ready for database', serialize
|
67
66
|
end
|
68
67
|
|
69
68
|
test "from_user + read_for_database type casts from the user to the database" do
|
70
|
-
@type.expect(:
|
71
|
-
@type.expect(:
|
69
|
+
@type.expect(:cast, 'read from user', ['whatever'])
|
70
|
+
@type.expect(:serialize, 'ready for database', ['read from user'])
|
72
71
|
attribute = Attribute.from_user(nil, 'whatever', @type)
|
73
72
|
|
74
|
-
|
73
|
+
serialize = attribute.value_for_database
|
75
74
|
|
76
|
-
assert_equal 'ready for database',
|
75
|
+
assert_equal 'ready for database', serialize
|
77
76
|
end
|
78
77
|
|
79
78
|
test "duping dups the value" do
|
80
|
-
@type.expect(:
|
79
|
+
@type.expect(:deserialize, 'type cast', ['a value'])
|
81
80
|
attribute = Attribute.from_database(nil, 'a value', @type)
|
82
81
|
|
83
82
|
value_from_orig = attribute.value
|
@@ -89,7 +88,7 @@ module ActiveRecord
|
|
89
88
|
end
|
90
89
|
|
91
90
|
test "duping does not dup the value if it is not dupable" do
|
92
|
-
@type.expect(:
|
91
|
+
@type.expect(:deserialize, false, ['a value'])
|
93
92
|
attribute = Attribute.from_database(nil, 'a value', @type)
|
94
93
|
|
95
94
|
assert_same attribute.value, attribute.dup.value
|
@@ -101,13 +100,16 @@ module ActiveRecord
|
|
101
100
|
end
|
102
101
|
|
103
102
|
class MyType
|
104
|
-
def
|
103
|
+
def cast(value)
|
105
104
|
value + " from user"
|
106
105
|
end
|
107
106
|
|
108
|
-
def
|
107
|
+
def deserialize(value)
|
109
108
|
value + " from database"
|
110
109
|
end
|
110
|
+
|
111
|
+
def assert_valid_value(*)
|
112
|
+
end
|
111
113
|
end
|
112
114
|
|
113
115
|
test "with_value_from_user returns a new attribute with the value from the user" do
|
@@ -169,12 +171,76 @@ module ActiveRecord
|
|
169
171
|
assert_not_equal first, second
|
170
172
|
end
|
171
173
|
|
174
|
+
test "an attribute has not been read by default" do
|
175
|
+
attribute = Attribute.from_database(:foo, 1, Type::Value.new)
|
176
|
+
assert_not attribute.has_been_read?
|
177
|
+
end
|
178
|
+
|
179
|
+
test "an attribute has been read when its value is calculated" do
|
180
|
+
attribute = Attribute.from_database(:foo, 1, Type::Value.new)
|
181
|
+
attribute.value
|
182
|
+
assert attribute.has_been_read?
|
183
|
+
end
|
184
|
+
|
185
|
+
test "an attribute is not changed if it hasn't been assigned or mutated" do
|
186
|
+
attribute = Attribute.from_database(:foo, 1, Type::Value.new)
|
187
|
+
|
188
|
+
refute attribute.changed?
|
189
|
+
end
|
190
|
+
|
191
|
+
test "an attribute is changed if it's been assigned a new value" do
|
192
|
+
attribute = Attribute.from_database(:foo, 1, Type::Value.new)
|
193
|
+
changed = attribute.with_value_from_user(2)
|
194
|
+
|
195
|
+
assert changed.changed?
|
196
|
+
end
|
197
|
+
|
198
|
+
test "an attribute is not changed if it's assigned the same value" do
|
199
|
+
attribute = Attribute.from_database(:foo, 1, Type::Value.new)
|
200
|
+
unchanged = attribute.with_value_from_user(1)
|
201
|
+
|
202
|
+
refute unchanged.changed?
|
203
|
+
end
|
204
|
+
|
172
205
|
test "an attribute can not be mutated if it has not been read,
|
173
206
|
and skips expensive calculations" do
|
174
207
|
type_which_raises_from_all_methods = Object.new
|
175
208
|
attribute = Attribute.from_database(:foo, "bar", type_which_raises_from_all_methods)
|
176
209
|
|
177
|
-
assert_not attribute.
|
210
|
+
assert_not attribute.changed_in_place?
|
211
|
+
end
|
212
|
+
|
213
|
+
test "an attribute is changed if it has been mutated" do
|
214
|
+
attribute = Attribute.from_database(:foo, "bar", Type::String.new)
|
215
|
+
attribute.value << "!"
|
216
|
+
|
217
|
+
assert attribute.changed_in_place?
|
218
|
+
assert attribute.changed?
|
219
|
+
end
|
220
|
+
|
221
|
+
test "an attribute can forget its changes" do
|
222
|
+
attribute = Attribute.from_database(:foo, "bar", Type::String.new)
|
223
|
+
changed = attribute.with_value_from_user("foo")
|
224
|
+
forgotten = changed.forgetting_assignment
|
225
|
+
|
226
|
+
assert changed.changed? # sanity check
|
227
|
+
refute forgotten.changed?
|
228
|
+
end
|
229
|
+
|
230
|
+
test "with_value_from_user validates the value" do
|
231
|
+
type = Type::Value.new
|
232
|
+
type.define_singleton_method(:assert_valid_value) do |value|
|
233
|
+
if value == 1
|
234
|
+
raise ArgumentError
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
attribute = Attribute.from_database(:foo, 1, type)
|
239
|
+
assert_equal 1, attribute.value
|
240
|
+
assert_equal 2, attribute.with_value_from_user(2).value
|
241
|
+
assert_raises ArgumentError do
|
242
|
+
attribute.with_value_from_user(1)
|
243
|
+
end
|
178
244
|
end
|
179
245
|
end
|
180
246
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
require 'cases/helper'
|
2
2
|
|
3
3
|
class OverloadedType < ActiveRecord::Base
|
4
|
-
attribute :overloaded_float,
|
5
|
-
attribute :overloaded_string_with_limit,
|
6
|
-
attribute :non_existent_decimal,
|
7
|
-
attribute :string_with_default,
|
4
|
+
attribute :overloaded_float, :integer
|
5
|
+
attribute :overloaded_string_with_limit, :string, limit: 50
|
6
|
+
attribute :non_existent_decimal, :decimal
|
7
|
+
attribute :string_with_default, :string, default: 'the overloaded default'
|
8
8
|
end
|
9
9
|
|
10
10
|
class ChildOfOverloadedType < OverloadedType
|
11
11
|
end
|
12
12
|
|
13
13
|
class GrandchildOfOverloadedType < ChildOfOverloadedType
|
14
|
-
attribute :overloaded_float,
|
14
|
+
attribute :overloaded_float, :float
|
15
15
|
end
|
16
16
|
|
17
17
|
class UnoverloadedType < ActiveRecord::Base
|
@@ -38,7 +38,7 @@ module ActiveRecord
|
|
38
38
|
data.reload
|
39
39
|
|
40
40
|
assert_equal 2, data.overloaded_float
|
41
|
-
assert_kind_of
|
41
|
+
assert_kind_of Integer, OverloadedType.last.overloaded_float
|
42
42
|
assert_equal 2.0, UnoverloadedType.last.overloaded_float
|
43
43
|
assert_kind_of Float, UnoverloadedType.last.overloaded_float
|
44
44
|
end
|
@@ -50,8 +50,8 @@ module ActiveRecord
|
|
50
50
|
end
|
51
51
|
|
52
52
|
test "overloaded properties with limit" do
|
53
|
-
assert_equal 50, OverloadedType.
|
54
|
-
assert_equal 255, UnoverloadedType.
|
53
|
+
assert_equal 50, OverloadedType.type_for_attribute('overloaded_string_with_limit').limit
|
54
|
+
assert_equal 255, UnoverloadedType.type_for_attribute('overloaded_string_with_limit').limit
|
55
55
|
end
|
56
56
|
|
57
57
|
test "nonexistent attribute" do
|
@@ -63,6 +63,15 @@ module ActiveRecord
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
test "model with nonexistent attribute with default value can be saved" do
|
67
|
+
klass = Class.new(OverloadedType) do
|
68
|
+
attribute :non_existent_string_with_default, :string, default: 'nonexistent'
|
69
|
+
end
|
70
|
+
|
71
|
+
model = klass.new
|
72
|
+
assert model.save
|
73
|
+
end
|
74
|
+
|
66
75
|
test "changing defaults" do
|
67
76
|
data = OverloadedType.new
|
68
77
|
unoverloaded_data = UnoverloadedType.new
|
@@ -87,50 +96,158 @@ module ActiveRecord
|
|
87
96
|
assert_equal 4.4, data.overloaded_float
|
88
97
|
end
|
89
98
|
|
90
|
-
test "overloading properties does not
|
91
|
-
|
92
|
-
assert_equal %w(id overloaded_float unoverloaded_float overloaded_string_with_limit string_with_default non_existent_decimal),
|
99
|
+
test "overloading properties does not attribute method order" do
|
100
|
+
attribute_names = OverloadedType.attribute_names
|
101
|
+
assert_equal %w(id overloaded_float unoverloaded_float overloaded_string_with_limit string_with_default non_existent_decimal), attribute_names
|
93
102
|
end
|
94
103
|
|
95
104
|
test "caches are cleared" do
|
96
105
|
klass = Class.new(OverloadedType)
|
97
106
|
|
98
|
-
assert_equal 6, klass.
|
99
|
-
assert_not klass.columns_hash.key?('wibble')
|
100
|
-
assert_equal 6, klass.column_types.length
|
107
|
+
assert_equal 6, klass.attribute_types.length
|
101
108
|
assert_equal 6, klass.column_defaults.length
|
102
|
-
assert_not klass.
|
103
|
-
assert_equal 5, klass.content_columns.length
|
109
|
+
assert_not klass.attribute_types.include?('wibble')
|
104
110
|
|
105
111
|
klass.attribute :wibble, Type::Value.new
|
106
112
|
|
107
|
-
assert_equal 7, klass.
|
108
|
-
assert klass.columns_hash.key?('wibble')
|
109
|
-
assert_equal 7, klass.column_types.length
|
113
|
+
assert_equal 7, klass.attribute_types.length
|
110
114
|
assert_equal 7, klass.column_defaults.length
|
111
|
-
assert klass.
|
112
|
-
assert_equal 6, klass.content_columns.length
|
115
|
+
assert klass.attribute_types.include?('wibble')
|
113
116
|
end
|
114
117
|
|
115
|
-
test "
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
118
|
+
test "the given default value is cast from user" do
|
119
|
+
custom_type = Class.new(Type::Value) do
|
120
|
+
def cast(*)
|
121
|
+
"from user"
|
122
|
+
end
|
123
|
+
|
124
|
+
def deserialize(*)
|
125
|
+
"from database"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
klass = Class.new(OverloadedType) do
|
130
|
+
attribute :wibble, custom_type.new, default: "default"
|
131
|
+
end
|
132
|
+
model = klass.new
|
133
|
+
|
134
|
+
assert_equal "from user", model.wibble
|
135
|
+
end
|
136
|
+
|
137
|
+
test "procs for default values" do
|
138
|
+
klass = Class.new(OverloadedType) do
|
139
|
+
@@counter = 0
|
140
|
+
attribute :counter, :integer, default: -> { @@counter += 1 }
|
141
|
+
end
|
142
|
+
|
143
|
+
assert_equal 1, klass.new.counter
|
144
|
+
assert_equal 2, klass.new.counter
|
145
|
+
end
|
146
|
+
|
147
|
+
test "procs are memoized before type casting" do
|
148
|
+
klass = Class.new(OverloadedType) do
|
149
|
+
@@counter = 0
|
150
|
+
attribute :counter, :integer, default: -> { @@counter += 1 }
|
151
|
+
end
|
152
|
+
|
153
|
+
model = klass.new
|
154
|
+
assert_equal 1, model.counter_before_type_cast
|
155
|
+
assert_equal 1, model.counter_before_type_cast
|
156
|
+
end
|
157
|
+
|
158
|
+
test "user provided defaults are persisted even if unchanged" do
|
159
|
+
model = OverloadedType.create!
|
160
|
+
|
161
|
+
assert_equal "the overloaded default", model.reload.string_with_default
|
162
|
+
end
|
163
|
+
|
164
|
+
if current_adapter?(:PostgreSQLAdapter)
|
165
|
+
test "array types can be specified" do
|
166
|
+
klass = Class.new(OverloadedType) do
|
167
|
+
attribute :my_array, :string, limit: 50, array: true
|
168
|
+
attribute :my_int_array, :integer, array: true
|
169
|
+
end
|
170
|
+
|
171
|
+
string_array = ConnectionAdapters::PostgreSQL::OID::Array.new(
|
172
|
+
Type::String.new(limit: 50))
|
173
|
+
int_array = ConnectionAdapters::PostgreSQL::OID::Array.new(
|
174
|
+
Type::Integer.new)
|
175
|
+
assert_not_equal string_array, int_array
|
176
|
+
assert_equal string_array, klass.type_for_attribute("my_array")
|
177
|
+
assert_equal int_array, klass.type_for_attribute("my_int_array")
|
120
178
|
end
|
121
179
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
"N"
|
180
|
+
test "range types can be specified" do
|
181
|
+
klass = Class.new(OverloadedType) do
|
182
|
+
attribute :my_range, :string, limit: 50, range: true
|
183
|
+
attribute :my_int_range, :integer, range: true
|
127
184
|
end
|
185
|
+
|
186
|
+
string_range = ConnectionAdapters::PostgreSQL::OID::Range.new(
|
187
|
+
Type::String.new(limit: 50))
|
188
|
+
int_range = ConnectionAdapters::PostgreSQL::OID::Range.new(
|
189
|
+
Type::Integer.new)
|
190
|
+
assert_not_equal string_range, int_range
|
191
|
+
assert_equal string_range, klass.type_for_attribute("my_range")
|
192
|
+
assert_equal int_range, klass.type_for_attribute("my_int_range")
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
test "attributes added after subclasses load are inherited" do
|
197
|
+
parent = Class.new(ActiveRecord::Base) do
|
198
|
+
self.table_name = "topics"
|
199
|
+
end
|
200
|
+
|
201
|
+
child = Class.new(parent)
|
202
|
+
child.new # => force a schema load
|
203
|
+
|
204
|
+
parent.attribute(:foo, Type::Value.new)
|
205
|
+
|
206
|
+
assert_equal(:bar, child.new(foo: :bar).foo)
|
207
|
+
end
|
208
|
+
|
209
|
+
test "attributes not backed by database columns are not dirty when unchanged" do
|
210
|
+
refute OverloadedType.new.non_existent_decimal_changed?
|
211
|
+
end
|
212
|
+
|
213
|
+
test "attributes not backed by database columns are always initialized" do
|
214
|
+
OverloadedType.create!
|
215
|
+
model = OverloadedType.first
|
216
|
+
|
217
|
+
assert_nil model.non_existent_decimal
|
218
|
+
model.non_existent_decimal = "123"
|
219
|
+
assert_equal 123, model.non_existent_decimal
|
220
|
+
end
|
221
|
+
|
222
|
+
test "attributes not backed by database columns return the default on models loaded from database" do
|
223
|
+
child = Class.new(OverloadedType) do
|
224
|
+
attribute :non_existent_decimal, :decimal, default: 123
|
128
225
|
end
|
226
|
+
child.create!
|
227
|
+
model = child.first
|
228
|
+
|
229
|
+
assert_equal 123, model.non_existent_decimal
|
230
|
+
end
|
231
|
+
|
232
|
+
test "attributes not backed by database columns properly interact with mutation and dirty" do
|
233
|
+
child = Class.new(ActiveRecord::Base) do
|
234
|
+
self.table_name = "topics"
|
235
|
+
attribute :foo, :string, default: "lol"
|
236
|
+
end
|
237
|
+
child.create!
|
238
|
+
model = child.first
|
239
|
+
|
240
|
+
assert_equal "lol", model.foo
|
241
|
+
|
242
|
+
model.foo << "asdf"
|
243
|
+
assert_equal "lolasdf", model.foo
|
244
|
+
assert model.foo_changed?
|
129
245
|
|
130
|
-
|
131
|
-
|
246
|
+
model.reload
|
247
|
+
assert_equal "lol", model.foo
|
132
248
|
|
133
|
-
|
249
|
+
model.foo = "lol"
|
250
|
+
refute model.changed?
|
134
251
|
end
|
135
252
|
end
|
136
253
|
end
|