activerecord 5.0.6 → 6.0.1
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.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +638 -2023
- data/MIT-LICENSE +3 -1
- data/README.rdoc +8 -6
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record/aggregations.rb +249 -246
- data/lib/active_record/association_relation.rb +24 -13
- data/lib/active_record/associations/alias_tracker.rb +24 -33
- data/lib/active_record/associations/association.rb +119 -56
- data/lib/active_record/associations/association_scope.rb +94 -94
- data/lib/active_record/associations/belongs_to_association.rb +58 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +18 -25
- data/lib/active_record/associations/builder/belongs_to.rb +43 -54
- data/lib/active_record/associations/builder/collection_association.rb +7 -18
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -61
- data/lib/active_record/associations/builder/has_many.rb +4 -0
- data/lib/active_record/associations/builder/has_one.rb +37 -1
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +80 -252
- data/lib/active_record/associations/collection_proxy.rb +158 -121
- data/lib/active_record/associations/foreign_association.rb +9 -0
- data/lib/active_record/associations/has_many_association.rb +23 -29
- data/lib/active_record/associations/has_many_through_association.rb +58 -44
- data/lib/active_record/associations/has_one_association.rb +59 -54
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -90
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/join_dependency.rb +134 -176
- data/lib/active_record/associations/preloader/association.rb +84 -125
- data/lib/active_record/associations/preloader/through_association.rb +82 -75
- data/lib/active_record/associations/preloader.rb +90 -102
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +26 -14
- data/lib/active_record/associations.rb +1603 -1592
- data/lib/active_record/attribute_assignment.rb +54 -60
- data/lib/active_record/attribute_decorators.rb +38 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -7
- data/lib/active_record/attribute_methods/dirty.rb +179 -109
- data/lib/active_record/attribute_methods/primary_key.rb +86 -91
- data/lib/active_record/attribute_methods/query.rb +4 -3
- data/lib/active_record/attribute_methods/read.rb +21 -49
- data/lib/active_record/attribute_methods/serialization.rb +30 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -64
- data/lib/active_record/attribute_methods/write.rb +35 -33
- data/lib/active_record/attribute_methods.rb +66 -106
- data/lib/active_record/attributes.rb +38 -24
- data/lib/active_record/autosave_association.rb +53 -32
- data/lib/active_record/base.rb +27 -24
- data/lib/active_record/callbacks.rb +63 -33
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +11 -11
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +553 -321
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +213 -94
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -28
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -27
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -126
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +369 -199
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +363 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -551
- data/lib/active_record/connection_adapters/column.rb +41 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +172 -138
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +143 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +50 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +49 -30
- data/lib/active_record/connection_adapters/postgresql/column.rb +22 -7
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +60 -54
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -10
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -17
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +31 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +35 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +380 -300
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
- data/lib/active_record/connection_adapters/postgresql/utils.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +382 -275
- data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +74 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +254 -262
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -7
- data/lib/active_record/connection_handling.rb +159 -40
- data/lib/active_record/core.rb +202 -162
- data/lib/active_record/counter_cache.rb +57 -28
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -86
- data/lib/active_record/enum.rb +60 -23
- data/lib/active_record/errors.rb +114 -18
- data/lib/active_record/explain.rb +4 -3
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +13 -8
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +195 -502
- data/lib/active_record/gem_version.rb +4 -2
- data/lib/active_record/inheritance.rb +151 -97
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +116 -25
- data/lib/active_record/internal_metadata.rb +15 -18
- data/lib/active_record/legacy_yaml_adapter.rb +4 -2
- data/lib/active_record/locking/optimistic.rb +78 -87
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +48 -29
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +143 -97
- data/lib/active_record/migration/compatibility.rb +174 -56
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +367 -300
- data/lib/active_record/model_schema.rb +145 -139
- data/lib/active_record/nested_attributes.rb +214 -201
- data/lib/active_record/no_touching.rb +10 -1
- data/lib/active_record/null_relation.rb +13 -34
- data/lib/active_record/persistence.rb +442 -72
- data/lib/active_record/query_cache.rb +15 -14
- data/lib/active_record/querying.rb +36 -23
- data/lib/active_record/railtie.rb +128 -36
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +309 -177
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +211 -249
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/batches.rb +99 -52
- data/lib/active_record/relation/calculations.rb +211 -172
- data/lib/active_record/relation/delegation.rb +67 -65
- data/lib/active_record/relation/finder_methods.rb +208 -247
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +78 -61
- data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +86 -104
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +458 -329
- data/lib/active_record/relation/record_fetch_warning.rb +5 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -7
- data/lib/active_record/relation/where_clause.rb +111 -95
- data/lib/active_record/relation/where_clause_factory.rb +6 -11
- data/lib/active_record/relation.rb +429 -318
- data/lib/active_record/result.rb +69 -39
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +83 -99
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +71 -69
- data/lib/active_record/schema_migration.rb +15 -5
- data/lib/active_record/scoping/default.rb +93 -95
- data/lib/active_record/scoping/named.rb +45 -25
- data/lib/active_record/scoping.rb +20 -19
- data/lib/active_record/secure_token.rb +4 -2
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +63 -28
- data/lib/active_record/store.rb +121 -41
- data/lib/active_record/suppressor.rb +4 -1
- data/lib/active_record/table_metadata.rb +26 -20
- data/lib/active_record/tasks/database_tasks.rb +276 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +54 -90
- data/lib/active_record/tasks/postgresql_database_tasks.rb +78 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +34 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +70 -35
- data/lib/active_record/touch_later.rb +7 -4
- data/lib/active_record/transactions.rb +133 -149
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +44 -45
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +16 -8
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +2 -1
- data/lib/active_record/type/type_map.rb +13 -15
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +23 -17
- data/lib/active_record/type_caster/connection.rb +17 -12
- data/lib/active_record/type_caster/map.rb +5 -4
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +3 -1
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +29 -42
- data/lib/active_record/validations.rb +7 -4
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +36 -22
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -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/insert_manager.rb +49 -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 +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -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 +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -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 +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -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 +41 -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 +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +58 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
- data/lib/rails/generators/active_record/migration.rb +17 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -29
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +133 -50
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set/builder.rb +0 -130
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
| @@ -1,4 +1,6 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "set"
         | 
