activerecord 5.2.8 → 7.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1393 -587
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +10 -9
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +122 -47
- data/lib/active_record/associations/association_scope.rb +24 -24
- data/lib/active_record/associations/belongs_to_association.rb +67 -49
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -7
- data/lib/active_record/associations/builder/association.rb +52 -23
- data/lib/active_record/associations/builder/belongs_to.rb +44 -61
- data/lib/active_record/associations/builder/collection_association.rb +17 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +10 -3
- data/lib/active_record/associations/builder/has_one.rb +35 -3
- data/lib/active_record/associations/builder/singular_association.rb +5 -3
- data/lib/active_record/associations/collection_association.rb +59 -50
- data/lib/active_record/associations/collection_proxy.rb +32 -23
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +27 -14
- data/lib/active_record/associations/has_many_through_association.rb +26 -19
- data/lib/active_record/associations/has_one_association.rb +52 -37
- data/lib/active_record/associations/has_one_through_association.rb +6 -6
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +97 -62
- data/lib/active_record/associations/preloader/association.rb +220 -60
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +85 -40
- data/lib/active_record/associations/preloader.rb +44 -105
- data/lib/active_record/associations/singular_association.rb +9 -17
- data/lib/active_record/associations/through_association.rb +4 -4
- data/lib/active_record/associations.rb +207 -66
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +19 -8
- data/lib/active_record/attribute_methods/dirty.rb +141 -47
- data/lib/active_record/attribute_methods/primary_key.rb +22 -27
- data/lib/active_record/attribute_methods/query.rb +6 -10
- data/lib/active_record/attribute_methods/read.rb +15 -55
- data/lib/active_record/attribute_methods/serialization.rb +77 -18
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +16 -18
- data/lib/active_record/attribute_methods/write.rb +18 -37
- data/lib/active_record/attribute_methods.rb +90 -153
- data/lib/active_record/attributes.rb +38 -12
- data/lib/active_record/autosave_association.rb +50 -50
- data/lib/active_record/base.rb +23 -18
- data/lib/active_record/callbacks.rb +159 -44
- data/lib/active_record/coders/yaml_column.rb +12 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +92 -464
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -51
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +209 -164
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +38 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +103 -82
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +140 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -94
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +16 -5
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +456 -159
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -162
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +311 -327
- data/lib/active_record/connection_adapters/column.rb +33 -11
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +113 -45
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +71 -5
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +25 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +143 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +63 -22
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +53 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +56 -63
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +54 -16
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +26 -12
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +39 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +128 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +149 -113
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +386 -182
- data/lib/active_record/connection_adapters/schema_cache.rb +161 -22
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +65 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +92 -26
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +251 -204
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +53 -0
- data/lib/active_record/connection_handling.rb +292 -38
- data/lib/active_record/core.rb +385 -158
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +100 -0
- data/lib/active_record/database_configurations/database_config.rb +83 -0
- data/lib/active_record/database_configurations/hash_config.rb +154 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +256 -0
- data/lib/active_record/delegated_type.rb +250 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +4 -5
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +90 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +130 -51
- data/lib/active_record/errors.rb +129 -23
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +22 -15
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +187 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +206 -490
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +104 -37
- data/lib/active_record/insert_all.rb +278 -0
- data/lib/active_record/integration.rb +69 -18
- data/lib/active_record/internal_metadata.rb +24 -9
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +41 -26
- data/lib/active_record/locking/pessimistic.rb +18 -8
- data/lib/active_record/log_subscriber.rb +46 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector.rb +82 -0
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +246 -64
- data/lib/active_record/migration/join_table.rb +1 -2
- data/lib/active_record/migration.rb +266 -187
- data/lib/active_record/model_schema.rb +165 -52
- data/lib/active_record/nested_attributes.rb +17 -19
- data/lib/active_record/no_touching.rb +11 -4
- data/lib/active_record/null_relation.rb +2 -7
- data/lib/active_record/persistence.rb +467 -92
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +51 -24
- data/lib/active_record/railtie.rb +224 -57
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +31 -36
- data/lib/active_record/railties/databases.rake +369 -101
- data/lib/active_record/readonly_attributes.rb +15 -0
- data/lib/active_record/reflection.rb +170 -137
- data/lib/active_record/relation/batches/batch_enumerator.rb +44 -14
- data/lib/active_record/relation/batches.rb +46 -37
- data/lib/active_record/relation/calculations.rb +168 -96
- data/lib/active_record/relation/delegation.rb +37 -52
- data/lib/active_record/relation/finder_methods.rb +79 -58
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +50 -51
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +58 -46
- data/lib/active_record/relation/query_attribute.rb +9 -10
- data/lib/active_record/relation/query_methods.rb +685 -208
- data/lib/active_record/relation/record_fetch_warning.rb +9 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -10
- data/lib/active_record/relation/where_clause.rb +108 -64
- data/lib/active_record/relation.rb +515 -151
- data/lib/active_record/result.rb +78 -42
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +29 -44
- data/lib/active_record/schema.rb +37 -31
- data/lib/active_record/schema_dumper.rb +74 -23
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +62 -17
- data/lib/active_record/scoping/named.rb +17 -32
- data/lib/active_record/scoping.rb +70 -41
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +6 -4
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +13 -17
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +352 -94
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +41 -39
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +44 -34
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +67 -128
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +34 -19
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +7 -4
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +9 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +2 -3
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +39 -31
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +209 -32
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +33 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +48 -0
- data/lib/arel/delete_manager.rb +32 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +48 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +44 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +45 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +46 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +71 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +258 -0
- data/lib/arel/select_manager.rb +276 -0
- data/lib/arel/table.rb +117 -0
- data/lib/arel/tree_manager.rb +60 -0
- data/lib/arel/update_manager.rb +48 -0
- data/lib/arel/visitors/dot.rb +298 -0
- data/lib/arel/visitors/mysql.rb +99 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +955 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +55 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +162 -32
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -7,7 +7,7 @@ module ActiveRecord
|
|
7
7
|
|
8
8
|
class ColumnNotSerializableError < StandardError
|
9
9
|
def initialize(name, type)
|
10
|
-
super
|
10
|
+
super <<~EOS
|
11
11
|
Column `#{name}` of type #{type.class} does not support `serialize` feature.
|
12
12
|
Usually it means that you are trying to use `serialize`
|
13
13
|
on a column that already implements serialization natively.
|
@@ -16,15 +16,45 @@ module ActiveRecord
|
|
16
16
|
end
|
17
17
|
|
18
18
|
module ClassMethods
|
19
|
-
# If you have an attribute that needs to be saved to the database as
|
20
|
-
# object, and retrieved
|
21
|
-
# attribute using this method and
|
22
|
-
#
|
23
|
-
# serialized object must be of that class on assignment and retrieval.
|
24
|
-
# Otherwise SerializationTypeMismatch will be raised.
|
19
|
+
# If you have an attribute that needs to be saved to the database as a
|
20
|
+
# serialized object, and retrieved by deserializing into the same object,
|
21
|
+
# then specify the name of that attribute using this method and serialization
|
22
|
+
# will be handled automatically.
|
25
23
|
#
|
26
|
-
#
|
27
|
-
#
|
24
|
+
# The serialization format may be YAML, JSON, or any custom format using a
|
25
|
+
# custom coder class.
|
26
|
+
#
|
27
|
+
# === Serialization formats
|
28
|
+
#
|
29
|
+
# serialize attr_name [, class_name_or_coder]
|
30
|
+
#
|
31
|
+
# | | database storage |
|
32
|
+
# class_name_or_coder | attribute read/write type | serialized | NULL |
|
33
|
+
# ---------------------+---------------------------+------------+--------+
|
34
|
+
# <not given> | any value that supports | YAML | |
|
35
|
+
# | .to_yaml | | |
|
36
|
+
# | | | |
|
37
|
+
# Array | Array ** | YAML | [] |
|
38
|
+
# | | | |
|
39
|
+
# Hash | Hash ** | YAML | {} |
|
40
|
+
# | | | |
|
41
|
+
# JSON | any value that supports | JSON | |
|
42
|
+
# | .to_json | | |
|
43
|
+
# | | | |
|
44
|
+
# <custom coder class> | any value supported by | custom | custom |
|
45
|
+
# | the custom coder class | | |
|
46
|
+
#
|
47
|
+
# ** If +class_name_or_coder+ is +Array+ or +Hash+, values retrieved will
|
48
|
+
# always be of that type, and any value assigned must be of that type or
|
49
|
+
# +SerializationTypeMismatch+ will be raised.
|
50
|
+
#
|
51
|
+
# ==== Custom coders
|
52
|
+
# A custom coder class or module may be given. This must have +self.load+
|
53
|
+
# and +self.dump+ class/module methods. <tt>self.dump(object)</tt> will be called
|
54
|
+
# to serialize an object and should return the serialized value to be
|
55
|
+
# stored in the database (+nil+ to store as +NULL+). <tt>self.load(string)</tt>
|
56
|
+
# will be called to reverse the process and load (unserialize) from the
|
57
|
+
# database.
|
28
58
|
#
|
29
59
|
# Keep in mind that database adapters handle certain serialization tasks
|
30
60
|
# for you. For instance: +json+ and +jsonb+ types in PostgreSQL will be
|
@@ -38,12 +68,19 @@ module ActiveRecord
|
|
38
68
|
# ==== Parameters
|
39
69
|
#
|
40
70
|
# * +attr_name+ - The field name that should be serialized.
|
41
|
-
# * +class_name_or_coder+ - Optional,
|
42
|
-
# or a
|
71
|
+
# * +class_name_or_coder+ - Optional, may be be +Array+ or +Hash+ or
|
72
|
+
# +JSON+ or a custom coder class or module which responds to +.load+
|
73
|
+
# and +.dump+. See table above.
|
74
|
+
#
|
75
|
+
# ==== Options
|
76
|
+
#
|
77
|
+
# +default+ The default value to use when no value is provided. If this option
|
78
|
+
# is not passed, the previous default value (if any) will be used.
|
79
|
+
# Otherwise, the default will be +nil+.
|
43
80
|
#
|
44
81
|
# ==== Example
|
45
82
|
#
|
46
|
-
# # Serialize a preferences attribute.
|
83
|
+
# # Serialize a preferences attribute using YAML coder.
|
47
84
|
# class User < ActiveRecord::Base
|
48
85
|
# serialize :preferences
|
49
86
|
# end
|
@@ -57,7 +94,29 @@ module ActiveRecord
|
|
57
94
|
# class User < ActiveRecord::Base
|
58
95
|
# serialize :preferences, Hash
|
59
96
|
# end
|
60
|
-
|
97
|
+
#
|
98
|
+
# # Serialize preferences using a custom coder.
|
99
|
+
# class Rot13JSON
|
100
|
+
# def self.rot13(string)
|
101
|
+
# string.tr("a-zA-Z", "n-za-mN-ZA-M")
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# # returns serialized string that will be stored in the database
|
105
|
+
# def self.dump(object)
|
106
|
+
# ActiveSupport::JSON.encode(object).rot13
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# # reverses the above, turning the serialized string from the database
|
110
|
+
# # back into its original value
|
111
|
+
# def self.load(string)
|
112
|
+
# ActiveSupport::JSON.decode(string.rot13)
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# class User < ActiveRecord::Base
|
117
|
+
# serialize :preferences, Rot13JSON
|
118
|
+
# end
|
119
|
+
def serialize(attr_name, class_name_or_coder = Object, **options)
|
61
120
|
# When ::JSON is used, force it to go through the Active Support JSON encoder
|
62
121
|
# to ensure special objects (e.g. Active Record models) are dumped correctly
|
63
122
|
# using the #as_json hook.
|
@@ -69,17 +128,17 @@ module ActiveRecord
|
|
69
128
|
Coders::YAMLColumn.new(attr_name, class_name_or_coder)
|
70
129
|
end
|
71
130
|
|
72
|
-
|
73
|
-
if type_incompatible_with_serialize?(
|
74
|
-
raise ColumnNotSerializableError.new(attr_name,
|
131
|
+
attribute(attr_name, **options) do |cast_type|
|
132
|
+
if type_incompatible_with_serialize?(cast_type, class_name_or_coder)
|
133
|
+
raise ColumnNotSerializableError.new(attr_name, cast_type)
|
75
134
|
end
|
76
135
|
|
77
|
-
Type::Serialized
|
136
|
+
cast_type = cast_type.subtype if Type::Serialized === cast_type
|
137
|
+
Type::Serialized.new(cast_type, coder)
|
78
138
|
end
|
79
139
|
end
|
80
140
|
|
81
141
|
private
|
82
|
-
|
83
142
|
def type_incompatible_with_serialize?(type, class_name)
|
84
143
|
type.is_a?(ActiveRecord::Type::Json) && class_name == ::JSON ||
|
85
144
|
type.respond_to?(:type_cast_array, true) && class_name == ::Array
|
@@ -1,9 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/object/try"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module AttributeMethods
|
5
7
|
module TimeZoneConversion
|
6
8
|
class TimeZoneConverter < DelegateClass(Type::Value) # :nodoc:
|
9
|
+
def self.new(subtype)
|
10
|
+
self === subtype ? subtype : super
|
11
|
+
end
|
12
|
+
|
7
13
|
def deserialize(value)
|
8
14
|
convert_time_to_time_zone(super)
|
9
15
|
end
|
@@ -19,19 +25,20 @@ module ActiveRecord
|
|
19
25
|
rescue ArgumentError
|
20
26
|
nil
|
21
27
|
end
|
28
|
+
elsif value.respond_to?(:infinite?) && value.infinite?
|
29
|
+
value
|
22
30
|
else
|
23
31
|
map_avoiding_infinite_recursion(super) { |v| cast(v) }
|
24
32
|
end
|
25
33
|
end
|
26
34
|
|
27
35
|
private
|
28
|
-
|
29
36
|
def convert_time_to_time_zone(value)
|
30
37
|
return if value.nil?
|
31
38
|
|
32
39
|
if value.acts_like?(:time)
|
33
40
|
value.in_time_zone
|
34
|
-
elsif value.
|
41
|
+
elsif value.respond_to?(:infinite?) && value.infinite?
|
35
42
|
value
|
36
43
|
else
|
37
44
|
map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
|
@@ -56,29 +63,20 @@ module ActiveRecord
|
|
56
63
|
extend ActiveSupport::Concern
|
57
64
|
|
58
65
|
included do
|
59
|
-
|
60
|
-
|
66
|
+
class_attribute :time_zone_aware_attributes, instance_writer: false, default: false
|
61
67
|
class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false, default: []
|
62
68
|
class_attribute :time_zone_aware_types, instance_writer: false, default: [ :datetime, :time ]
|
63
69
|
end
|
64
70
|
|
65
71
|
module ClassMethods # :nodoc:
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
super
|
70
|
-
# We need to apply this decorator here, rather than on module inclusion. The closure
|
71
|
-
# created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the
|
72
|
-
# sub class being decorated. As such, changes to `time_zone_aware_attributes`, or
|
73
|
-
# `skip_time_zone_conversion_for_attributes` would not be picked up.
|
74
|
-
subclass.class_eval do
|
75
|
-
matcher = ->(name, type) { create_time_zone_conversion_attribute?(name, type) }
|
76
|
-
decorate_matching_attribute_types(matcher, :_time_zone_conversion) do |type|
|
77
|
-
TimeZoneConverter.new(type)
|
78
|
-
end
|
79
|
-
end
|
72
|
+
def define_attribute(name, cast_type, **)
|
73
|
+
if create_time_zone_conversion_attribute?(name, cast_type)
|
74
|
+
cast_type = TimeZoneConverter.new(cast_type)
|
80
75
|
end
|
76
|
+
super
|
77
|
+
end
|
81
78
|
|
79
|
+
private
|
82
80
|
def create_time_zone_conversion_attribute?(name, cast_type)
|
83
81
|
enabled_for_column = time_zone_aware_attributes &&
|
84
82
|
!skip_time_zone_conversion_for_attributes.include?(name.to_sym)
|
@@ -6,26 +6,22 @@ module ActiveRecord
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
9
|
-
attribute_method_suffix "="
|
9
|
+
attribute_method_suffix "=", parameters: "value"
|
10
10
|
end
|
11
11
|
|
12
12
|
module ClassMethods # :nodoc:
|
13
13
|
private
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
#{sync_with_transaction_state}
|
24
|
-
_write_attribute(name, value)
|
14
|
+
def define_method_attribute=(name, owner:)
|
15
|
+
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
16
|
+
owner, name, writer: true,
|
17
|
+
) do |temp_method_name, attr_name_expr|
|
18
|
+
owner.define_cached_method("#{name}=", as: temp_method_name, namespace: :active_record) do |batch|
|
19
|
+
batch <<
|
20
|
+
"def #{temp_method_name}(value)" <<
|
21
|
+
" _write_attribute(#{attr_name_expr}, value)" <<
|
22
|
+
"end"
|
25
23
|
end
|
26
|
-
|
27
|
-
undef_method :__temp__#{safe_name}=
|
28
|
-
STR
|
24
|
+
end
|
29
25
|
end
|
30
26
|
end
|
31
27
|
|
@@ -33,36 +29,21 @@ module ActiveRecord
|
|
33
29
|
# specified +value+. Empty strings for Integer and Float columns are
|
34
30
|
# turned into +nil+.
|
35
31
|
def write_attribute(attr_name, value)
|
36
|
-
name =
|
37
|
-
|
38
|
-
else
|
39
|
-
attr_name.to_s
|
40
|
-
end
|
32
|
+
name = attr_name.to_s
|
33
|
+
name = self.class.attribute_aliases[name] || name
|
41
34
|
|
42
|
-
|
43
|
-
name
|
44
|
-
sync_with_transaction_state if name == primary_key
|
45
|
-
_write_attribute(name, value)
|
35
|
+
name = @primary_key if name == "id" && @primary_key
|
36
|
+
@attributes.write_from_user(name, value)
|
46
37
|
end
|
47
38
|
|
48
39
|
# This method exists to avoid the expensive primary_key check internally, without
|
49
40
|
# breaking compatibility with the write_attribute API
|
50
41
|
def _write_attribute(attr_name, value) # :nodoc:
|
51
|
-
@attributes.write_from_user(attr_name
|
52
|
-
value
|
42
|
+
@attributes.write_from_user(attr_name, value)
|
53
43
|
end
|
54
44
|
|
55
|
-
|
56
|
-
|
57
|
-
name = attr_name.to_s
|
58
|
-
@attributes.write_cast_value(name, value)
|
59
|
-
value
|
60
|
-
end
|
61
|
-
|
62
|
-
# Handle *= for method_missing.
|
63
|
-
def attribute=(attribute_name, value)
|
64
|
-
_write_attribute(attribute_name, value)
|
65
|
-
end
|
45
|
+
alias :attribute= :_write_attribute
|
46
|
+
private :attribute=
|
66
47
|
end
|
67
48
|
end
|
68
49
|
end
|