activerecord 5.2.8 → 7.0.2
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 +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
 
| 
         @@ -1,5 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            require "active_record/insert_all"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
       3 
5 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       4 
6 
     | 
    
         
             
              # = Active Record \Persistence
         
     | 
| 
       5 
7 
     | 
    
         
             
              module Persistence
         
     | 
| 
         @@ -55,6 +57,283 @@ module ActiveRecord 
     | 
|
| 
       55 
57 
     | 
    
         
             
                    end
         
     | 
| 
       56 
58 
     | 
    
         
             
                  end
         
     | 
| 
       57 
59 
     | 
    
         | 
| 
      
 60 
     | 
    
         
            +
                  # Inserts a single record into the database in a single SQL INSERT
         
     | 
| 
      
 61 
     | 
    
         
            +
                  # statement. It does not instantiate any models nor does it trigger
         
     | 
| 
      
 62 
     | 
    
         
            +
                  # Active Record callbacks or validations. Though passed values
         
     | 
| 
      
 63 
     | 
    
         
            +
                  # go through Active Record's type casting and serialization.
         
     | 
| 
      
 64 
     | 
    
         
            +
                  #
         
     | 
| 
      
 65 
     | 
    
         
            +
                  # See <tt>ActiveRecord::Persistence#insert_all</tt> for documentation.
         
     | 
| 
      
 66 
     | 
    
         
            +
                  def insert(attributes, returning: nil, unique_by: nil, record_timestamps: nil)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    insert_all([ attributes ], returning: returning, unique_by: unique_by, record_timestamps: record_timestamps)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  # Inserts multiple records into the database in a single SQL INSERT
         
     | 
| 
      
 71 
     | 
    
         
            +
                  # statement. It does not instantiate any models nor does it trigger
         
     | 
| 
      
 72 
     | 
    
         
            +
                  # Active Record callbacks or validations. Though passed values
         
     | 
| 
      
 73 
     | 
    
         
            +
                  # go through Active Record's type casting and serialization.
         
     | 
| 
      
 74 
     | 
    
         
            +
                  #
         
     | 
| 
      
 75 
     | 
    
         
            +
                  # The +attributes+ parameter is an Array of Hashes. Every Hash determines
         
     | 
| 
      
 76 
     | 
    
         
            +
                  # the attributes for a single row and must have the same keys.
         
     | 
| 
      
 77 
     | 
    
         
            +
                  #
         
     | 
| 
      
 78 
     | 
    
         
            +
                  # Rows are considered to be unique by every unique index on the table. Any
         
     | 
| 
      
 79 
     | 
    
         
            +
                  # duplicate rows are skipped.
         
     | 
| 
      
 80 
     | 
    
         
            +
                  # Override with <tt>:unique_by</tt> (see below).
         
     | 
| 
      
 81 
     | 
    
         
            +
                  #
         
     | 
| 
      
 82 
     | 
    
         
            +
                  # Returns an <tt>ActiveRecord::Result</tt> with its contents based on
         
     | 
| 
      
 83 
     | 
    
         
            +
                  # <tt>:returning</tt> (see below).
         
     | 
| 
      
 84 
     | 
    
         
            +
                  #
         
     | 
| 
      
 85 
     | 
    
         
            +
                  # ==== Options
         
     | 
| 
      
 86 
     | 
    
         
            +
                  #
         
     | 
| 
      
 87 
     | 
    
         
            +
                  # [:returning]
         
     | 
| 
      
 88 
     | 
    
         
            +
                  #   (PostgreSQL only) An array of attributes to return for all successfully
         
     | 
| 
      
 89 
     | 
    
         
            +
                  #   inserted records, which by default is the primary key.
         
     | 
| 
      
 90 
     | 
    
         
            +
                  #   Pass <tt>returning: %w[ id name ]</tt> for both id and name
         
     | 
| 
      
 91 
     | 
    
         
            +
                  #   or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
         
     | 
| 
      
 92 
     | 
    
         
            +
                  #   clause entirely.
         
     | 
| 
      
 93 
     | 
    
         
            +
                  #
         
     | 
| 
      
 94 
     | 
    
         
            +
                  #   You can also pass an SQL string if you need more control on the return values
         
     | 
| 
      
 95 
     | 
    
         
            +
                  #   (for example, <tt>returning: "id, name as new_name"</tt>).
         
     | 
| 
      
 96 
     | 
    
         
            +
                  #
         
     | 
| 
      
 97 
     | 
    
         
            +
                  # [:unique_by]
         
     | 
| 
      
 98 
     | 
    
         
            +
                  #   (PostgreSQL and SQLite only) By default rows are considered to be unique
         
     | 
| 
      
 99 
     | 
    
         
            +
                  #   by every unique index on the table. Any duplicate rows are skipped.
         
     | 
| 
      
 100 
     | 
    
         
            +
                  #
         
     | 
| 
      
 101 
     | 
    
         
            +
                  #   To skip rows according to just one unique index pass <tt>:unique_by</tt>.
         
     | 
| 
      
 102 
     | 
    
         
            +
                  #
         
     | 
| 
      
 103 
     | 
    
         
            +
                  #   Consider a Book model where no duplicate ISBNs make sense, but if any
         
     | 
| 
      
 104 
     | 
    
         
            +
                  #   row has an existing id, or is not unique by another unique index,
         
     | 
| 
      
 105 
     | 
    
         
            +
                  #   <tt>ActiveRecord::RecordNotUnique</tt> is raised.
         
     | 
| 
      
 106 
     | 
    
         
            +
                  #
         
     | 
| 
      
 107 
     | 
    
         
            +
                  #   Unique indexes can be identified by columns or name:
         
     | 
| 
      
 108 
     | 
    
         
            +
                  #
         
     | 
| 
      
 109 
     | 
    
         
            +
                  #     unique_by: :isbn
         
     | 
| 
      
 110 
     | 
    
         
            +
                  #     unique_by: %i[ author_id name ]
         
     | 
| 
      
 111 
     | 
    
         
            +
                  #     unique_by: :index_books_on_isbn
         
     | 
| 
      
 112 
     | 
    
         
            +
                  #
         
     | 
| 
      
 113 
     | 
    
         
            +
                  # [:record_timestamps]
         
     | 
| 
      
 114 
     | 
    
         
            +
                  #   By default, automatic setting of timestamp columns is controlled by
         
     | 
| 
      
 115 
     | 
    
         
            +
                  #   the model's <tt>record_timestamps</tt> config, matching typical
         
     | 
| 
      
 116 
     | 
    
         
            +
                  #   behavior.
         
     | 
| 
      
 117 
     | 
    
         
            +
                  #
         
     | 
| 
      
 118 
     | 
    
         
            +
                  #   To override this and force automatic setting of timestamp columns one
         
     | 
| 
      
 119 
     | 
    
         
            +
                  #   way or the other, pass <tt>:record_timestamps</tt>:
         
     | 
| 
      
 120 
     | 
    
         
            +
                  #
         
     | 
| 
      
 121 
     | 
    
         
            +
                  #     record_timestamps: true  # Always set timestamps automatically
         
     | 
| 
      
 122 
     | 
    
         
            +
                  #     record_timestamps: false # Never set timestamps automatically
         
     | 
| 
      
 123 
     | 
    
         
            +
                  #
         
     | 
| 
      
 124 
     | 
    
         
            +
                  # Because it relies on the index information from the database
         
     | 
| 
      
 125 
     | 
    
         
            +
                  # <tt>:unique_by</tt> is recommended to be paired with
         
     | 
| 
      
 126 
     | 
    
         
            +
                  # Active Record's schema_cache.
         
     | 
| 
      
 127 
     | 
    
         
            +
                  #
         
     | 
| 
      
 128 
     | 
    
         
            +
                  # ==== Example
         
     | 
| 
      
 129 
     | 
    
         
            +
                  #
         
     | 
| 
      
 130 
     | 
    
         
            +
                  #   # Insert records and skip inserting any duplicates.
         
     | 
| 
      
 131 
     | 
    
         
            +
                  #   # Here "Eloquent Ruby" is skipped because its id is not unique.
         
     | 
| 
      
 132 
     | 
    
         
            +
                  #
         
     | 
| 
      
 133 
     | 
    
         
            +
                  #   Book.insert_all([
         
     | 
| 
      
 134 
     | 
    
         
            +
                  #     { id: 1, title: "Rework", author: "David" },
         
     | 
| 
      
 135 
     | 
    
         
            +
                  #     { id: 1, title: "Eloquent Ruby", author: "Russ" }
         
     | 
| 
      
 136 
     | 
    
         
            +
                  #   ])
         
     | 
| 
      
 137 
     | 
    
         
            +
                  #
         
     | 
| 
      
 138 
     | 
    
         
            +
                  #   # insert_all works on chained scopes, and you can use create_with
         
     | 
| 
      
 139 
     | 
    
         
            +
                  #   # to set default attributes for all inserted records.
         
     | 
| 
      
 140 
     | 
    
         
            +
                  #
         
     | 
| 
      
 141 
     | 
    
         
            +
                  #   author.books.create_with(created_at: Time.now).insert_all([
         
     | 
| 
      
 142 
     | 
    
         
            +
                  #     { id: 1, title: "Rework" },
         
     | 
| 
      
 143 
     | 
    
         
            +
                  #     { id: 2, title: "Eloquent Ruby" }
         
     | 
| 
      
 144 
     | 
    
         
            +
                  #   ])
         
     | 
| 
      
 145 
     | 
    
         
            +
                  def insert_all(attributes, returning: nil, unique_by: nil, record_timestamps: nil)
         
     | 
| 
      
 146 
     | 
    
         
            +
                    InsertAll.new(self, attributes, on_duplicate: :skip, returning: returning, unique_by: unique_by, record_timestamps: record_timestamps).execute
         
     | 
| 
      
 147 
     | 
    
         
            +
                  end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                  # Inserts a single record into the database in a single SQL INSERT
         
     | 
| 
      
 150 
     | 
    
         
            +
                  # statement. It does not instantiate any models nor does it trigger
         
     | 