| 2 4 |  | 
| 3 5 | 
             
            module ActiveRecord
         | 
| 4 6 | 
             
              module AttributeMethods
         | 
| @@ -8,134 +10,127 @@ module ActiveRecord | |
| 8 10 | 
             
                  # Returns this record's primary key value wrapped in an array if one is
         | 
| 9 11 | 
             
                  # available.
         | 
| 10 12 | 
             
                  def to_key
         | 
| 11 | 
            -
                     | 
| 12 | 
            -
                    key = self.id
         | 
| 13 | 
            +
                    key = id
         | 
| 13 14 | 
             
                    [key] if key
         | 
| 14 15 | 
             
                  end
         | 
| 15 16 |  | 
| 16 | 
            -
                  # Returns the primary key value.
         | 
| 17 | 
            +
                  # Returns the primary key column's value.
         | 
| 17 18 | 
             
                  def id
         | 
| 18 | 
            -
                     | 
| 19 | 
            -
                      sync_with_transaction_state
         | 
| 20 | 
            -
                      _read_attribute(pk)
         | 
| 21 | 
            -
                    end
         | 
| 19 | 
            +
                    _read_attribute(@primary_key)
         | 
| 22 20 | 
             
                  end
         | 
| 23 21 |  | 
| 24 | 
            -
                  # Sets the primary key value.
         | 
| 22 | 
            +
                  # Sets the primary key column's value.
         | 
| 25 23 | 
             
                  def id=(value)
         | 
| 26 | 
            -
                     | 
| 27 | 
            -
                    write_attribute(self.class.primary_key, value) if self.class.primary_key
         | 
| 24 | 
            +
                    _write_attribute(@primary_key, value)
         | 
| 28 25 | 
             
                  end
         | 
| 29 26 |  | 
| 30 | 
            -
                  # Queries the primary key value.
         | 
| 27 | 
            +
                  # Queries the primary key column's value.
         | 
| 31 28 | 
             
                  def id?
         | 
| 32 | 
            -
                     | 
| 33 | 
            -
                    query_attribute(self.class.primary_key)
         | 
| 29 | 
            +
                    query_attribute(@primary_key)
         | 
| 34 30 | 
             
                  end
         | 
| 35 31 |  | 
| 36 | 
            -
                  # Returns the primary key value before type cast.
         | 
| 32 | 
            +
                  # Returns the primary key column's value before type cast.
         | 
| 37 33 | 
             
                  def id_before_type_cast
         | 
| 38 | 
            -
                     | 
| 39 | 
            -
                    read_attribute_before_type_cast(self.class.primary_key)
         | 
| 34 | 
            +
                    read_attribute_before_type_cast(@primary_key)
         | 
| 40 35 | 
             
                  end
         | 
| 41 36 |  | 
| 42 | 
            -
                  # Returns the primary key previous value.
         | 