| 
      
 151 
     | 
    
         
            +
                  # Active Record callbacks or validations. Though passed values
         
     | 
| 
      
 152 
     | 
    
         
            +
                  # go through Active Record's type casting and serialization.
         
     | 
| 
      
 153 
     | 
    
         
            +
                  #
         
     | 
| 
      
 154 
     | 
    
         
            +
                  # See <tt>ActiveRecord::Persistence#insert_all!</tt> for more.
         
     | 
| 
      
 155 
     | 
    
         
            +
                  def insert!(attributes, returning: nil, record_timestamps: nil)
         
     | 
| 
      
 156 
     | 
    
         
            +
                    insert_all!([ attributes ], returning: returning, record_timestamps: record_timestamps)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                  # Inserts multiple records into the database in a single SQL INSERT
         
     | 
| 
      
 160 
     | 
    
         
            +
                  # statement. It does not instantiate any models nor does it trigger
         
     | 
| 
      
 161 
     | 
    
         
            +
                  # Active Record callbacks or validations. Though passed values
         
     | 
| 
      
 162 
     | 
    
         
            +
                  # go through Active Record's type casting and serialization.
         
     | 
| 
      
 163 
     | 
    
         
            +
                  #
         
     | 
| 
      
 164 
     | 
    
         
            +
                  # The +attributes+ parameter is an Array of Hashes. Every Hash determines
         
     | 
| 
      
 165 
     | 
    
         
            +
                  # the attributes for a single row and must have the same keys.
         
     | 
| 
      
 166 
     | 
    
         
            +
                  #
         
     | 
| 
      
 167 
     | 
    
         
            +
                  # Raises <tt>ActiveRecord::RecordNotUnique</tt> if any rows violate a
         
     | 
| 
      
 168 
     | 
    
         
            +
                  # unique index on the table. In that case, no rows are inserted.
         
     | 
| 
      
 169 
     | 
    
         
            +
                  #
         
     | 
| 
      
 170 
     | 
    
         
            +
                  # To skip duplicate rows, see <tt>ActiveRecord::Persistence#insert_all</tt>.
         
     | 
| 
      
 171 
     | 
    
         
            +
                  # To replace them, see <tt>ActiveRecord::Persistence#upsert_all</tt>.
         
     | 
| 
      
 172 
     | 
    
         
            +
                  #
         
     | 
| 
      
 173 
     | 
    
         
            +
                  # Returns an <tt>ActiveRecord::Result</tt> with its contents based on
         
     | 
| 
      
 174 
     | 
    
         
            +
                  # <tt>:returning</tt> (see below).
         
     | 
| 
      
 175 
     | 
    
         
            +
                  #
         
     | 
| 
      
 176 
     | 
    
         
            +
                  # ==== Options
         
     | 
| 
      
 177 
     | 
    
         
            +
                  #
         
     | 
| 
      
 178 
     | 
    
         
            +
                  # [:returning]
         
     | 
| 
      
 179 
     | 
    
         
            +
                  #   (PostgreSQL only) An array of attributes to return for all successfully
         
     | 
| 
      
 180 
     | 
    
         
            +
                  #   inserted records, which by default is the primary key.
         
     | 
| 
      
 181 
     | 
    
         
            +
                  #   Pass <tt>returning: %w[ id name ]</tt> for both id and name
         
     | 
| 
      
 182 
     | 
    
         
            +
                  #   or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
         
     | 
| 
      
 183 
     | 
    
         
            +
                  #   clause entirely.
         
     | 
| 
      
 184 
     | 
    
         
            +
                  #
         
     | 
| 
      
 185 
     | 
    
         
            +
                  #   You can also pass an SQL string if you need more control on the return values
         
     | 
| 
      
 186 
     | 
    
         
            +
                  #   (for example, <tt>returning: "id, name as new_name"</tt>).
         
     | 
| 
      
 187 
     | 
    
         
            +
                  #
         
     | 
| 
      
 188 
     | 
    
         
            +
                  # [:record_timestamps]
         
     | 
| 
      
 189 
     | 
    
         
            +
                  #   By default, automatic setting of timestamp columns is controlled by
         
     | 
| 
      
 190 
     | 
    
         
            +
                  #   the model's <tt>record_timestamps</tt> config, matching typical
         
     | 
| 
      
 191 
     | 
    
         
            +
                  #   behavior.
         
     | 
| 
      
 192 
     | 
    
         
            +
                  #
         
     | 
| 
      
 193 
     | 
    
         
            +
                  #   To override this and force automatic setting of timestamp columns one
         
     | 
| 
      
 194 
     | 
    
         
            +
                  #   way or the other, pass <tt>:record_timestamps</tt>:
         
     | 
| 
      
 195 
     | 
    
         
            +
                  #
         
     | 
| 
      
 196 
     | 
    
         
            +
                  #     record_timestamps: true  # Always set timestamps automatically
         
     | 
| 
      
 197 
     | 
    
         
            +
                  #     record_timestamps: false # Never set timestamps automatically
         
     | 
| 
      
 198 
     | 
    
         
            +
                  #
         
     | 
| 
      
 199 
     | 
    
         
            +
                  # ==== Examples
         
     | 
| 
      
 200 
     | 
    
         
            +
                  #
         
     | 
| 
      
 201 
     | 
    
         
            +
                  #   # Insert multiple records
         
     | 
| 
      
 202 
     | 
    
         
            +
                  #   Book.insert_all!([
         
     | 
| 
      
 203 
     | 
    
         
            +
                  #     { title: "Rework", author: "David" },
         
     | 
| 
      
 204 
     | 
    
         
            +
                  #     { title: "Eloquent Ruby", author: "Russ" }
         
     | 
| 
      
 205 
     | 
    
         
            +
                  #   ])
         
     | 
| 
      
 206 
     | 
    
         
            +
                  #
         
     | 
| 
      
 207 
     | 
    
         
            +
                  #   # Raises ActiveRecord::RecordNotUnique because "Eloquent Ruby"
         
     | 
| 
      
 208 
     | 
    
         
            +
                  #   # does not have a unique id.
         
     | 
| 
      
 209 
     | 
    
         
            +
                  #   Book.insert_all!([
         
     | 
| 
      
 210 
     | 
    
         
            +
                  #     { id: 1, title: "Rework", author: "David" },
         
     | 
| 
      
 211 
     | 
    
         
            +
                  #     { id: 1, title: "Eloquent Ruby", author: "Russ" }
         
     | 
| 
      
 212 
     | 
    
         
            +
                  #   ])
         
     | 
| 
      
 213 
     | 
    
         
            +
                  def insert_all!(attributes, returning: nil, record_timestamps: nil)
         
     | 
| 
      
 214 
     | 
    
         
            +
                    InsertAll.new(self, attributes, on_duplicate: :raise, returning: returning, record_timestamps: record_timestamps).execute
         
     | 
| 
      
 215 
     | 
    
         
            +
                  end
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                  # Updates or inserts (upserts) a single record into the database in a
         
     | 
| 
      
 218 
     | 
    
         
            +
                  # single SQL INSERT statement. It does not instantiate any models nor does
         
     | 
| 
      
 219 
     | 
    
         
            +
                  # it trigger Active Record callbacks or validations. Though passed values
         
     | 
| 
      
 220 
     | 
    
         
            +
                  # go through Active Record's type casting and serialization.
         
     | 
| 
      
 221 
     | 
    
         
            +
                  #
         
     | 
| 
      
 222 
     | 
    
         
            +
                  # See <tt>ActiveRecord::Persistence#upsert_all</tt> for documentation.
         
     | 
| 
      
 223 
     | 
    
         
            +
                  def upsert(attributes, on_duplicate: :update, returning: nil, unique_by: nil, record_timestamps: nil)
         
     | 
| 
      
 224 
     | 
    
         
            +
                    upsert_all([ attributes ], on_duplicate: on_duplicate, returning: returning, unique_by: unique_by, record_timestamps: record_timestamps)
         
     | 
| 
      
 225 
     | 
    
         
            +
                  end
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                  # Updates or inserts (upserts) multiple records into the database in a
         
     | 
| 
      
 228 
     | 
    
         
            +
                  # single SQL INSERT statement. It does not instantiate any models nor does
         
     | 
| 
      
 229 
     | 
    
         
            +
                  # it trigger Active Record callbacks or validations. Though passed values
         
     | 
| 
      
 230 
     | 
    
         
            +
                  # go through Active Record's type casting and serialization.
         
     | 
| 
      
 231 
     | 
    
         
            +
                  #
         
     | 
| 
      
 232 
     | 
    
         
            +
                  # The +attributes+ parameter is an Array of Hashes. Every Hash determines
         
     | 
| 
      
 233 
     | 
    
         
            +
                  # the attributes for a single row and must have the same keys.
         
     | 
| 
      
 234 
     | 
    
         
            +
                  #
         
     | 
| 
      
 235 
     | 
    
         
            +
                  # Returns an <tt>ActiveRecord::Result</tt> with its contents based on
         
     | 
| 
      
 236 
     | 
    
         
            +
                  # <tt>:returning</tt> (see below).
         
     | 
| 
      
 237 
     | 
    
         
            +
                  #
         
     | 
| 
      
 238 
     | 
    
         
            +
                  # By default, +upsert_all+ will update all the columns that can be updated when
         
     | 
| 
      
 239 
     | 
    
         
            +
                  # there is a conflict. These are all the columns except primary keys, read-only
         
     | 
| 
      
 240 
     | 
    
         
            +
                  # columns, and columns covered by the optional +unique_by+.
         
     | 
| 
      
 241 
     | 
    
         
            +
                  #
         
     | 
| 
      
 242 
     | 
    
         
            +
                  # ==== Options
         
     | 
| 
      
 243 
     | 
    
         
            +
                  #
         
     | 
| 
      
 244 
     | 
    
         
            +
                  # [:returning]
         
     | 
| 
      
 245 
     | 
    
         
            +
                  #   (PostgreSQL only) An array of attributes to return for all successfully
         
     | 
| 
      
 246 
     | 
    
         
            +
                  #   inserted records, which by default is the primary key.
         
     | 
| 
      
 247 
     | 
    
         
            +
                  #   Pass <tt>returning: %w[ id name ]</tt> for both id and name
         
     | 
| 
      
 248 
     | 
    
         
            +
                  #   or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
         
     | 
| 
      
 249 
     | 
    
         
            +
                  #   clause entirely.
         
     | 
| 
      
 250 
     | 
    
         
            +
                  #
         
     | 
| 
      
 251 
     | 
    
         
            +
                  #   You can also pass an SQL string if you need more control on the return values
         
     | 
| 
      
 252 
     | 
    
         
            +
                  #   (for example, <tt>returning: "id, name as new_name"</tt>).
         
     | 
| 
      
 253 
     | 
    
         
            +
                  #
         
     | 
| 
      
 254 
     | 
    
         
            +
                  # [:unique_by]
         
     | 
| 
      
 255 
     | 
    
         
            +
                  #   (PostgreSQL and SQLite only) By default rows are considered to be unique
         
     | 
| 
      
 256 
     | 
    
         
            +
                  #   by every unique index on the table. Any duplicate rows are skipped.
         
     | 
| 
      
 257 
     | 
    
         
            +
                  #
         
     | 
| 
      
 258 
     | 
    
         
            +
                  #   To skip rows according to just one unique index pass <tt>:unique_by</tt>.
         
     | 
| 
      
 259 
     | 
    
         
            +
                  #
         
     | 
| 
      
 260 
     | 
    
         
            +
                  #   Consider a Book model where no duplicate ISBNs make sense, but if any
         
     | 
| 
      
 261 
     | 
    
         
            +
                  #   row has an existing id, or is not unique by another unique index,
         
     | 
| 
      
 262 
     | 
    
         
            +
                  #   <tt>ActiveRecord::RecordNotUnique</tt> is raised.
         
     | 
| 
      
 263 
     | 
    
         
            +
                  #
         
     | 
| 
      
 264 
     | 
    
         
            +
                  #   Unique indexes can be identified by columns or name:
         
     | 
| 
      
 265 
     | 
    
         
            +
                  #
         
     | 
| 
      
 266 
     | 
    
         
            +
                  #     unique_by: :isbn
         
     | 
| 
      
 267 
     | 
    
         
            +
                  #     unique_by: %i[ author_id name ]
         
     | 
| 
      
 268 
     | 
    
         
            +
                  #     unique_by: :index_books_on_isbn
         
     | 
| 
      
 269 
     | 
    
         
            +
                  #
         
     | 
| 
      
 270 
     | 
    
         
            +
                  # Because it relies on the index information from the database
         
     | 
| 
      
 271 
     | 
    
         
            +
                  # <tt>:unique_by</tt> is recommended to be paired with
         
     | 
| 
      
 272 
     | 
    
         
            +
                  # Active Record's schema_cache.
         
     | 
| 
      
 273 
     | 
    
         
            +
                  #
         
     | 
| 
      
 274 
     | 
    
         
            +
                  # [:on_duplicate]
         
     | 
| 
      
 275 
     | 
    
         
            +
                  #   Configure the SQL update sentence that will be used in case of conflict.
         
     | 
| 
      
 276 
     | 
    
         
            +
                  #
         
     | 
| 
      
 277 
     | 
    
         
            +
                  #   NOTE: If you use this option you must provide all the columns you want to update
         
     | 
| 
      
 278 
     | 
    
         
            +
                  #   by yourself.
         
     | 
| 
      
 279 
     | 
    
         
            +
                  #
         
     | 
| 
      
 280 
     | 
    
         
            +
                  #   Example:
         
     | 
| 
      
 281 
     | 
    
         
            +
                  #
         
     | 
| 
      
 282 
     | 
    
         
            +
                  #     Commodity.upsert_all(
         
     | 
| 
      
 283 
     | 
    
         
            +
                  #       [
         
     | 
| 
      
 284 
     | 
    
         
            +
                  #         { id: 2, name: "Copper", price: 4.84 },
         
     | 
| 
      
 285 
     | 
    
         
            +
                  #         { id: 4, name: "Gold", price: 1380.87 },
         
     | 
| 
      
 286 
     | 
    
         
            +
                  #         { id: 6, name: "Aluminium", price: 0.35 }
         
     | 
| 
      
 287 
     | 
    
         
            +
                  #       ],
         
     | 
| 
      
 288 
     | 
    
         
            +
                  #       on_duplicate: Arel.sql("price = GREATEST(commodities.price, EXCLUDED.price)")
         
     | 
| 
      
 289 
     | 
    
         
            +
                  #     )
         
     | 
| 
      
 290 
     | 
    
         
            +
                  #
         
     | 
| 
      
 291 
     | 
    
         
            +
                  #   See the related +:update_only+ option. Both options can't be used at the same time.
         
     | 
| 
      
 292 
     | 
    
         
            +
                  #
         
     | 
| 
      
 293 
     | 
    
         
            +
                  # [:update_only]
         
     | 
| 
      
 294 
     | 
    
         
            +
                  #   Provide a list of column names that will be updated in case of conflict. If not provided,
         
     | 
| 
      
 295 
     | 
    
         
            +
                  #   +upsert_all+ will update all the columns that can be updated. These are all the columns
         
     | 
| 
      
 296 
     | 
    
         
            +
                  #   except primary keys, read-only columns, and columns covered by the optional +unique_by+
         
     | 
| 
      
 297 
     | 
    
         
            +
                  #
         
     | 
| 
      
 298 
     | 
    
         
            +
                  #   Example:
         
     | 
| 
      
 299 
     | 
    
         
            +
                  #
         
     | 
| 
      
 300 
     | 
    
         
            +
                  #     Commodity.upsert_all(
         
     | 
| 
      
 301 
     | 
    
         
            +
                  #       [
         
     | 
| 
      
 302 
     | 
    
         
            +
                  #         { id: 2, name: "Copper", price: 4.84 },
         
     | 
| 
      
 303 
     | 
    
         
            +
                  #         { id: 4, name: "Gold", price: 1380.87 },
         
     | 
| 
      
 304 
     | 
    
         
            +
                  #         { id: 6, name: "Aluminium", price: 0.35 }
         
     | 
| 
      
 305 
     | 
    
         
            +
                  #       ],
         
     | 
| 
      
 306 
     | 
    
         
            +
                  #       update_only: [:price] # Only prices will be updated
         
     | 
| 
      
 307 
     | 
    
         
            +
                  #     )
         
     | 
| 
      
 308 
     | 
    
         
            +
                  #
         
     | 
| 
      
 309 
     | 
    
         
            +
                  #   See the related +:on_duplicate+ option. Both options can't be used at the same time.
         
     | 
| 
      
 310 
     | 
    
         
            +
                  #
         
     | 
| 
      
 311 
     | 
    
         
            +
                  # [:record_timestamps]
         
     | 
| 
      
 312 
     | 
    
         
            +
                  #   By default, automatic setting of timestamp columns is controlled by
         
     | 
| 
      
 313 
     | 
    
         
            +
                  #   the model's <tt>record_timestamps</tt> config, matching typical
         
     | 
| 
      
 314 
     | 
    
         
            +
                  #   behavior.
         
     | 
| 
      
 315 
     | 
    
         
            +
                  #
         
     | 
| 
      
 316 
     | 
    
         
            +
                  #   To override this and force automatic setting of timestamp columns one
         
     | 
| 
      
 317 
     | 
    
         
            +
                  #   way or the other, pass <tt>:record_timestamps</tt>:
         
     | 
| 
      
 318 
     | 
    
         
            +
                  #
         
     | 
| 
      
 319 
     | 
    
         
            +
                  #     record_timestamps: true  # Always set timestamps automatically
         
     | 
| 
      
 320 
     | 
    
         
            +
                  #     record_timestamps: false # Never set timestamps automatically
         
     | 
| 
      
 321 
     | 
    
         
            +
                  #
         
     | 
| 
      
 322 
     | 
    
         
            +
                  # ==== Examples
         
     | 
| 
      
 323 
     | 
    
         
            +
                  #
         
     | 
| 
      
 324 
     | 
    
         
            +
                  #   # Inserts multiple records, performing an upsert when records have duplicate ISBNs.
         
     | 
| 
      
 325 
     | 
    
         
            +
                  #   # Here "Eloquent Ruby" overwrites "Rework" because its ISBN is duplicate.
         
     | 
| 
      
 326 
     | 
    
         
            +
                  #
         
     | 
| 
      
 327 
     | 
    
         
            +
                  #   Book.upsert_all([
         
     | 
| 
      
 328 
     | 
    
         
            +
                  #     { title: "Rework", author: "David", isbn: "1" },
         
     | 
| 
      
 329 
     | 
    
         
            +
                  #     { title: "Eloquent Ruby", author: "Russ", isbn: "1" }
         
     | 
| 
      
 330 
     | 
    
         
            +
                  #   ], unique_by: :isbn)
         
     | 
| 
      
 331 
     | 
    
         
            +
                  #
         
     | 
| 
      
 332 
     | 
    
         
            +
                  #   Book.find_by(isbn: "1").title # => "Eloquent Ruby"
         
     | 
| 
      
 333 
     | 
    
         
            +
                  def upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
         
     | 
| 
      
 334 
     | 
    
         
            +
                    InsertAll.new(self, attributes, on_duplicate: on_duplicate, update_only: update_only, returning: returning, unique_by: unique_by, record_timestamps: record_timestamps).execute
         
     | 
| 
      
 335 
     | 
    
         
            +
                  end
         
     | 
| 
      
 336 
     | 
    
         
            +
             
     | 
| 
       58 
337 
     | 
    
         
             
                  # Given an attributes hash, +instantiate+ returns a new instance of
         
     | 
| 
       59 
338 
     | 
    
         
             
                  # the appropriate class. Accepts only keys as strings.
         
     | 
| 
       60 
339 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -67,8 +346,7 @@ module ActiveRecord 
     | 
|
| 
       67 
346 
     | 
    
         
             
                  # how this "single-table" inheritance mapping is implemented.
         
     | 
| 
       68 