| 37 | 
            +
                  # Returns the primary key column's previous value.
         | 
| 43 38 | 
             
                  def id_was
         | 
| 44 | 
            -
                     | 
| 45 | 
            -
                    attribute_was(self.class.primary_key)
         | 
| 39 | 
            +
                    attribute_was(@primary_key)
         | 
| 46 40 | 
             
                  end
         | 
| 47 41 |  | 
| 48 | 
            -
                   | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
                    attr_name == 'id' || super
         | 
| 42 | 
            +
                  # Returns the primary key column's value from the database.
         | 
| 43 | 
            +
                  def id_in_database
         | 
| 44 | 
            +
                    attribute_in_database(@primary_key)
         | 
| 52 45 | 
             
                  end
         | 
| 53 46 |  | 
| 54 | 
            -
                   | 
| 55 | 
            -
                    def define_method_attribute(attr_name)
         | 
| 56 | 
            -
                      super
         | 
| 47 | 
            +
                  private
         | 
| 57 48 |  | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
                      end
         | 
| 49 | 
            +
                    def attribute_method?(attr_name)
         | 
| 50 | 
            +
                      attr_name == "id" || super
         | 
| 61 51 | 
             
                    end
         | 
| 62 52 |  | 
| 63 | 
            -
                     | 
| 53 | 
            +
                    module ClassMethods
         | 
| 54 | 
            +
                      ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was id_in_database).to_set
         | 
| 64 55 |  | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 56 | 
            +
                      def instance_method_already_implemented?(method_name)
         | 
| 57 | 
            +
                        super || primary_key && ID_ATTRIBUTE_METHODS.include?(method_name)
         | 
| 58 | 
            +
                      end
         | 
| 68 59 |  | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
                    def primary_key
         | 
| 73 | 
            -
                      @primary_key = reset_primary_key unless defined? @primary_key
         | 
| 74 | 
            -
                      @primary_key
         | 
| 75 | 
            -
                    end
         | 
| 60 | 
            +
                      def dangerous_attribute_method?(method_name)
         | 
| 61 | 
            +
                        super && !ID_ATTRIBUTE_METHODS.include?(method_name)
         | 
| 62 | 
            +
                      end
         | 
| 76 63 |  | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
                       | 
| 81 | 
            -
             | 
| 64 | 
            +
                      # Defines the primary key field -- can be overridden in subclasses.
         | 
| 65 | 
            +
                      # Overwriting will negate any effect of the +primary_key_prefix_type+
         | 
| 66 | 
            +
                      # setting, though.
         | 
| 67 | 
            +
                      def primary_key
         | 
| 68 | 
            +
                        @primary_key = reset_primary_key unless defined? @primary_key
         | 
| 69 | 
            +
                        @primary_key
         | 
| 70 | 
            +
                      end
         | 
| 82 71 |  | 
| 83 | 
            -
             | 
| 84 | 
            -
                       | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
                        self.primary_key = base_class.primary_key
         | 
| 72 | 
            +
                      # Returns a quoted version of the primary key name, used to construct
         | 
| 73 | 
            +
                      # SQL statements.
         | 
| 74 | 
            +
                      def quoted_primary_key
         | 
| 75 | 
            +
                        @quoted_primary_key ||= connection.quote_column_name(primary_key)
         | 
| 88 76 | 
             
                      end
         | 
| 89 | 
            -
                    end
         | 
| 90 77 |  | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
                      elsif base_name && primary_key_prefix_type == :table_name_with_underscore
         | 
| 95 | 
            -
                        base_name.foreign_key
         | 
| 96 | 
            -
                      else
         | 
| 97 | 
            -
                        if ActiveRecord::Base != self && table_exists?
         | 
| 98 | 
            -
                          pk = connection.schema_cache.primary_keys(table_name)
         | 
| 99 | 
            -
                          suppress_composite_primary_key(pk)
         | 
| 78 | 
            +
                      def reset_primary_key #:nodoc:
         | 
| 79 | 
            +
                        if base_class?
         | 
| 80 | 
            +
                          self.primary_key = get_primary_key(base_class.name)
         | 
| 100 81 | 
             
                        else
         | 
| 101 | 
            -
                           | 
| 82 | 
            +
                          self.primary_key = base_class.primary_key
         | 
| 102 83 | 
             
                        end
         | 
| 103 84 | 
             
                      end
         | 
| 104 | 
            -
                    end
         | 
| 105 85 |  | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
                       | 
| 123 | 
            -
                       | 
| 124 | 
            -
                       | 
| 125 | 
            -
             | 
| 86 | 
            +
                      def get_primary_key(base_name) #:nodoc:
         | 
| 87 | 
            +
                        if base_name && primary_key_prefix_type == :table_name
         | 
| 88 | 
            +
                          base_name.foreign_key(false)
         | 
| 89 | 
            +
                        elsif base_name && primary_key_prefix_type == :table_name_with_underscore
         | 
| 90 | 
            +
                          base_name.foreign_key
         | 
| 91 | 
            +
                        else
         | 
| 92 | 
            +
                          if ActiveRecord::Base != self && table_exists?
         | 
| 93 | 
            +
                            pk = connection.schema_cache.primary_keys(table_name)
         | 
| 94 | 
            +
                            suppress_composite_primary_key(pk)
         | 
| 95 | 
            +
                          else
         | 
| 96 | 
            +
                            "id"
         | 
| 97 | 
            +
                          end
         | 
| 98 | 
            +
                        end
         | 
| 99 | 
            +
                      end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                      # Sets the name of the primary key column.
         | 
| 102 | 
            +
                      #
         | 
| 103 | 
            +
                      #   class Project < ActiveRecord::Base
         | 
| 104 | 
            +
                      #     self.primary_key = 'sysid'
         | 
| 105 | 
            +
                      #   end
         | 
| 106 | 
            +
                      #
         | 
| 107 | 
            +
                      # You can also define the #primary_key method yourself:
         | 
| 108 | 
            +
                      #
         | 
| 109 | 
            +
                      #   class Project < ActiveRecord::Base
         | 
| 110 | 
            +
                      #     def self.primary_key
         | 
| 111 | 
            +
                      #       'foo_' + super
         | 
| 112 | 
            +
                      #     end
         | 
| 113 | 
            +
                      #   end
         | 
| 114 | 
            +
                      #
         | 
| 115 | 
            +
                      #   Project.primary_key # => "foo_id"
         | 
| 116 | 
            +
                      def primary_key=(value)
         | 
| 117 | 
            +
                        @primary_key        = value && -value.to_s
         | 
| 118 | 
            +
                        @quoted_primary_key = nil
         | 
| 119 | 
            +
                        @attributes_builder = nil
         | 
| 120 | 
            +
                      end
         | 
| 126 121 |  | 
| 127 | 
            -
             | 
| 122 | 
            +
                      private
         | 
| 128 123 |  | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 124 | 
            +
                        def suppress_composite_primary_key(pk)
         | 
| 125 | 
            +
                          return pk unless pk.is_a?(Array)
         | 
| 131 126 |  | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 127 | 
            +
                          warn <<~WARNING
         | 
| 128 | 
            +
                            WARNING: Active Record does not support composite primary key.
         | 
| 134 129 |  | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 130 | 
            +
                            #{table_name} has composite primary key. Composite primary key is ignored.
         | 
| 131 | 
            +
                          WARNING
         | 
| 132 | 
            +
                        end
         | 
| 137 133 | 
             
                    end
         | 
| 138 | 
            -
                  end
         | 
| 139 134 | 
             
                end
         | 
| 140 135 | 
             
              end
         | 
| 141 136 | 
             
            end
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module ActiveRecord
         | 
| 2 4 | 
             
              module AttributeMethods
         | 
| 3 5 | 
             
                module Query
         | 
| @@ -14,8 +16,7 @@ module ActiveRecord | |
| 14 16 | 
             
                    when true        then true
         | 
| 15 17 | 
             
                    when false, nil  then false
         | 
| 16 18 | 
             
                    else
         | 
| 17 | 
            -
                       | 
| 18 | 
            -
                      if column.nil?
         | 
| 19 | 
            +
                      if !type_for_attribute(attr_name) { false }
         | 
| 19 20 | 
             
                        if Numeric === value || value !~ /[^0-9]/
         | 
| 20 21 | 
             
                          !value.to_i.zero?
         | 
| 21 22 | 
             
                        else
         | 
| @@ -31,7 +32,7 @@ module ActiveRecord | |
| 31 32 | 
             
                  end
         | 
| 32 33 |  | 
| 33 34 | 
             
                  private
         | 
| 34 | 
            -
                    #  | 
| 35 | 
            +
                    # Dispatch target for <tt>*?</tt> attribute methods.
         | 
| 35 36 | 
             
                    def attribute?(attribute_name)
         | 
| 36 37 | 
             
                      query_attribute(attribute_name)
         | 
| 37 38 | 
             
                    end
         | 
| @@ -1,47 +1,25 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module ActiveRecord
         | 
| 2 4 | 
             
              module AttributeMethods
         | 