347 
     | 
    
         
             
                  def instantiate(attributes, column_types = {}, &block)
         
     | 
| 
       69 
348 
     | 
    
         
             
                    klass = discriminate_class_for_record(attributes)
         
     | 
| 
       70 
     | 
    
         
            -
                     
     | 
| 
       71 
     | 
    
         
            -
                    klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block)
         
     | 
| 
      
 349 
     | 
    
         
            +
                    instantiate_instance_of(klass, attributes, column_types, &block)
         
     | 
| 
       72 
350 
     | 
    
         
             
                  end
         
     | 
| 
       73 
351 
     | 
    
         | 
| 
       74 
352 
     | 
    
         
             
                  # Updates an object (or multiple objects) and saves it to the database, if validations pass.
         
     | 
| 
         @@ -77,6 +355,7 @@ module ActiveRecord 
     | 
|
| 
       77 
355 
     | 
    
         
             
                  # ==== Parameters
         
     | 
| 
       78 
356 
     | 
    
         
             
                  #
         
     | 
| 
       79 
357 
     | 
    
         
             
                  # * +id+ - This should be the id or an array of ids to be updated.
         
     | 
| 
      
 358 
     | 
    
         
            +
                  #   Optional argument, defaults to all records in the relation.
         
     | 
| 
       80 
359 
     | 
    
         
             
                  # * +attributes+ - This should be a hash of attributes or an array of hashes.
         
     | 
| 
       81 
360 
     | 
    
         
             
                  #
         
     | 
| 
       82 
361 
     | 
    
         
             
                  # ==== Examples
         
     | 
| 
         @@ -99,6 +378,11 @@ module ActiveRecord 
     | 
|
| 
       99 
378 
     | 
    
         
             
                  # for updating all records in a single query.
         
     | 
| 
       100 
379 
     | 
    
         
             
                  def update(id = :all, attributes)
         
     | 
| 
       101 
380 
     | 
    
         
             
                    if id.is_a?(Array)
         
     | 
| 
      
 381 
     | 
    
         
            +
                      if id.any?(ActiveRecord::Base)
         
     | 
| 
      
 382 
     | 
    
         
            +
                        raise ArgumentError,
         
     | 
| 
      
 383 
     | 
    
         
            +
                          "You are passing an array of ActiveRecord::Base instances to `update`. " \
         
     | 
| 
      
 384 
     | 
    
         
            +
                          "Please pass the ids of the objects by calling `pluck(:id)` or `map(&:id)`."
         
     | 
| 
      
 385 
     | 
    
         
            +
                      end
         
     | 
| 
       102 
386 
     | 
    
         
             
                      id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
         
     | 
| 
       103 
387 
     | 
    
         
             
                        object.update(attributes[idx])
         
     | 
| 
       104 
388 
     | 
    
         
             
                      }
         
     | 
| 
         @@ -116,6 +400,32 @@ module ActiveRecord 
     | 
|
| 
       116 
400 
     | 
    
         
             
                    end
         
     | 
| 
       117 
401 
     | 
    
         
             
                  end
         
     | 
| 
       118 
402 
     | 
    
         | 
| 
      
 403 
     | 
    
         
            +
                  # Updates the object (or multiple objects) just like #update but calls #update! instead
         
     | 
| 
      
 404 
     | 
    
         
            +
                  # of +update+, so an exception is raised if the record is invalid and saving will fail.
         
     | 
| 
      
 405 
     | 
    
         
            +
                  def update!(id = :all, attributes)
         
     | 
| 
      
 406 
     | 
    
         
            +
                    if id.is_a?(Array)
         
     | 
| 
      
 407 
     | 
    
         
            +
                      if id.any?(ActiveRecord::Base)
         
     | 
| 
      
 408 
     | 
    
         
            +
                        raise ArgumentError,
         
     | 
| 
      
 409 
     | 
    
         
            +
                          "You are passing an array of ActiveRecord::Base instances to `update!`. " \
         
     | 
| 
      
 410 
     | 
    
         
            +
                          "Please pass the ids of the objects by calling `pluck(:id)` or `map(&:id)`."
         
     | 
| 
      
 411 
     | 
    
         
            +
                      end
         
     | 
| 
      
 412 
     | 
    
         
            +
                      id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
         
     | 
| 
      
 413 
     | 
    
         
            +
                        object.update!(attributes[idx])
         
     | 
| 
      
 414 
     | 
    
         
            +
                      }
         
     | 
| 
      
 415 
     | 
    
         
            +
                    elsif id == :all
         
     | 
| 
      
 416 
     | 
    
         
            +
                      all.each { |record| record.update!(attributes) }
         
     | 
| 
      
 417 
     | 
    
         
            +
                    else
         
     | 
| 
      
 418 
     | 
    
         
            +
                      if ActiveRecord::Base === id
         
     | 
| 
      
 419 
     | 
    
         
            +
                        raise ArgumentError,
         
     | 
| 
      
 420 
     | 
    
         
            +
                          "You are passing an instance of ActiveRecord::Base to `update!`. " \
         
     | 
| 
      
 421 
     | 
    
         
            +
                          "Please pass the id of the object by calling `.id`."
         
     | 
| 
      
 422 
     | 
    
         
            +
                      end
         
     | 
| 
      
 423 
     | 
    
         
            +
                      object = find(id)
         
     | 
| 
      
 424 
     | 
    
         
            +
                      object.update!(attributes)
         
     | 
| 
      
 425 
     | 
    
         
            +
                      object
         
     | 
| 
      
 426 
     | 
    
         
            +
                    end
         
     | 
| 
      
 427 
     | 
    
         
            +
                  end
         
     | 
| 
      
 428 
     | 
    
         
            +
             
     | 
| 
       119 
429 
     | 
    
         
             
                  # Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
         
     | 
| 
       120 
430 
     | 
    
         
             
                  # therefore all callbacks and filters are fired off before the object is deleted. This method is
         
     | 
| 
       121 
431 
     | 
    
         
             
                  # less efficient than #delete but allows cleanup methods and other actions to be run.
         
     | 
| 
         @@ -143,7 +453,7 @@ module ActiveRecord 
     | 
|
| 
       143 
453 
     | 
    
         
             
                    end
         
     | 
| 
       144 
454 
     | 
    
         
             
                  end
         
     | 
| 
       145 
455 
     | 
    
         | 
| 
       146 
     | 
    
         
            -
                  # Deletes the row with a primary key matching the +id+ argument, using  
     | 
| 
      
 456 
     | 
    
         
            +
                  # Deletes the row with a primary key matching the +id+ argument, using an
         
     | 
| 
       147 
457 
     | 
    
         
             
                  # SQL +DELETE+ statement, and returns the number of rows deleted. Active
         
     | 
| 
       148 
458 
     | 
    
         
             
                  # Record objects are not instantiated, so the object's callbacks are not
         
     | 
| 
       149 
459 
     | 
    
         
             
                  # executed, including any <tt>:dependent</tt> association options.
         
     | 
| 
         @@ -162,52 +472,72 @@ module ActiveRecord 
     | 
|
| 
       162 
472 
     | 
    
         
             
                  #   # Delete multiple rows
         
     | 
| 
       163 
473 
     | 
    
         
             
                  #   Todo.delete([2,3,4])
         
     | 
| 
       164 
474 
     | 
    
         
             
                  def delete(id_or_array)
         
     | 
| 
       165 
     | 
    
         
            -
                     
     | 
| 
      
 475 
     | 
    
         
            +
                    delete_by(primary_key => id_or_array)
         
     | 
| 
       166 
476 
     | 
    
         
             
                  end
         
     | 
| 
       167 
477 
     | 
    
         | 
| 
       168 
478 
     | 
    
         
             
                  def _insert_record(values) # :nodoc:
         
     | 
| 
      
 479 
     | 
    
         
            +
                    primary_key = self.primary_key
         
     | 
| 
       169 
480 
     | 
    
         
             
                    primary_key_value = nil
         
     | 
| 
       170 
481 
     | 
    
         | 
| 
       171 
     | 
    
         
            -
                    if  
     | 
| 
       172 
     | 
    
         
            -
                       
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
     | 
    
         
            -
                      if !primary_key_value && prefetch_primary_key?
         
     | 
| 
      
 482 
     | 
    
         
            +
                    if prefetch_primary_key? && primary_key
         
     | 
| 
      
 483 
     | 
    
         
            +
                      values[primary_key] ||= begin
         
     | 
| 
       175 
484 
     | 
    
         
             
                        primary_key_value = next_sequence_value
         
     | 
| 
       176 
     | 
    
         
            -
                         
     | 
| 
      
 485 
     | 
    
         
            +
                        _default_attributes[primary_key].with_cast_value(primary_key_value)
         
     | 
| 
       177 
486 
     | 
    
         
             
                      end
         
     | 
| 
       178 
487 
     | 
    
         
             
                    end
         
     | 
| 
       179 
488 
     | 
    
         | 
| 
      
 489 
     | 
    
         
            +
                    im = Arel::InsertManager.new(arel_table)
         
     | 
| 
      
 490 
     | 
    
         
            +
             
     | 
| 
       180 
491 
     | 
    
         
             
                    if values.empty?
         
     | 
| 
       181 
     | 
    
         
            -
                      im 
     | 
| 
       182 
     | 
    
         
            -
                      im.into arel_table
         
     | 
| 
      
 492 
     | 
    
         
            +
                      im.insert(connection.empty_insert_statement_value(primary_key))
         
     | 
| 
       183 
493 
     | 
    
         
             
                    else
         
     | 
| 
       184 
     | 
    
         
            -
                      im  
     | 
| 
      
 494 
     | 
    
         
            +
                      im.insert(values.transform_keys { |name| arel_table[name] })
         
     | 
| 
       185 
495 
     | 
    
         
             
                    end
         
     | 
| 
       186 
496 
     | 
    
         | 
| 
       187 
497 
     | 
    
         
             
                    connection.insert(im, "#{self} Create", primary_key || false, primary_key_value)
         
     | 
| 
       188 
498 
     | 
    
         
             
                  end
         
     | 
| 
       189 
499 
     | 
    
         | 