| 3 5 | 
             
                module Read
         | 
| 4 6 | 
             
                  extend ActiveSupport::Concern
         | 
| 5 7 |  | 
| 6 | 
            -
                  module ClassMethods
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
                    # the __temp__ identifier, and then use alias method to rename
         | 
| 20 | 
            -
                    # it to what we want.
         | 
| 21 | 
            -
                    #
         | 
| 22 | 
            -
                    # We are also defining a constant to hold the frozen string of
         | 
| 23 | 
            -
                    # the attribute name. Using a constant means that we do not have
         | 
| 24 | 
            -
                    # to allocate an object on each call to the attribute method.
         | 
| 25 | 
            -
                    # Making it frozen means that it doesn't get duped when used to
         | 
| 26 | 
            -
                    # key the @attributes in read_attribute.
         | 
| 27 | 
            -
                    def define_method_attribute(name)
         | 
| 28 | 
            -
                      safe_name = name.unpack('h*'.freeze).first
         | 
| 29 | 
            -
                      temp_method = "__temp__#{safe_name}"
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                      ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                      generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
         | 
| 34 | 
            -
                        def #{temp_method}
         | 
| 35 | 
            -
                          name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
         | 
| 36 | 
            -
                          _read_attribute(name) { |n| missing_attribute(n, caller) }
         | 
| 8 | 
            +
                  module ClassMethods # :nodoc:
         | 
| 9 | 
            +
                    private
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                      def define_method_attribute(name)
         | 
| 12 | 
            +
                        ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
         | 
| 13 | 
            +
                          generated_attribute_methods, name
         | 
| 14 | 
            +
                        ) do |temp_method_name, attr_name_expr|
         | 
| 15 | 
            +
                          generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
         | 
| 16 | 
            +
                            def #{temp_method_name}
         | 
| 17 | 
            +
                              name = #{attr_name_expr}
         | 
| 18 | 
            +
                              _read_attribute(name) { |n| missing_attribute(n, caller) }
         | 
| 19 | 
            +
                            end
         | 
| 20 | 
            +
                          RUBY
         | 
| 37 21 | 
             
                        end
         | 
| 38 | 
            -
                      STR
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                      generated_attribute_methods.module_eval do
         | 
| 41 | 
            -
                        alias_method name, temp_method
         | 
| 42 | 
            -
                        undef_method temp_method
         | 
| 43 22 | 
             
                      end
         | 
| 44 | 
            -
                    end
         | 
| 45 23 | 
             
                  end
         | 
| 46 24 |  | 
| 47 25 | 
             
                  # Returns the value of the attribute identified by <tt>attr_name</tt> after
         | 
| @@ -49,27 +27,21 @@ module ActiveRecord | |
| 49 27 | 
             
                  # to a date object, like Date.new(2004, 12, 12)).
         | 
| 50 28 | 
             
                  def read_attribute(attr_name, &block)
         | 
| 51 29 | 
             
                    name = attr_name.to_s
         | 
| 52 | 
            -
                    name = self.class. | 
| 30 | 
            +
                    name = self.class.attribute_aliases[name] || name
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    name = @primary_key if name == "id" && @primary_key
         | 
| 53 33 | 
             
                    _read_attribute(name, &block)
         | 
| 54 34 | 
             
                  end
         | 
| 55 35 |  | 
| 56 36 | 
             
                  # This method exists to avoid the expensive primary_key check internally, without
         | 
| 57 37 | 
             
                  # breaking compatibility with the read_attribute API
         | 
| 58 | 
            -
                   | 
| 59 | 
            -
                     | 
| 60 | 
            -
                     | 
| 61 | 
            -
                    def _read_attribute(attr_name, &block) # :nodoc
         | 
| 62 | 
            -
                      @attributes.fetch_value(attr_name.to_s, &block)
         | 
| 63 | 
            -
                    end
         | 
| 64 | 
            -
                  else
         | 
| 65 | 
            -
                    def _read_attribute(attr_name) # :nodoc:
         | 
| 66 | 
            -
                      @attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? }
         | 
| 67 | 
            -
                    end
         | 
| 38 | 
            +
                  def _read_attribute(attr_name, &block) # :nodoc
         | 
| 39 | 
            +
                    sync_with_transaction_state if @transaction_state&.finalized?
         | 
| 40 | 
            +
                    @attributes.fetch_value(attr_name.to_s, &block)
         | 
| 68 41 | 
             
                  end
         | 
| 69 42 |  | 
| 70 43 | 
             
                  alias :attribute :_read_attribute
         | 
| 71 44 | 
             
                  private :attribute
         | 
| 72 | 
            -
             | 
| 73 45 | 
             
                end
         | 
| 74 46 | 
             
              end
         | 
| 75 47 | 
             
            end
         | 
| @@ -1,8 +1,20 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module ActiveRecord
         | 
| 2 4 | 
             
              module AttributeMethods
         | 
| 3 5 | 
             
                module Serialization
         | 
| 4 6 | 
             
                  extend ActiveSupport::Concern
         | 
| 5 7 |  | 
| 8 | 
            +
                  class ColumnNotSerializableError < StandardError
         | 
| 9 | 
            +
                    def initialize(name, type)
         | 
| 10 | 
            +
                      super <<~EOS
         | 
| 11 | 
            +
                        Column `#{name}` of type #{type.class} does not support `serialize` feature.
         | 
| 12 | 
            +
                        Usually it means that you are trying to use `serialize`
         | 
| 13 | 
            +
                        on a column that already implements serialization natively.
         | 
| 14 | 
            +
                      EOS
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 6 18 | 
             
                  module ClassMethods
         | 
| 7 19 | 
             
                    # If you have an attribute that needs to be saved to the database as an
         | 
| 8 20 | 
             
                    # object, and retrieved as the same object, then specify the name of that
         | 
| @@ -26,7 +38,7 @@ module ActiveRecord | |
| 26 38 | 
             
                    # ==== Parameters
         | 
| 27 39 | 
             
                    #
         | 
| 28 40 | 
             
                    # * +attr_name+ - The field name that should be serialized.
         | 
| 29 | 
            -
                    # * +class_name_or_coder+ - Optional, a coder object, which responds to  | 
| 41 | 
            +
                    # * +class_name_or_coder+ - Optional, a coder object, which responds to +.load+ and +.dump+
         | 
| 30 42 | 
             
                    #   or a class name that the object type should be equal to.
         | 
| 31 43 | 
             
                    #
         | 
| 32 44 | 
             
                    # ==== Example
         | 
| @@ -50,17 +62,28 @@ module ActiveRecord | |
| 50 62 | 
             
                      # to ensure special objects (e.g. Active Record models) are dumped correctly
         | 
| 51 63 | 
             
                      # using the #as_json hook.
         | 
| 52 64 | 
             
                      coder = if class_name_or_coder == ::JSON
         | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 65 | 
            +
                        Coders::JSON
         | 
| 66 | 
            +
                      elsif [:load, :dump].all? { |x| class_name_or_coder.respond_to?(x) }
         | 
| 67 | 
            +
                        class_name_or_coder
         | 
| 68 | 
            +
                      else
         | 
| 69 | 
            +
                        Coders::YAMLColumn.new(attr_name, class_name_or_coder)
         | 
| 70 | 
            +
                      end
         | 
| 59 71 |  | 
| 60 72 | 
             
                      decorate_attribute_type(attr_name, :serialize) do |type|
         | 
| 73 | 
            +
                        if type_incompatible_with_serialize?(type, class_name_or_coder)
         | 
| 74 | 
            +
                          raise ColumnNotSerializableError.new(attr_name, type)
         | 
| 75 | 
            +
                        end
         | 
| 76 | 
            +
             | 
| 61 77 | 
             
                        Type::Serialized.new(type, coder)
         | 
| 62 78 | 
             
                      end
         | 
| 63 79 | 
             
                    end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    private
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                      def type_incompatible_with_serialize?(type, class_name)
         | 
| 84 | 
            +
                        type.is_a?(ActiveRecord::Type::Json) && class_name == ::JSON ||
         | 
| 85 | 
            +
                          type.respond_to?(:type_cast_array, true) && class_name == ::Array
         | 
| 86 | 
            +
                      end
         | 
| 64 87 | 
             
                  end
         | 
| 65 88 | 
             
                end
         | 
| 66 89 | 
             
              end
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            module ActiveRecord
         | 
| 4 4 | 
             
              module AttributeMethods
         | 
| @@ -26,90 +26,65 @@ module ActiveRecord | |
| 26 26 |  | 
| 27 27 | 
             
                    private
         | 
| 28 28 |  | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 29 | 
            +
                      def convert_time_to_time_zone(value)
         | 
| 30 | 
            +
                        return if value.nil?
         | 
| 31 31 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 32 | 
            +
                        if value.acts_like?(:time)
         | 
| 33 | 
            +
                          value.in_time_zone
         | 
| 34 | 
            +
                        elsif value.is_a?(::Float)
         | 
| 35 | 
            +
                          value
         | 