| 
       190 
500 
     | 
    
         
             
                  def _update_record(values, constraints) # :nodoc:
         
     | 
| 
       191 
     | 
    
         
            -
                    constraints =  
     | 
| 
      
 501 
     | 
    
         
            +
                    constraints = constraints.map { |name, value| predicate_builder[name, value] }
         
     | 
| 
      
 502 
     | 
    
         
            +
             
     | 
| 
      
 503 
     | 
    
         
            +
                    default_constraint = build_default_constraint
         
     | 
| 
      
 504 
     | 
    
         
            +
                    constraints << default_constraint if default_constraint
         
     | 
| 
       192 
505 
     | 
    
         | 
| 
       193 
     | 
    
         
            -
                     
     | 
| 
       194 
     | 
    
         
            -
                      constraints. 
     | 
| 
       195 
     | 
    
         
            -
                     
     | 
| 
      
 506 
     | 
    
         
            +
                    if current_scope = self.global_current_scope
         
     | 
| 
      
 507 
     | 
    
         
            +
                      constraints << current_scope.where_clause.ast
         
     | 
| 
      
 508 
     | 
    
         
            +
                    end
         
     | 
| 
      
 509 
     | 
    
         
            +
             
     | 
| 
      
 510 
     | 
    
         
            +
                    um = Arel::UpdateManager.new(arel_table)
         
     | 
| 
      
 511 
     | 
    
         
            +
                    um.set(values.transform_keys { |name| arel_table[name] })
         
     | 
| 
      
 512 
     | 
    
         
            +
                    um.wheres = constraints
         
     | 
| 
       196 
513 
     | 
    
         | 
| 
       197 
514 
     | 
    
         
             
                    connection.update(um, "#{self} Update")
         
     | 
| 
       198 
515 
     | 
    
         
             
                  end
         
     | 
| 
       199 
516 
     | 
    
         | 
| 
       200 
517 
     | 
    
         
             
                  def _delete_record(constraints) # :nodoc:
         
     | 
| 
       201 
     | 
    
         
            -
                    constraints =  
     | 
| 
      
 518 
     | 
    
         
            +
                    constraints = constraints.map { |name, value| predicate_builder[name, value] }
         
     | 
| 
      
 519 
     | 
    
         
            +
             
     | 
| 
      
 520 
     | 
    
         
            +
                    default_constraint = build_default_constraint
         
     | 
| 
      
 521 
     | 
    
         
            +
                    constraints << default_constraint if default_constraint
         
     | 
| 
      
 522 
     | 
    
         
            +
             
     | 
| 
      
 523 
     | 
    
         
            +
                    if current_scope = self.global_current_scope
         
     | 
| 
      
 524 
     | 
    
         
            +
                      constraints << current_scope.where_clause.ast
         
     | 
| 
      
 525 
     | 
    
         
            +
                    end
         
     | 
| 
       202 
526 
     | 
    
         | 
| 
       203 
     | 
    
         
            -
                    dm = Arel::DeleteManager.new
         
     | 
| 
       204 
     | 
    
         
            -
                    dm.from(arel_table)
         
     | 
| 
      
 527 
     | 
    
         
            +
                    dm = Arel::DeleteManager.new(arel_table)
         
     | 
| 
       205 
528 
     | 
    
         
             
                    dm.wheres = constraints
         
     | 
| 
       206 
529 
     | 
    
         | 
| 
       207 
530 
     | 
    
         
             
                    connection.delete(dm, "#{self} Destroy")
         
     | 
| 
       208 
531 
     | 
    
         
             
                  end
         
     | 
| 
       209 
532 
     | 
    
         | 
| 
       210 
533 
     | 
    
         
             
                  private
         
     | 
| 
      
 534 
     | 
    
         
            +
                    # Given a class, an attributes hash, +instantiate_instance_of+ returns a
         
     | 
| 
      
 535 
     | 
    
         
            +
                    # new instance of the class. Accepts only keys as strings.
         
     | 
| 
      
 536 
     | 
    
         
            +
                    def instantiate_instance_of(klass, attributes, column_types = {}, &block)
         
     | 
| 
      
 537 
     | 
    
         
            +
                      attributes = klass.attributes_builder.build_from_database(attributes, column_types)
         
     | 
| 
      
 538 
     | 
    
         
            +
                      klass.allocate.init_with_attributes(attributes, &block)
         
     | 
| 
      
 539 
     | 
    
         
            +
                    end
         
     | 
| 
      
 540 
     | 
    
         
            +
             
     | 
| 
       211 
541 
     | 
    
         
             
                    # Called by +instantiate+ to decide which class to use for a new
         
     | 
| 
       212 
542 
     | 
    
         
             
                    # record instance.
         
     | 
| 
       213 
543 
     | 
    
         
             
                    #
         
     | 
| 
         @@ -217,38 +547,49 @@ module ActiveRecord 
     | 
|
| 
       217 
547 
     | 
    
         
             
                      self
         
     | 
| 
       218 
548 
     | 
    
         
             
                    end
         
     | 
| 
       219 
549 
     | 
    
         | 
| 
       220 
     | 
    
         
            -
                     
     | 
| 
       221 
     | 
    
         
            -
             
     | 
| 
       222 
     | 
    
         
            -
             
     | 
| 
       223 
     | 
    
         
            -
             
     | 
| 
       224 
     | 
    
         
            -
             
     | 
| 
       225 
     | 
    
         
            -
             
     | 
| 
      
 550 
     | 
    
         
            +
                    # Called by +_update_record+ and +_delete_record+
         
     | 
| 
      
 551 
     | 
    
         
            +
                    # to build `where` clause from default scopes.
         
     | 
| 
      
 552 
     | 
    
         
            +
                    # Skips empty scopes.
         
     | 
| 
      
 553 
     | 
    
         
            +
                    def build_default_constraint
         
     | 
| 
      
 554 
     | 
    
         
            +
                      return unless default_scopes?(all_queries: true)
         
     | 
| 
      
 555 
     | 
    
         
            +
             
     | 
| 
      
 556 
     | 
    
         
            +
                      default_where_clause = default_scoped(all_queries: true).where_clause
         
     | 
| 
      
 557 
     | 
    
         
            +
                      default_where_clause.ast unless default_where_clause.empty?
         
     | 
| 
       226 
558 
     | 
    
         
             
                    end
         
     | 
| 
       227 
559 
     | 
    
         
             
                end
         
     | 
| 
       228 
560 
     | 
    
         | 
| 
       229 
561 
     | 
    
         
             
                # Returns true if this object hasn't been saved yet -- that is, a record
         
     | 
| 
       230 
562 
     | 
    
         
             
                # for the object doesn't exist in the database yet; otherwise, returns false.
         
     | 
| 
       231 
563 
     | 
    
         
             
                def new_record?
         
     | 
| 
       232 
     | 
    
         
            -
                  sync_with_transaction_state
         
     | 
| 
       233 
564 
     | 
    
         
             
                  @new_record
         
     | 
| 
       234 
565 
     | 
    
         
             
                end
         
     | 
| 
       235 
566 
     | 
    
         | 
| 
      
 567 
     | 
    
         
            +
                # Returns true if this object was just created -- that is, prior to the last
         
     | 
| 
      
 568 
     | 
    
         
            +
                # save, the object didn't exist in the database and new_record? would have
         
     | 
| 
      
 569 
     | 
    
         
            +
                # returned true.
         
     | 
| 
      
 570 
     | 
    
         
            +
                def previously_new_record?
         
     | 
| 
      
 571 
     | 
    
         
            +
                  @previously_new_record
         
     | 
| 
      
 572 
     | 
    
         
            +
                end
         
     | 
| 
      
 573 
     | 
    
         
            +
             
     | 
| 
      
 574 
     | 
    
         
            +
                # Returns true if this object was previously persisted but now it has been deleted.
         
     | 
| 
      
 575 
     | 
    
         
            +
                def previously_persisted?
         
     | 
| 
      
 576 
     | 
    
         
            +
                  !new_record? && destroyed?
         
     | 
| 
      
 577 
     | 
    
         
            +
                end
         
     | 
| 
      
 578 
     | 
    
         
            +
             
     | 
| 
       236 
579 
     | 
    
         
             
                # Returns true if this object has been destroyed, otherwise returns false.
         
     | 
| 
       237 
580 
     | 
    
         
             
                def destroyed?
         
     | 
| 
       238 
     | 
    
         
            -
                  sync_with_transaction_state
         
     | 
| 
       239 
581 
     | 
    
         
             
                  @destroyed
         
     | 
| 
       240 
582 
     | 
    
         
             
                end
         
     | 
| 
       241 
583 
     | 
    
         | 
| 
       242 
584 
     | 
    
         
             
                # Returns true if the record is persisted, i.e. it's not a new record and it was
         
     | 
| 
       243 
585 
     | 
    
         
             
                # not destroyed, otherwise returns false.
         
     | 
| 
       244 
586 
     | 
    
         
             
                def persisted?
         
     | 
| 
       245 
     | 
    
         
            -
                  sync_with_transaction_state
         
     | 
| 
       246 
587 
     | 
    
         
             
                  !(@new_record || @destroyed)
         
     | 
| 
       247 
588 
     | 
    
         
             
                end
         
     | 
| 
       248 
589 
     | 
    
         | 
| 
       249 
590 
     | 
    
         
             
                ##
         
     | 
| 
       250 
591 
     | 
    
         
             
                # :call-seq:
         
     | 
| 
       251 
     | 
    
         
            -
                #   save( 
     | 
| 
      
 592 
     | 
    
         
            +
                #   save(**options)
         
     | 
| 
       252 
593 
     | 
    
         
             
                #
         
     | 
| 
       253 
594 
     | 
    
         
             
                # Saves the model.
         
     | 
| 
       254 
595 
     | 
    
         
             
                #
         
     | 
| 
         @@ -271,15 +612,15 @@ module ActiveRecord 
     | 
|
| 
       271 
612 
     | 
    
         
             
                #
         
     | 
| 
       272 
613 
     | 
    
         
             
                # Attributes marked as readonly are silently ignored if the record is
         
     | 