| 36 | 
            +
                        else
         | 
| 37 | 
            +
                          map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
         | 
| 38 | 
            +
                        end
         | 
| 38 39 | 
             
                      end
         | 
| 39 | 
            -
                    end
         | 
| 40 40 |  | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 41 | 
            +
                      def set_time_zone_without_conversion(value)
         | 
| 42 | 
            +
                        ::Time.zone.local_to_utc(value).try(:in_time_zone) if value
         | 
| 43 | 
            +
                      end
         | 
| 44 44 |  | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 45 | 
            +
                      def map_avoiding_infinite_recursion(value)
         | 
| 46 | 
            +
                        map(value) do |v|
         | 
| 47 | 
            +
                          if value.equal?(v)
         | 
| 48 | 
            +
                            nil
         | 
| 49 | 
            +
                          else
         | 
| 50 | 
            +
                            yield(v)
         | 
| 51 | 
            +
                          end
         | 
| 51 52 | 
             
                        end
         | 
| 52 53 | 
             
                      end
         | 
| 53 | 
            -
                    end
         | 
| 54 54 | 
             
                  end
         | 
| 55 55 |  | 
| 56 56 | 
             
                  extend ActiveSupport::Concern
         | 
| 57 57 |  | 
| 58 58 | 
             
                  included do
         | 
| 59 | 
            -
                    mattr_accessor :time_zone_aware_attributes, instance_writer: false
         | 
| 60 | 
            -
                    self.time_zone_aware_attributes = false
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                    class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false
         | 
| 63 | 
            -
                    self.skip_time_zone_conversion_for_attributes = []
         | 
| 59 | 
            +
                    mattr_accessor :time_zone_aware_attributes, instance_writer: false, default: false
         | 
| 64 60 |  | 
| 65 | 
            -
                    class_attribute : | 
| 66 | 
            -
                     | 
| 61 | 
            +
                    class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false, default: []
         | 
| 62 | 
            +
                    class_attribute :time_zone_aware_types, instance_writer: false, default: [ :datetime, :time ]
         | 
| 67 63 | 
             
                  end
         | 
| 68 64 |  | 
| 69 | 
            -
                  module ClassMethods
         | 
| 65 | 
            +
                  module ClassMethods # :nodoc:
         | 
| 70 66 | 
             
                    private
         | 
| 71 67 |  | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
                         | 
| 79 | 
            -
             | 
| 80 | 
            -
                           | 
| 68 | 
            +
                      def inherited(subclass)
         | 
| 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
         | 
| 81 79 | 
             
                        end
         | 
| 82 80 | 
             
                      end
         | 
| 83 | 
            -
                      super
         | 
| 84 | 
            -
                    end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                    def create_time_zone_conversion_attribute?(name, cast_type)
         | 
| 87 | 
            -
                      enabled_for_column = time_zone_aware_attributes &&
         | 
| 88 | 
            -
                        !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym)
         | 
| 89 | 
            -
                      result = enabled_for_column &&
         | 
| 90 | 
            -
                        time_zone_aware_types.include?(cast_type.type)
         | 
| 91 | 
            -
             | 
| 92 | 
            -
                      if enabled_for_column &&
         | 
| 93 | 
            -
                        !result &&
         | 
| 94 | 
            -
                        cast_type.type == :time &&
         | 
| 95 | 
            -
                        time_zone_aware_types.include?(:not_explicitly_configured)
         | 
| 96 | 
            -
                        ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
         | 
| 97 | 
            -
                          Time columns will become time zone aware in Rails 5.1. This
         | 
| 98 | 
            -
                          still causes `String`s to be parsed as if they were in `Time.zone`,
         | 
| 99 | 
            -
                          and `Time`s to be converted to `Time.zone`.
         | 
| 100 81 |  | 
| 101 | 
            -
             | 
| 82 | 
            +
                      def create_time_zone_conversion_attribute?(name, cast_type)
         | 
| 83 | 
            +
                        enabled_for_column = time_zone_aware_attributes &&
         | 
| 84 | 
            +
                          !skip_time_zone_conversion_for_attributes.include?(name.to_sym)
         | 
| 102 85 |  | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
                          To silence this deprecation warning, add the following:
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                              config.active_record.time_zone_aware_types = [:datetime, :time]
         | 
| 108 | 
            -
                        MESSAGE
         | 
| 86 | 
            +
                        enabled_for_column && time_zone_aware_types.include?(cast_type.type)
         | 
| 109 87 | 
             
                      end
         | 
| 110 | 
            -
             | 
| 111 | 
            -
                      result
         | 