| 
       273 
614 
     | 
    
         
             
                # being updated.
         
     | 
| 
       274 
     | 
    
         
            -
                def save( 
     | 
| 
       275 
     | 
    
         
            -
                  create_or_update( 
     | 
| 
      
 615 
     | 
    
         
            +
                def save(**options, &block)
         
     | 
| 
      
 616 
     | 
    
         
            +
                  create_or_update(**options, &block)
         
     | 
| 
       276 
617 
     | 
    
         
             
                rescue ActiveRecord::RecordInvalid
         
     | 
| 
       277 
618 
     | 
    
         
             
                  false
         
     | 
| 
       278 
619 
     | 
    
         
             
                end
         
     | 
| 
       279 
620 
     | 
    
         | 
| 
       280 
621 
     | 
    
         
             
                ##
         
     | 
| 
       281 
622 
     | 
    
         
             
                # :call-seq:
         
     | 
| 
       282 
     | 
    
         
            -
                #   save!( 
     | 
| 
      
 623 
     | 
    
         
            +
                #   save!(**options)
         
     | 
| 
       283 
624 
     | 
    
         
             
                #
         
     | 
| 
       284 
625 
     | 
    
         
             
                # Saves the model.
         
     | 
| 
       285 
626 
     | 
    
         
             
                #
         
     | 
| 
         @@ -304,8 +645,8 @@ module ActiveRecord 
     | 
|
| 
       304 
645 
     | 
    
         
             
                # being updated.
         
     | 
| 
       305 
646 
     | 
    
         
             
                #
         
     | 
| 
       306 
647 
     | 
    
         
             
                # Unless an error is raised, returns true.
         
     | 
| 
       307 
     | 
    
         
            -
                def save!( 
     | 
| 
       308 
     | 
    
         
            -
                  create_or_update( 
     | 
| 
      
 648 
     | 
    
         
            +
                def save!(**options, &block)
         
     | 
| 
      
 649 
     | 
    
         
            +
                  create_or_update(**options, &block) || raise(RecordNotSaved.new("Failed to save the record", self))
         
     | 
| 
       309 
650 
     | 
    
         
             
                end
         
     | 
| 
       310 
651 
     | 
    
         | 
| 
       311 
652 
     | 
    
         
             
                # Deletes the record in the database and freezes this instance to
         
     | 
| 
         @@ -319,7 +660,7 @@ module ActiveRecord 
     | 
|
| 
       319 
660 
     | 
    
         
             
                #
         
     | 
| 
       320 
661 
     | 
    
         
             
                # To enforce the object's +before_destroy+ and +after_destroy+
         
     | 
| 
       321 
662 
     | 
    
         
             
                # callbacks or any <tt>:dependent</tt> association
         
     | 
| 
       322 
     | 
    
         
            -
                # options, use  
     | 
| 
      
 663 
     | 
    
         
            +
                # options, use #destroy.
         
     | 
| 
       323 
664 
     | 
    
         
             
                def delete
         
     | 
| 
       324 
665 
     | 
    
         
             
                  _delete_row if persisted?
         
     | 
| 
       325 
666 
     | 
    
         
             
                  @destroyed = true
         
     | 
| 
         @@ -336,7 +677,6 @@ module ActiveRecord 
     | 
|
| 
       336 
677 
     | 
    
         
             
                def destroy
         
     | 
| 
       337 
678 
     | 
    
         
             
                  _raise_readonly_record_error if readonly?
         
     | 
| 
       338 
679 
     | 
    
         
             
                  destroy_associations
         
     | 
| 
       339 
     | 
    
         
            -
                  self.class.connection.add_transaction_record(self)
         
     | 
| 
       340 
680 
     | 
    
         
             
                  @_trigger_destroy_callback = if persisted?
         
     | 
| 
       341 
681 
     | 
    
         
             
                    destroy_row > 0
         
     | 
| 
       342 
682 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -358,34 +698,36 @@ module ActiveRecord 
     | 
|
| 
       358 
698 
     | 
    
         
             
                end
         
     | 
| 
       359 
699 
     | 
    
         | 
| 
       360 
700 
     | 
    
         
             
                # Returns an instance of the specified +klass+ with the attributes of the
         
     | 
| 
       361 
     | 
    
         
            -
                # current record. This is mostly useful in relation to single 
     | 
| 
       362 
     | 
    
         
            -
                # inheritance structures where you want a subclass to appear as the
         
     | 
| 
      
 701 
     | 
    
         
            +
                # current record. This is mostly useful in relation to single table
         
     | 
| 
      
 702 
     | 
    
         
            +
                # inheritance (STI) structures where you want a subclass to appear as the
         
     | 
| 
       363 
703 
     | 
    
         
             
                # superclass. This can be used along with record identification in
         
     | 
| 
       364 
704 
     | 
    
         
             
                # Action Pack to allow, say, <tt>Client < Company</tt> to do something
         
     | 
| 
       365 
705 
     | 
    
         
             
                # like render <tt>partial: @client.becomes(Company)</tt> to render that
         
     | 
| 
       366 
706 
     | 
    
         
             
                # instance using the companies/company partial instead of clients/client.
         
     | 
| 
       367 
707 
     | 
    
         
             
                #
         
     | 
| 
       368 
708 
     | 
    
         
             
                # Note: The new instance will share a link to the same attributes as the original class.
         
     | 
| 
       369 
     | 
    
         
            -
                # Therefore the  
     | 
| 
      
 709 
     | 
    
         
            +
                # Therefore the STI column value will still be the same.
         
     | 
| 
       370 
710 
     | 
    
         
             
                # Any change to the attributes on either instance will affect both instances.
         
     | 
| 
       371 
     | 
    
         
            -
                # If you want to change the  
     | 
| 
      
 711 
     | 
    
         
            +
                # If you want to change the STI column as well, use #becomes! instead.
         
     | 
| 
       372 
712 
     | 
    
         
             
                def becomes(klass)
         
     | 
| 
       373 
713 
     | 
    
         
             
                  became = klass.allocate
         
     | 
| 
       374 
     | 
    
         
            -
             
     | 
| 
       375 
     | 
    
         
            -
                  became. 
     | 
| 
       376 
     | 
    
         
            -
             
     | 
| 
       377 
     | 
    
         
            -
             
     | 
| 
       378 
     | 
    
         
            -
             
     | 
| 
       379 
     | 
    
         
            -
             
     | 
| 
       380 
     | 
    
         
            -
             
     | 
| 
      
 714 
     | 
    
         
            +
             
     | 
| 
      
 715 
     | 
    
         
            +
                  became.send(:initialize) do |becoming|
         
     | 
| 
      
 716 
     | 
    
         
            +
                    becoming.instance_variable_set(:@attributes, @attributes)
         
     | 
| 
      
 717 
     | 
    
         
            +
                    becoming.instance_variable_set(:@mutations_from_database, @mutations_from_database ||= nil)
         
     | 
| 
      
 718 
     | 
    
         
            +
                    becoming.instance_variable_set(:@new_record, new_record?)
         
     | 
| 
      
 719 
     | 
    
         
            +
                    becoming.instance_variable_set(:@destroyed, destroyed?)
         
     | 
| 
      
 720 
     | 
    
         
            +
                    becoming.errors.copy!(errors)
         
     | 
| 
      
 721 
     | 
    
         
            +
                  end
         
     | 
| 
      
 722 
     | 
    
         
            +
             
     | 
| 
       381 
723 
     | 
    
         
             
                  became
         
     | 
| 
       382 
724 
     | 
    
         
             
                end
         
     | 
| 
       383 
725 
     | 
    
         | 
| 
       384 
     | 
    
         
            -
                # Wrapper around #becomes that also changes the instance's  
     | 
| 
      
 726 
     | 
    
         
            +
                # Wrapper around #becomes that also changes the instance's STI column value.
         
     | 
| 
       385 
727 
     | 
    
         
             
                # This is especially useful if you want to persist the changed class in your
         
     | 
| 
       386 
728 
     | 
    
         
             
                # database.
         
     | 
| 
       387 
729 
     | 
    
         
             
                #
         
     | 
| 
       388 
     | 
    
         
            -
                # Note: The old instance's  
     | 
| 
      
 730 
     | 
    
         
            +
                # Note: The old instance's STI column value will be changed too, as both objects
         
     | 
| 
       389 
731 
     | 
    
         
             
                # share the same set of attributes.
         
     | 
| 
       390 
732 
     | 
    
         
             
                def becomes!(klass)
         
     | 
| 
       391 
733 
     | 
    
         
             
                  became = becomes(klass)
         
     | 
| 
         @@ -429,8 +771,6 @@ module ActiveRecord 
     | 
|
| 
       429 
771 
     | 
    
         
             
                  end
         
     | 
| 
       430 
772 
     | 
    
         
             
                end
         
     | 
| 
       431 
773 
     | 
    
         | 
| 
       432 
     | 
    
         
            -
                alias update_attributes update
         
     | 
| 
       433 
     | 
    
         
            -
             
     | 
| 
       434 
774 
     | 
    
         
             
                # Updates its receiver just like #update but calls #save! instead
         
     | 
| 
       435 
775 
     | 
    
         
             
                # of +save+, so an exception is raised if the record is invalid and saving will fail.
         
     | 
| 
       436 
776 
     | 
    
         
             
                def update!(attributes)
         
     | 
| 
         @@ -442,8 +782,6 @@ module ActiveRecord 
     | 
|
| 
       442 
782 
     | 
    
         
             
                  end
         
     | 
| 
       443 
783 
     | 
    
         
             
                end
         
     | 
| 
       444 
784 
     | 
    
         | 
| 
       445 
     | 
    
         
            -
                alias update_attributes! update!
         
     | 
| 
       446 
     | 
    
         
            -
             
     | 
| 
       447 
785 
     | 
    
         
             
                # Equivalent to <code>update_columns(name => value)</code>.
         
     | 
| 
       448 
786 
     | 
    
         
             
                def update_column(name, value)
         
     | 
| 
       449 
787 
     | 
    
         
             
                  update_columns(name => value)
         
     | 
| 
         @@ -469,18 +807,21 @@ module ActiveRecord 
     | 
|
| 
       469 
807 
     | 
    
         
             
                  raise ActiveRecordError, "cannot update a new record" if new_record?
         
     | 
| 
       470 
808 
     | 
    
         
             
                  raise ActiveRecordError, "cannot update a destroyed record" if destroyed?
         
     | 
| 
       471 
809 
     | 
    
         | 
| 
       472 
     | 
    
         
            -
                  attributes. 
     | 
| 
       473 
     | 
    
         
            -
                     
     | 
| 
      
 810 
     | 
    
         
            +
                  attributes = attributes.transform_keys do |key|
         
     | 
| 
      
 811 
     | 
    
         
            +
                    name = key.to_s
         
     | 
| 
      
 812 
     | 
    
         
            +
                    name = self.class.attribute_aliases[name] || name
         
     | 
| 
      
 813 
     | 
    
         
            +
                    verify_readonly_attribute(name) || name
         
     | 
| 
       474 
814 
     | 
    
         
             
                  end
         
     | 
| 
       475 
815 
     | 
    
         | 
| 
       476 
     | 
    
         
            -
                   
     | 
| 
       477 
     | 
    
         
            -
                  attributes. 
     | 
| 
       478 
     | 
    
         
            -
                     
     | 
| 
      
 816 
     | 
    
         
            +
                  update_constraints = _primary_key_constraints_hash
         
     | 
| 
      
 817 
     | 
    
         
            +
                  attributes = attributes.each_with_object({}) do |(k, v), h|
         
     | 
| 
      
 818 
     | 
    
         
            +
                    h[k] = @attributes.write_cast_value(k, v)
         
     | 
| 
      
 819 
     | 
    
         
            +
                    clear_attribute_change(k)
         
     | 
| 
       479 
820 
     | 
    
         
             
                  end
         
     | 
| 
       480 
821 
     | 
    
         | 
| 
       481 
822 
     | 
    
         
             
                  affected_rows = self.class._update_record(
         
     | 
| 
       482 
823 
     | 
    
         
             
                    attributes,
         
     | 
| 
       483 
     | 
    
         
            -
                     
     | 
| 
      
 824 
     | 
    
         
            +
                    update_constraints
         
     | 
| 
       484 
825 
     | 
    
         
             
                  )
         
     | 
| 
       485 
826 
     | 
    
         | 
| 
       486 
827 
     | 
    
         
             
                  affected_rows == 1
         
     | 
| 
         @@ -503,9 +844,9 @@ module ActiveRecord 
     | 
|
| 
       503 
844 
     | 
    
         
             
                # Returns +self+.
         
     | 
| 
       504 
845 
     | 
    
         
             
                def increment!(attribute, by = 1, touch: nil)
         
     | 
| 
       505 
846 
     | 
    
         
             
                  increment(attribute, by)
         
     | 
| 
       506 
     | 
    
         
            -
                  change = public_send(attribute) - ( 
     | 
| 
      
 847 
     | 
    
         
            +
                  change = public_send(attribute) - (public_send(:"#{attribute}_in_database") || 0)
         
     | 
| 
       507 
848 
     | 
    
         
             
                  self.class.update_counters(id, attribute => change, touch: touch)
         
     | 
| 
       508 
     | 
    
         
            -
                   
     | 
| 
      
 849 
     | 
    
         
            +
                  public_send(:"clear_#{attribute}_change")
         
     | 
| 
       509 
850 
     | 
    
         
             
                  self
         
     | 
| 
       510 
851 
     | 
    
         
             
                end
         
     | 
| 
       511 
852 
     | 
    
         | 
| 
         @@ -602,15 +943,16 @@ module ActiveRecord 
     | 
|
| 
       602 
943 
     | 
    
         
             
                def reload(options = nil)
         
     | 
| 
       603 
944 
     | 
    
         
             
                  self.class.connection.clear_query_cache
         
     | 
| 
       604 
945 
     | 
    
         | 
| 
       605 
     | 
    
         
            -
                  fresh_object =
         
     | 
| 
       606 
     | 
    
         
            -
                     
     | 
| 
       607 
     | 
    
         
            -
             
     | 
| 
       608 
     | 
    
         
            -
                     
     | 
| 
       609 
     | 
    
         
            -
             
     | 
| 
       610 
     | 
    
         
            -
                    end
         
     | 
| 
      
 946 
     | 
    
         
            +
                  fresh_object = if apply_scoping?(options)
         
     | 
| 
      
 947 
     | 
    
         
            +
                    _find_record(options)
         
     | 
| 
      
 948 
     | 
    
         
            +
                  else
         
     | 
| 
      
 949 
     | 
    
         
            +
                    self.class.unscoped { _find_record(options) }
         
     | 
| 
      
 950 
     | 
    
         
            +
                  end
         
     | 
| 
       611 
951 
     | 
    
         | 
| 
       612 
     | 
    
         
            -
                  @ 
     | 
| 
      
 952 
     | 
    
         
            +
                  @association_cache = fresh_object.instance_variable_get(:@association_cache)
         
     | 
| 
      
 953 
     | 
    
         
            +
                  @attributes = fresh_object.instance_variable_get(:@attributes)
         
     | 
| 
       613 
954 
     | 
    
         
             
                  @new_record = false
         
     | 
| 
      
 955 
     | 
    
         
            +
                  @previously_new_record = false
         
     | 
| 
       614 
956 
     | 
    
         
             
                  self
         
     | 
| 
       615 
957 
     | 
    
         
             
                end
         
     | 
| 
       616 
958 
     | 
    
         | 
| 
         @@ -649,15 +991,13 @@ module ActiveRecord 
     | 
|
| 
       649 
991 
     | 
    
         
             
                #   ball.touch(:updated_at)   # => raises ActiveRecordError
         
     | 
| 
       650 
992 
     | 
    
         
             
                #
         
     | 
| 
       651 
993 
     | 
    
         
             
                def touch(*names, time: nil)
         
     | 
| 
       652 
     | 
    
         
            -
                  unless persisted?
         
     | 
| 
       653 
     | 
    
         
            -
                    raise ActiveRecordError, <<-MSG.squish
         
     | 
| 
       654 
     | 
    
         
            -
                      cannot touch on a new or destroyed record object. Consider using
         
     | 
| 
       655 
     | 
    
         
            -
                      persisted?, new_record?, or destroyed? before touching
         
     | 
| 
       656 
     | 
    
         
            -
                    MSG
         
     | 
| 
       657 
     | 
    
         
            -
                  end
         
     | 
| 
      
 994 
     | 
    
         
            +
                  _raise_record_not_touched_error unless persisted?
         
     | 
| 
       658 
995 
     | 
    
         | 
| 
       659 
996 
     | 
    
         
             
                  attribute_names = timestamp_attributes_for_update_in_model
         
     | 
| 
       660 
     | 
    
         
            -
                  attribute_names |= names.map 
     | 
| 
      
 997 
     | 
    
         
            +
                  attribute_names |= names.map! do |name|
         
     | 
| 
      
 998 
     | 
    
         
            +
                    name = name.to_s
         
     | 
| 
      
 999 
     | 
    
         
            +
                    self.class.attribute_aliases[name] || name
         
     | 
| 
      
 1000 
     | 
    
         
            +
                  end unless names.empty?
         
     | 
| 
       661 
1001 
     | 
    
         | 
| 
       662 
1002 
     | 
    
         
             
                  unless attribute_names.empty?
         
     | 
| 
       663 
1003 
     | 
    
         
             
                    affected_rows = _touch_row(attribute_names, time)
         
     | 
| 
         @@ -668,6 +1008,28 @@ module ActiveRecord 
     | 
|
| 
       668 
1008 
     | 
    
         
             
                end
         
     | 
| 
       669 
1009 
     | 
    
         | 
| 
       670 
1010 
     | 
    
         
             
              private
         
     | 
| 
      
 1011 
     | 
    
         
            +
                def strict_loaded_associations
         
     | 
| 
      
 1012 
     | 
    
         
            +
                  @association_cache.find_all do |_, assoc|
         
     | 
| 
      
 1013 
     | 
    
         
            +
                    assoc.owner.strict_loading? && !assoc.owner.strict_loading_n_plus_one_only?
         
     | 
| 
      
 1014 
     | 
    
         
            +
                  end.map(&:first)
         
     | 
| 
      
 1015 
     | 
    
         
            +
                end
         
     | 
| 
      
 1016 
     | 
    
         
            +
             
     | 
| 
      
 1017 
     | 
    
         
            +
                def _find_record(options)
         
     | 
| 
      
 1018 
     | 
    
         
            +
                  if options && options[:lock]
         
     | 
| 
      
 1019 
     | 
    
         
            +
                    self.class.preload(strict_loaded_associations).lock(options[:lock]).find(id)
         
     | 
| 
      
 1020 
     | 
    
         
            +
                  else
         
     | 
| 
      
 1021 
     | 
    
         
            +
                    self.class.preload(strict_loaded_associations).find(id)
         
     | 
| 
      
 1022 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1023 
     | 
    
         
            +
                end
         
     | 
| 
      
 1024 
     | 
    
         
            +
             
     | 
| 
      
 1025 
     | 
    
         
            +
                def apply_scoping?(options)
         
     | 
| 
      
 1026 
     | 
    
         
            +
                  !(options && options[:unscoped]) &&
         
     | 
| 
      
 1027 
     | 
    
         
            +
                    (self.class.default_scopes?(all_queries: true) || self.class.global_current_scope)
         
     | 
| 
      
 1028 
     | 
    
         
            +
                end
         
     | 
| 
      
 1029 
     | 
    
         
            +
             
     | 
| 
      
 1030 
     | 
    
         
            +
                def _primary_key_constraints_hash
         
     | 
| 
      
 1031 
     | 
    
         
            +
                  { @primary_key => id_in_database }
         
     | 
| 
      
 1032 
     | 
    
         
            +
                end
         
     | 
| 
       671 
1033 
     | 
    
         | 
| 
       672 
1034 
     | 
    
         
             
                # A hook to be overridden by association modules.
         
     | 
| 
       673 
1035 
     | 
    
         
             
                def destroy_associations
         
     | 
| 
         @@ -678,15 +1040,14 @@ module ActiveRecord 
     | 
|
| 
       678 
1040 
     | 
    
         
             
                end
         
     | 
| 
       679 
1041 
     | 
    
         | 
| 
       680 
1042 
     | 
    
         
             
                def _delete_row
         
     | 
| 
       681 
     | 
    
         
            -
                  self.class._delete_record( 
     | 
| 
      
 1043 
     | 
    
         
            +
                  self.class._delete_record(_primary_key_constraints_hash)
         
     | 
| 
       682 
1044 
     | 
    
         
             
                end
         
     | 
| 
       683 
1045 
     | 
    
         | 
| 
       684 
1046 
     | 
    
         
             
                def _touch_row(attribute_names, time)
         
     | 
| 
       685 
1047 
     | 
    
         
             
                  time ||= current_time_from_proper_timezone
         
     | 
| 
       686 
1048 
     | 
    
         | 
| 
       687 
1049 
     | 
    
         
             
                  attribute_names.each do |attr_name|
         
     | 
| 
       688 
     | 
    
         
            -
                     
     | 
| 
       689 
     | 
    
         
            -
                    clear_attribute_change(attr_name)
         
     | 
| 
      
 1050 
     | 
    
         
            +
                    _write_attribute(attr_name, time)
         
     | 
| 
       690 
1051 
     | 
    
         
             
                  end
         
     | 
| 
       691 
1052 
     | 
    
         | 
| 
       692 
1053 
     | 
    
         
             
                  _update_row(attribute_names, "touch")
         
     | 
| 
         @@ -695,21 +1056,20 @@ module ActiveRecord 
     | 
|
| 
       695 
1056 
     | 
    
         
             
                def _update_row(attribute_names, attempted_action = "update")
         
     | 
| 
       696 
1057 
     | 
    
         
             
                  self.class._update_record(
         
     | 
| 
       697 
1058 
     | 
    
         
             
                    attributes_with_values(attribute_names),
         
     | 
| 
       698 
     | 
    
         
            -
                     
     | 
| 
      
 1059 
     | 
    
         
            +
                    _primary_key_constraints_hash
         
     | 
| 
       699 
1060 
     | 
    
         
             
                  )
         
     | 
| 
       700 
1061 
     | 
    
         
             
                end
         
     | 
| 
       701 
1062 
     | 
    
         | 
| 
       702 
     | 
    
         
            -
                def create_or_update( 
     | 
| 
      
 1063 
     | 
    
         
            +
                def create_or_update(**, &block)
         
     | 
| 
       703 
1064 
     | 
    
         
             
                  _raise_readonly_record_error if readonly?
         
     | 
| 
       704 
1065 
     | 
    
         
             
                  return false if destroyed?
         
     | 
| 
       705 
     | 
    
         
            -
                  result = new_record? ? _create_record(&block) : _update_record( 
     | 
| 
      
 1066 
     | 
    
         
            +
                  result = new_record? ? _create_record(&block) : _update_record(&block)
         
     | 
| 
       706 
1067 
     | 
    
         
             
                  result != false
         
     | 
| 
       707 
1068 
     | 
    
         
             
                end
         
     | 
| 
       708 
1069 
     | 
    
         | 
| 
       709 
1070 
     | 
    
         
             
                # Updates the associated record with values matching those of the instance attributes.
         
     | 
| 
       710 
1071 
     | 
    
         
             
                # Returns the number of affected rows.
         
     | 
| 
       711 
1072 
     | 
    
         
             
                def _update_record(attribute_names = self.attribute_names)
         
     | 
| 
       712 
     | 
    
         
            -
                  attribute_names &= self.class.column_names
         
     | 
| 
       713 
1073 
     | 
    
         
             
                  attribute_names = attributes_for_update(attribute_names)
         
     | 
| 
       714 
1074 
     | 
    
         | 
| 
       715 
1075 
     | 
    
         
             
                  if attribute_names.empty?
         
     | 
| 
         @@ -720,6 +1080,8 @@ module ActiveRecord 
     | 
|
| 
       720 
1080 
     | 
    
         
             
                    @_trigger_update_callback = affected_rows == 1
         
     | 
| 
       721 
1081 
     | 
    
         
             
                  end
         
     | 
| 
       722 
1082 
     | 
    
         | 
| 
      
 1083 
     | 
    
         
            +
                  @previously_new_record = false
         
     | 
| 
      
 1084 
     | 
    
         
            +
             
     | 
| 
       723 
1085 
     | 
    
         
             
                  yield(self) if block_given?
         
     | 
| 
       724 
1086 
     | 
    
         | 
| 
       725 
1087 
     | 
    
         
             
                  affected_rows
         
     | 
| 
         @@ -728,13 +1090,16 @@ module ActiveRecord 
     | 
|
| 
       728 
1090 
     | 
    
         
             
                # Creates a record with values matching those of the instance attributes
         
     | 
| 
       729 
1091 
     | 
    
         
             
                # and returns its id.
         
     | 
| 
       730 
1092 
     | 
    
         
             
                def _create_record(attribute_names = self.attribute_names)
         
     | 
| 
       731 
     | 
    
         
            -
                  attribute_names  
     | 
| 
       732 
     | 
    
         
            -
             
     | 
| 
      
 1093 
     | 
    
         
            +
                  attribute_names = attributes_for_create(attribute_names)
         
     | 
| 
      
 1094 
     | 
    
         
            +
             
     | 
| 
      
 1095 
     | 
    
         
            +
                  new_id = self.class._insert_record(
         
     | 
| 
      
 1096 
     | 
    
         
            +
                    attributes_with_values(attribute_names)
         
     | 
| 
      
 1097 
     | 
    
         
            +
                  )
         
     | 
| 
       733 
1098 
     | 
    
         | 
| 
       734 
     | 
    
         
            -
                  new_id  
     | 
| 
       735 
     | 
    
         
            -
                  self.id ||= new_id if self.class.primary_key
         
     | 
| 
      
 1099 
     | 
    
         
            +
                  self.id ||= new_id if @primary_key
         
     | 
| 
       736 
1100 
     | 
    
         | 
| 
       737 
1101 
     | 
    
         
             
                  @new_record = false
         
     | 
| 
      
 1102 
     | 
    
         
            +
                  @previously_new_record = true
         
     | 
| 
       738 
1103 
     | 
    
         | 
| 
       739 
1104 
     | 
    
         
             
                  yield(self) if block_given?
         
     | 
| 
       740 
1105 
     | 
    
         | 
| 
         @@ -742,22 +1107,32 @@ module ActiveRecord 
     | 
|
| 
       742 
1107 
     | 
    
         
             
                end
         
     | 
| 
       743 
1108 
     | 
    
         | 
| 
       744 
1109 
     | 
    
         
             
                def verify_readonly_attribute(name)
         
     | 
| 
       745 
     | 
    
         
            -
                  raise ActiveRecordError, "#{name} is marked as readonly" if self.class. 
     | 
| 
      
 1110 
     | 
    
         
            +
                  raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attribute?(name)
         
     | 
| 
       746 
1111 
     | 
    
         
             
                end
         
     | 
| 
       747 
1112 
     | 
    
         | 
| 
       748 
1113 
     | 
    
         
             
                def _raise_record_not_destroyed
         
     | 
| 
       749 
1114 
     | 
    
         
             
                  @_association_destroy_exception ||= nil
         
     | 
| 
       750 
     | 
    
         
            -
                   
     | 
| 
      
 1115 
     | 
    
         
            +
                  key = self.class.primary_key
         
     | 
| 
      
 1116 
     | 
    
         
            +
                  raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy #{self.class} with #{key}=#{send(key)}", self)
         
     | 
| 
       751 
1117 
     | 
    
         
             
                ensure
         
     | 
| 
       752 
1118 
     | 
    
         
             
                  @_association_destroy_exception = nil
         
     | 
| 
       753 
1119 
     | 
    
         
             
                end
         
     | 
| 
       754 
1120 
     | 
    
         | 
| 
       755 
     | 
    
         
            -
                def belongs_to_touch_method
         
     | 
| 
       756 
     | 
    
         
            -
                  :touch
         
     | 
| 
       757 
     | 
    
         
            -
                end
         
     | 
| 
       758 
     | 
    
         
            -
             
     | 
| 
       759 
1121 
     | 
    
         
             
                def _raise_readonly_record_error
         
     | 
| 
       760 
1122 
     | 
    
         
             
                  raise ReadOnlyRecord, "#{self.class} is marked as readonly"
         
     | 
| 
       761 
1123 
     | 
    
         
             
                end
         
     | 
| 
      
 1124 
     | 
    
         
            +
             
     | 
| 
      
 1125 
     | 
    
         
            +
                def _raise_record_not_touched_error
         
     | 
| 
      
 1126 
     | 
    
         
            +
                  raise ActiveRecordError, <<~MSG.squish
         
     | 
| 
      
 1127 
     | 
    
         
            +
                    Cannot touch on a new or destroyed record object. Consider using
         
     | 
| 
      
 1128 
     | 
    
         
            +
                    persisted?, new_record?, or destroyed? before touching.
         
     | 
| 
      
 1129 
     | 
    
         
            +
                  MSG
         
     | 
| 
      
 1130 
     | 
    
         
            +
                end
         
     | 
| 
      
 1131 
     | 
    
         
            +
             
     | 
| 
      
 1132 
     | 
    
         
            +
                # The name of the method used to touch a +belongs_to+ association when the
         
     | 
| 
      
 1133 
     | 
    
         
            +
                # +:touch+ option is used.
         
     | 
| 
      
 1134 
     | 
    
         
            +
                def belongs_to_touch_method
         
     | 
| 
      
 1135 
     | 
    
         
            +
                  :touch
         
     | 
| 
      
 1136 
     | 
    
         
            +
                end
         
     | 
| 
       762 
1137 
     | 
    
         
             
              end
         
     | 
| 
       763 
1138 
     | 
    
         
             
            end
         
     |