| 112 | 
            -
                    end
         | 
| 113 88 | 
             
                  end
         | 
| 114 89 | 
             
                end
         | 
| 115 90 | 
             
              end
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module ActiveRecord
         | 
| 2 4 | 
             
              module AttributeMethods
         | 
| 3 5 | 
             
                module Write
         | 
| @@ -7,53 +9,53 @@ module ActiveRecord | |
| 7 9 | 
             
                    attribute_method_suffix "="
         | 
| 8 10 | 
             
                  end
         | 
| 9 11 |  | 
| 10 | 
            -
                  module ClassMethods
         | 
| 11 | 
            -
                     | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 12 | 
            +
                  module ClassMethods # :nodoc:
         | 
| 13 | 
            +
                    private
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      def define_method_attribute=(name)
         | 
| 16 | 
            +
                        ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
         | 
| 17 | 
            +
                          generated_attribute_methods, name, writer: true,
         | 
| 18 | 
            +
                        ) do |temp_method_name, attr_name_expr|
         | 
| 19 | 
            +
                          generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
         | 
| 20 | 
            +
                            def #{temp_method_name}(value)
         | 
| 21 | 
            +
                              name = #{attr_name_expr}
         | 
| 22 | 
            +
                              _write_attribute(name, value)
         | 
| 23 | 
            +
                            end
         | 
| 24 | 
            +
                          RUBY
         | 
| 21 25 | 
             
                        end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                        undef_method :__temp__#{safe_name}=
         | 
| 24 | 
            -
                      STR
         | 
| 25 | 
            -
                    end
         | 
| 26 | 
            +
                      end
         | 
| 26 27 | 
             
                  end
         | 
| 27 28 |  | 
| 28 29 | 
             
                  # Updates the attribute identified by <tt>attr_name</tt> with the
         | 
| 29 30 | 
             
                  # specified +value+. Empty strings for Integer and Float columns are
         | 
| 30 31 | 
             
                  # turned into +nil+.
         | 
| 31 32 | 
             
                  def write_attribute(attr_name, value)
         | 
| 32 | 
            -
                     | 
| 33 | 
            -
             | 
| 33 | 
            +
                    name = attr_name.to_s
         | 
| 34 | 
            +
                    name = self.class.attribute_aliases[name] || name
         | 
| 34 35 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
                     | 
| 36 | 
            +
                    name = @primary_key if name == "id" && @primary_key
         | 
| 37 | 
            +
                    _write_attribute(name, value)
         | 
| 37 38 | 
             
                  end
         | 
| 38 39 |  | 
| 39 | 
            -
                   | 
| 40 | 
            -
                  #  | 
| 41 | 
            -
                  def  | 
| 42 | 
            -
                     | 
| 40 | 
            +
                  # This method exists to avoid the expensive primary_key check internally, without
         | 
| 41 | 
            +
                  # breaking compatibility with the write_attribute API
         | 
| 42 | 
            +
                  def _write_attribute(attr_name, value) # :nodoc:
         | 
| 43 | 
            +
                    sync_with_transaction_state if @transaction_state&.finalized?
         | 
| 44 | 
            +
                    @attributes.write_from_user(attr_name.to_s, value)
         | 
| 45 | 
            +
                    value
         | 
| 43 46 | 
             
                  end
         | 
| 44 47 |  | 
| 45 | 
            -
                   | 
| 46 | 
            -
                    attr_name  | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
                      @attributes.write_from_user(attr_name, value)
         | 
| 51 | 
            -
                    else
         | 
| 52 | 
            -
                      @attributes.write_cast_value(attr_name, value)
         | 
| 48 | 
            +
                  private
         | 
| 49 | 
            +
                    def write_attribute_without_type_cast(attr_name, value)
         | 
| 50 | 
            +
                      sync_with_transaction_state if @transaction_state&.finalized?
         | 
| 51 | 
            +
                      @attributes.write_cast_value(attr_name.to_s, value)
         | 
| 52 | 
            +
                      value
         | 
| 53 53 | 
             
                    end
         | 
| 54 54 |  | 
| 55 | 
            -
                     | 
| 56 | 
            -
             | 
| 55 | 
            +
                    # Dispatch target for <tt>*=</tt> attribute methods.
         | 
| 56 | 
            +
                    def attribute=(attribute_name, value)
         | 
| 57 | 
            +
                      _write_attribute(attribute_name, value)
         | 
| 58 | 
            +
                    end
         | 
| 57 59 | 
             
                end
         | 
| 58 60 | 
             
              end
         | 
| 59 61 | 
             
            end
         |