activerecord 5.2.3 → 6.1.0
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 +898 -532
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +5 -4
- 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 +95 -42
- data/lib/active_record/associations/association_scope.rb +21 -21
- data/lib/active_record/associations/belongs_to_association.rb +50 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -5
- data/lib/active_record/associations/builder/association.rb +23 -21
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +10 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +31 -29
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +27 -28
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -12
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +71 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +48 -35
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +133 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +45 -8
- data/lib/active_record/autosave_association.rb +76 -47
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +293 -132
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +21 -17
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +203 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +381 -146
- data/lib/active_record/connection_adapters/abstract/transaction.rb +155 -68
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +86 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- 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 +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +38 -54
- 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 +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- 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/money.rb +2 -2
- 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/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- 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 +222 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +127 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +19 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +175 -187
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_handling.rb +285 -33
- data/lib/active_record/core.rb +308 -100
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +71 -17
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- 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 +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +197 -481
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +26 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +26 -22
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +34 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +141 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +205 -156
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +115 -58
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +402 -78
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +113 -101
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +157 -93
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +65 -40
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- 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 +4 -7
- 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 -40
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +487 -199
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +108 -58
- data/lib/active_record/relation.rb +375 -104
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +6 -8
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +51 -8
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -43
- data/lib/active_record/tasks/database_tasks.rb +276 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- 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 +246 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +59 -117
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +10 -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 +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -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 +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +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 +45 -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/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -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 +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -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 +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -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
- metadata +117 -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,192 @@ 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)
         | 
| 67 | 
            +
                    insert_all([ attributes ], returning: returning, unique_by: unique_by)
         | 
| 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 | 
            +
                  # [:unique_by]
         | 
| 95 | 
            +
                  #   (PostgreSQL and SQLite only) By default rows are considered to be unique
         | 
| 96 | 
            +
                  #   by every unique index on the table. Any duplicate rows are skipped.
         | 
| 97 | 
            +
                  #
         | 
| 98 | 
            +
                  #   To skip rows according to just one unique index pass <tt>:unique_by</tt>.
         | 
| 99 | 
            +
                  #
         | 
| 100 | 
            +
                  #   Consider a Book model where no duplicate ISBNs make sense, but if any
         | 
| 101 | 
            +
                  #   row has an existing id, or is not unique by another unique index,
         | 
| 102 | 
            +
                  #   <tt>ActiveRecord::RecordNotUnique</tt> is raised.
         | 
| 103 | 
            +
                  #
         | 
| 104 | 
            +
                  #   Unique indexes can be identified by columns or name:
         | 
| 105 | 
            +
                  #
         | 
| 106 | 
            +
                  #     unique_by: :isbn
         | 
| 107 | 
            +
                  #     unique_by: %i[ author_id name ]
         | 
| 108 | 
            +
                  #     unique_by: :index_books_on_isbn
         | 
| 109 | 
            +
                  #
         | 
| 110 | 
            +
                  # Because it relies on the index information from the database
         | 
| 111 | 
            +
                  # <tt>:unique_by</tt> is recommended to be paired with
         | 
| 112 | 
            +
                  # Active Record's schema_cache.
         | 
| 113 | 
            +
                  #
         | 
| 114 | 
            +
                  # ==== Example
         | 
| 115 | 
            +
                  #
         | 
| 116 | 
            +
                  #   # Insert records and skip inserting any duplicates.
         | 
| 117 | 
            +
                  #   # Here "Eloquent Ruby" is skipped because its id is not unique.
         | 
| 118 | 
            +
                  #
         | 
| 119 | 
            +
                  #   Book.insert_all([
         | 
| 120 | 
            +
                  #     { id: 1, title: "Rework", author: "David" },
         | 
| 121 | 
            +
                  #     { id: 1, title: "Eloquent Ruby", author: "Russ" }
         | 
| 122 | 
            +
                  #   ])
         | 
| 123 | 
            +
                  def insert_all(attributes, returning: nil, unique_by: nil)
         | 
| 124 | 
            +
                    InsertAll.new(self, attributes, on_duplicate: :skip, returning: returning, unique_by: unique_by).execute
         | 
| 125 | 
            +
                  end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                  # Inserts a single record into the database in a single SQL INSERT
         | 
| 128 | 
            +
                  # statement. It does not instantiate any models nor does it trigger
         | 
| 129 | 
            +
                  # Active Record callbacks or validations. Though passed values
         | 
| 130 | 
            +
                  # go through Active Record's type casting and serialization.
         | 
| 131 | 
            +
                  #
         | 
| 132 | 
            +
                  # See <tt>ActiveRecord::Persistence#insert_all!</tt> for more.
         | 
| 133 | 
            +
                  def insert!(attributes, returning: nil)
         | 
| 134 | 
            +
                    insert_all!([ attributes ], returning: returning)
         | 
| 135 | 
            +
                  end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                  # Inserts multiple records into the database in a single SQL INSERT
         | 
| 138 | 
            +
                  # statement. It does not instantiate any models nor does it trigger
         | 
| 139 | 
            +
                  # Active Record callbacks or validations. Though passed values
         | 
| 140 | 
            +
                  # go through Active Record's type casting and serialization.
         | 
| 141 | 
            +
                  #
         | 
| 142 | 
            +
                  # The +attributes+ parameter is an Array of Hashes. Every Hash determines
         | 
| 143 | 
            +
                  # the attributes for a single row and must have the same keys.
         | 
| 144 | 
            +
                  #
         | 
| 145 | 
            +
                  # Raises <tt>ActiveRecord::RecordNotUnique</tt> if any rows violate a
         | 
| 146 | 
            +
                  # unique index on the table. In that case, no rows are inserted.
         | 
| 147 | 
            +
                  #
         | 
| 148 | 
            +
                  # To skip duplicate rows, see <tt>ActiveRecord::Persistence#insert_all</tt>.
         | 
| 149 | 
            +
                  # To replace them, see <tt>ActiveRecord::Persistence#upsert_all</tt>.
         | 
| 150 | 
            +
                  #
         | 
| 151 | 
            +
                  # Returns an <tt>ActiveRecord::Result</tt> with its contents based on
         | 
| 152 | 
            +
                  # <tt>:returning</tt> (see below).
         | 
| 153 | 
            +
                  #
         | 
| 154 | 
            +
                  # ==== Options
         | 
| 155 | 
            +
                  #
         | 
| 156 | 
            +
                  # [:returning]
         | 
| 157 | 
            +
                  #   (PostgreSQL only) An array of attributes to return for all successfully
         | 
| 158 | 
            +
                  #   inserted records, which by default is the primary key.
         | 
| 159 | 
            +
                  #   Pass <tt>returning: %w[ id name ]</tt> for both id and name
         | 
| 160 | 
            +
                  #   or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
         | 
| 161 | 
            +
                  #   clause entirely.
         | 
| 162 | 
            +
                  #
         | 
| 163 | 
            +
                  # ==== Examples
         | 
| 164 | 
            +
                  #
         | 
| 165 | 
            +
                  #   # Insert multiple records
         | 
| 166 | 
            +
                  #   Book.insert_all!([
         | 
| 167 | 
            +
                  #     { title: "Rework", author: "David" },
         | 
| 168 | 
            +
                  #     { title: "Eloquent Ruby", author: "Russ" }
         | 
| 169 | 
            +
                  #   ])
         | 
| 170 | 
            +
                  #
         | 
| 171 | 
            +
                  #   # Raises ActiveRecord::RecordNotUnique because "Eloquent Ruby"
         | 
| 172 | 
            +
                  #   # does not have a unique id.
         | 
| 173 | 
            +
                  #   Book.insert_all!([
         | 
| 174 | 
            +
                  #     { id: 1, title: "Rework", author: "David" },
         | 
| 175 | 
            +
                  #     { id: 1, title: "Eloquent Ruby", author: "Russ" }
         | 
| 176 | 
            +
                  #   ])
         | 
| 177 | 
            +
                  def insert_all!(attributes, returning: nil)
         | 
| 178 | 
            +
                    InsertAll.new(self, attributes, on_duplicate: :raise, returning: returning).execute
         | 
| 179 | 
            +
                  end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                  # Updates or inserts (upserts) a single record into the database in a
         | 
| 182 | 
            +
                  # single SQL INSERT statement. It does not instantiate any models nor does
         | 
| 183 | 
            +
                  # it trigger Active Record callbacks or validations. Though passed values
         | 
| 184 | 
            +
                  # go through Active Record's type casting and serialization.
         | 
| 185 | 
            +
                  #
         | 
| 186 | 
            +
                  # See <tt>ActiveRecord::Persistence#upsert_all</tt> for documentation.
         | 
| 187 | 
            +
                  def upsert(attributes, returning: nil, unique_by: nil)
         | 
| 188 | 
            +
                    upsert_all([ attributes ], returning: returning, unique_by: unique_by)
         | 
| 189 | 
            +
                  end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                  # Updates or inserts (upserts) multiple records into the database in a
         | 
| 192 | 
            +
                  # single SQL INSERT statement. It does not instantiate any models nor does
         | 
| 193 | 
            +
                  # it trigger Active Record callbacks or validations. Though passed values
         | 
| 194 | 
            +
                  # go through Active Record's type casting and serialization.
         | 
| 195 | 
            +
                  #
         | 
| 196 | 
            +
                  # The +attributes+ parameter is an Array of Hashes. Every Hash determines
         | 
| 197 | 
            +
                  # the attributes for a single row and must have the same keys.
         | 
| 198 | 
            +
                  #
         | 
| 199 | 
            +
                  # Returns an <tt>ActiveRecord::Result</tt> with its contents based on
         | 
| 200 | 
            +
                  # <tt>:returning</tt> (see below).
         | 
| 201 | 
            +
                  #
         | 
| 202 | 
            +
                  # ==== Options
         | 
| 203 | 
            +
                  #
         | 
| 204 | 
            +
                  # [:returning]
         | 
| 205 | 
            +
                  #   (PostgreSQL only) An array of attributes to return for all successfully
         | 
| 206 | 
            +
                  #   inserted records, which by default is the primary key.
         | 
| 207 | 
            +
                  #   Pass <tt>returning: %w[ id name ]</tt> for both id and name
         | 
| 208 | 
            +
                  #   or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
         | 
| 209 | 
            +
                  #   clause entirely.
         | 
| 210 | 
            +
                  #
         | 
| 211 | 
            +
                  # [:unique_by]
         | 
| 212 | 
            +
                  #   (PostgreSQL and SQLite only) By default rows are considered to be unique
         | 
| 213 | 
            +
                  #   by every unique index on the table. Any duplicate rows are skipped.
         | 
| 214 | 
            +
                  #
         | 
| 215 | 
            +
                  #   To skip rows according to just one unique index pass <tt>:unique_by</tt>.
         | 
| 216 | 
            +
                  #
         | 
| 217 | 
            +
                  #   Consider a Book model where no duplicate ISBNs make sense, but if any
         | 
| 218 | 
            +
                  #   row has an existing id, or is not unique by another unique index,
         | 
| 219 | 
            +
                  #   <tt>ActiveRecord::RecordNotUnique</tt> is raised.
         | 
| 220 | 
            +
                  #
         | 
| 221 | 
            +
                  #   Unique indexes can be identified by columns or name:
         | 
| 222 | 
            +
                  #
         | 
| 223 | 
            +
                  #     unique_by: :isbn
         | 
| 224 | 
            +
                  #     unique_by: %i[ author_id name ]
         | 
| 225 | 
            +
                  #     unique_by: :index_books_on_isbn
         | 
| 226 | 
            +
                  #
         | 
| 227 | 
            +
                  # Because it relies on the index information from the database
         | 
| 228 | 
            +
                  # <tt>:unique_by</tt> is recommended to be paired with
         | 
| 229 | 
            +
                  # Active Record's schema_cache.
         | 
| 230 | 
            +
                  #
         | 
| 231 | 
            +
                  # ==== Examples
         | 
| 232 | 
            +
                  #
         | 
| 233 | 
            +
                  #   # Inserts multiple records, performing an upsert when records have duplicate ISBNs.
         | 
| 234 | 
            +
                  #   # Here "Eloquent Ruby" overwrites "Rework" because its ISBN is duplicate.
         | 
| 235 | 
            +
                  #
         | 
| 236 | 
            +
                  #   Book.upsert_all([
         | 
| 237 | 
            +
                  #     { title: "Rework", author: "David", isbn: "1" },
         | 
| 238 | 
            +
                  #     { title: "Eloquent Ruby", author: "Russ", isbn: "1" }
         | 
| 239 | 
            +
                  #   ], unique_by: :isbn)
         | 
| 240 | 
            +
                  #
         | 
| 241 | 
            +
                  #   Book.find_by(isbn: "1").title # => "Eloquent Ruby"
         | 
| 242 | 
            +
                  def upsert_all(attributes, returning: nil, unique_by: nil)
         | 
| 243 | 
            +
                    InsertAll.new(self, attributes, on_duplicate: :update, returning: returning, unique_by: unique_by).execute
         | 
| 244 | 
            +
                  end
         | 
| 245 | 
            +
             | 
| 58 246 | 
             
                  # Given an attributes hash, +instantiate+ returns a new instance of
         | 
| 59 247 | 
             
                  # the appropriate class. Accepts only keys as strings.
         | 
| 60 248 | 
             
                  #
         | 
| @@ -67,8 +255,7 @@ module ActiveRecord | |
| 67 255 | 
             
                  # how this "single-table" inheritance mapping is implemented.
         | 
| 68 256 | 
             
                  def instantiate(attributes, column_types = {}, &block)
         | 
| 69 257 | 
             
                    klass = discriminate_class_for_record(attributes)
         | 
| 70 | 
            -
                     | 
| 71 | 
            -
                    klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block)
         | 
| 258 | 
            +
                    instantiate_instance_of(klass, attributes, column_types, &block)
         | 
| 72 259 | 
             
                  end
         | 
| 73 260 |  | 
| 74 261 | 
             
                  # Updates an object (or multiple objects) and saves it to the database, if validations pass.
         | 
| @@ -143,7 +330,7 @@ module ActiveRecord | |
| 143 330 | 
             
                    end
         | 
| 144 331 | 
             
                  end
         | 
| 145 332 |  | 
| 146 | 
            -
                  # Deletes the row with a primary key matching the +id+ argument, using  | 
| 333 | 
            +
                  # Deletes the row with a primary key matching the +id+ argument, using an
         | 
| 147 334 | 
             
                  # SQL +DELETE+ statement, and returns the number of rows deleted. Active
         | 
| 148 335 | 
             
                  # Record objects are not instantiated, so the object's callbacks are not
         | 
| 149 336 | 
             
                  # executed, including any <tt>:dependent</tt> association options.
         | 
| @@ -162,10 +349,11 @@ module ActiveRecord | |
| 162 349 | 
             
                  #   # Delete multiple rows
         | 
| 163 350 | 
             
                  #   Todo.delete([2,3,4])
         | 
| 164 351 | 
             
                  def delete(id_or_array)
         | 
| 165 | 
            -
                     | 
| 352 | 
            +
                    delete_by(primary_key => id_or_array)
         | 
| 166 353 | 
             
                  end
         | 
| 167 354 |  | 
| 168 355 | 
             
                  def _insert_record(values) # :nodoc:
         | 
| 356 | 
            +
                    primary_key = self.primary_key
         | 
| 169 357 | 
             
                    primary_key_value = nil
         | 
| 170 358 |  | 
| 171 359 | 
             
                    if primary_key && Hash === values
         | 
| @@ -178,7 +366,7 @@ module ActiveRecord | |
| 178 366 | 
             
                    end
         | 
| 179 367 |  | 
| 180 368 | 
             
                    if values.empty?
         | 
| 181 | 
            -
                      im = arel_table.compile_insert(connection.empty_insert_statement_value)
         | 
| 369 | 
            +
                      im = arel_table.compile_insert(connection.empty_insert_statement_value(primary_key))
         | 
| 182 370 | 
             
                      im.into arel_table
         | 
| 183 371 | 
             
                    else
         | 
| 184 372 | 
             
                      im = arel_table.compile_insert(_substitute_values(values))
         | 
| @@ -208,6 +396,13 @@ module ActiveRecord | |
| 208 396 | 
             
                  end
         | 
| 209 397 |  | 
| 210 398 | 
             
                  private
         | 
| 399 | 
            +
                    # Given a class, an attributes hash, +instantiate_instance_of+ returns a
         | 
| 400 | 
            +
                    # new instance of the class. Accepts only keys as strings.
         | 
| 401 | 
            +
                    def instantiate_instance_of(klass, attributes, column_types = {}, &block)
         | 
| 402 | 
            +
                      attributes = klass.attributes_builder.build_from_database(attributes, column_types)
         | 
| 403 | 
            +
                      klass.allocate.init_with_attributes(attributes, &block)
         | 
| 404 | 
            +
                    end
         | 
| 405 | 
            +
             | 
| 211 406 | 
             
                    # Called by +instantiate+ to decide which class to use for a new
         | 
| 212 407 | 
             
                    # record instance.
         | 
| 213 408 | 
             
                    #
         | 
| @@ -219,8 +414,8 @@ module ActiveRecord | |
| 219 414 |  | 
| 220 415 | 
             
                    def _substitute_values(values)
         | 
| 221 416 | 
             
                      values.map do |name, value|
         | 
| 222 | 
            -
                        attr =  | 
| 223 | 
            -
                        bind = predicate_builder.build_bind_attribute(name, value)
         | 
| 417 | 
            +
                        attr = arel_table[name]
         | 
| 418 | 
            +
                        bind = predicate_builder.build_bind_attribute(attr.name, value)
         | 
| 224 419 | 
             
                        [attr, bind]
         | 
| 225 420 | 
             
                      end
         | 
| 226 421 | 
             
                    end
         | 
| @@ -229,26 +424,30 @@ module ActiveRecord | |
| 229 424 | 
             
                # Returns true if this object hasn't been saved yet -- that is, a record
         | 
| 230 425 | 
             
                # for the object doesn't exist in the database yet; otherwise, returns false.
         | 
| 231 426 | 
             
                def new_record?
         | 
| 232 | 
            -
                  sync_with_transaction_state
         | 
| 233 427 | 
             
                  @new_record
         | 
| 234 428 | 
             
                end
         | 
| 235 429 |  | 
| 430 | 
            +
                # Returns true if this object was just created -- that is, prior to the last
         | 
| 431 | 
            +
                # save, the object didn't exist in the database and new_record? would have
         | 
| 432 | 
            +
                # returned true.
         | 
| 433 | 
            +
                def previously_new_record?
         | 
| 434 | 
            +
                  @previously_new_record
         | 
| 435 | 
            +
                end
         | 
| 436 | 
            +
             | 
| 236 437 | 
             
                # Returns true if this object has been destroyed, otherwise returns false.
         | 
| 237 438 | 
             
                def destroyed?
         | 
| 238 | 
            -
                  sync_with_transaction_state
         | 
| 239 439 | 
             
                  @destroyed
         | 
| 240 440 | 
             
                end
         | 
| 241 441 |  | 
| 242 442 | 
             
                # Returns true if the record is persisted, i.e. it's not a new record and it was
         | 
| 243 443 | 
             
                # not destroyed, otherwise returns false.
         | 
| 244 444 | 
             
                def persisted?
         | 
| 245 | 
            -
                  sync_with_transaction_state
         | 
| 246 445 | 
             
                  !(@new_record || @destroyed)
         | 
| 247 446 | 
             
                end
         | 
| 248 447 |  | 
| 249 448 | 
             
                ##
         | 
| 250 449 | 
             
                # :call-seq:
         | 
| 251 | 
            -
                #   save( | 
| 450 | 
            +
                #   save(**options)
         | 
| 252 451 | 
             
                #
         | 
| 253 452 | 
             
                # Saves the model.
         | 
| 254 453 | 
             
                #
         | 
| @@ -271,15 +470,15 @@ module ActiveRecord | |
| 271 470 | 
             
                #
         | 
| 272 471 | 
             
                # Attributes marked as readonly are silently ignored if the record is
         | 
| 273 472 | 
             
                # being updated.
         | 
| 274 | 
            -
                def save( | 
| 275 | 
            -
                  create_or_update( | 
| 473 | 
            +
                def save(**options, &block)
         | 
| 474 | 
            +
                  create_or_update(**options, &block)
         | 
| 276 475 | 
             
                rescue ActiveRecord::RecordInvalid
         | 
| 277 476 | 
             
                  false
         | 
| 278 477 | 
             
                end
         | 
| 279 478 |  | 
| 280 479 | 
             
                ##
         | 
| 281 480 | 
             
                # :call-seq:
         | 
| 282 | 
            -
                #   save!( | 
| 481 | 
            +
                #   save!(**options)
         | 
| 283 482 | 
             
                #
         | 
| 284 483 | 
             
                # Saves the model.
         | 
| 285 484 | 
             
                #
         | 
| @@ -304,8 +503,8 @@ module ActiveRecord | |
| 304 503 | 
             
                # being updated.
         | 
| 305 504 | 
             
                #
         | 
| 306 505 | 
             
                # Unless an error is raised, returns true.
         | 
| 307 | 
            -
                def save!( | 
| 308 | 
            -
                  create_or_update( | 
| 506 | 
            +
                def save!(**options, &block)
         | 
| 507 | 
            +
                  create_or_update(**options, &block) || raise(RecordNotSaved.new("Failed to save the record", self))
         | 
| 309 508 | 
             
                end
         | 
| 310 509 |  | 
| 311 510 | 
             
                # Deletes the record in the database and freezes this instance to
         | 
| @@ -319,7 +518,7 @@ module ActiveRecord | |
| 319 518 | 
             
                #
         | 
| 320 519 | 
             
                # To enforce the object's +before_destroy+ and +after_destroy+
         | 
| 321 520 | 
             
                # callbacks or any <tt>:dependent</tt> association
         | 
| 322 | 
            -
                # options, use  | 
| 521 | 
            +
                # options, use #destroy.
         | 
| 323 522 | 
             
                def delete
         | 
| 324 523 | 
             
                  _delete_row if persisted?
         | 
| 325 524 | 
             
                  @destroyed = true
         | 
| @@ -336,7 +535,6 @@ module ActiveRecord | |
| 336 535 | 
             
                def destroy
         | 
| 337 536 | 
             
                  _raise_readonly_record_error if readonly?
         | 
| 338 537 | 
             
                  destroy_associations
         | 
| 339 | 
            -
                  self.class.connection.add_transaction_record(self)
         | 
| 340 538 | 
             
                  @_trigger_destroy_callback = if persisted?
         | 
| 341 539 | 
             
                    destroy_row > 0
         | 
| 342 540 | 
             
                  else
         | 
| @@ -371,13 +569,15 @@ module ActiveRecord | |
| 371 569 | 
             
                # If you want to change the sti column as well, use #becomes! instead.
         | 
| 372 570 | 
             
                def becomes(klass)
         | 
| 373 571 | 
             
                  became = klass.allocate
         | 
| 374 | 
            -
             | 
| 375 | 
            -
                  became. | 
| 376 | 
            -
             | 
| 377 | 
            -
             | 
| 378 | 
            -
             | 
| 379 | 
            -
             | 
| 380 | 
            -
             | 
| 572 | 
            +
             | 
| 573 | 
            +
                  became.send(:initialize) do |becoming|
         | 
| 574 | 
            +
                    becoming.instance_variable_set(:@attributes, @attributes)
         | 
| 575 | 
            +
                    becoming.instance_variable_set(:@mutations_from_database, @mutations_from_database ||= nil)
         | 
| 576 | 
            +
                    becoming.instance_variable_set(:@new_record, new_record?)
         | 
| 577 | 
            +
                    becoming.instance_variable_set(:@destroyed, destroyed?)
         | 
| 578 | 
            +
                    becoming.errors.copy!(errors)
         | 
| 579 | 
            +
                  end
         | 
| 580 | 
            +
             | 
| 381 581 | 
             
                  became
         | 
| 382 582 | 
             
                end
         | 
| 383 583 |  | 
| @@ -429,8 +629,6 @@ module ActiveRecord | |
| 429 629 | 
             
                  end
         | 
| 430 630 | 
             
                end
         | 
| 431 631 |  | 
| 432 | 
            -
                alias update_attributes update
         | 
| 433 | 
            -
             | 
| 434 632 | 
             
                # Updates its receiver just like #update but calls #save! instead
         | 
| 435 633 | 
             
                # of +save+, so an exception is raised if the record is invalid and saving will fail.
         | 
| 436 634 | 
             
                def update!(attributes)
         | 
| @@ -442,8 +640,6 @@ module ActiveRecord | |
| 442 640 | 
             
                  end
         | 
| 443 641 | 
             
                end
         | 
| 444 642 |  | 
| 445 | 
            -
                alias update_attributes! update!
         | 
| 446 | 
            -
             | 
| 447 643 | 
             
                # Equivalent to <code>update_columns(name => value)</code>.
         | 
| 448 644 | 
             
                def update_column(name, value)
         | 
| 449 645 | 
             
                  update_columns(name => value)
         | 
| @@ -469,8 +665,10 @@ module ActiveRecord | |
| 469 665 | 
             
                  raise ActiveRecordError, "cannot update a new record" if new_record?
         | 
| 470 666 | 
             
                  raise ActiveRecordError, "cannot update a destroyed record" if destroyed?
         | 
| 471 667 |  | 
| 472 | 
            -
                  attributes. | 
| 473 | 
            -
                     | 
| 668 | 
            +
                  attributes = attributes.transform_keys do |key|
         | 
| 669 | 
            +
                    name = key.to_s
         | 
| 670 | 
            +
                    name = self.class.attribute_aliases[name] || name
         | 
| 671 | 
            +
                    verify_readonly_attribute(name) || name
         | 
| 474 672 | 
             
                  end
         | 
| 475 673 |  | 
| 476 674 | 
             
                  id_in_database = self.id_in_database
         | 
| @@ -480,7 +678,7 @@ module ActiveRecord | |
| 480 678 |  | 
| 481 679 | 
             
                  affected_rows = self.class._update_record(
         | 
| 482 680 | 
             
                    attributes,
         | 
| 483 | 
            -
                     | 
| 681 | 
            +
                    @primary_key => id_in_database
         | 
| 484 682 | 
             
                  )
         | 
| 485 683 |  | 
| 486 684 | 
             
                  affected_rows == 1
         | 
| @@ -503,9 +701,9 @@ module ActiveRecord | |
| 503 701 | 
             
                # Returns +self+.
         | 
| 504 702 | 
             
                def increment!(attribute, by = 1, touch: nil)
         | 
| 505 703 | 
             
                  increment(attribute, by)
         | 
| 506 | 
            -
                  change = public_send(attribute) - ( | 
| 704 | 
            +
                  change = public_send(attribute) - (public_send(:"#{attribute}_in_database") || 0)
         | 
| 507 705 | 
             
                  self.class.update_counters(id, attribute => change, touch: touch)
         | 
| 508 | 
            -
                   | 
| 706 | 
            +
                  public_send(:"clear_#{attribute}_change")
         | 
| 509 707 | 
             
                  self
         | 
| 510 708 | 
             
                end
         | 
| 511 709 |  | 
| @@ -609,8 +807,9 @@ module ActiveRecord | |
| 609 807 | 
             
                      self.class.unscoped { self.class.find(id) }
         | 
| 610 808 | 
             
                    end
         | 
| 611 809 |  | 
| 612 | 
            -
                  @attributes = fresh_object.instance_variable_get( | 
| 810 | 
            +
                  @attributes = fresh_object.instance_variable_get(:@attributes)
         | 
| 613 811 | 
             
                  @new_record = false
         | 
| 812 | 
            +
                  @previously_new_record = false
         | 
| 614 813 | 
             
                  self
         | 
| 615 814 | 
             
                end
         | 
| 616 815 |  | 
| @@ -649,15 +848,13 @@ module ActiveRecord | |
| 649 848 | 
             
                #   ball.touch(:updated_at)   # => raises ActiveRecordError
         | 
| 650 849 | 
             
                #
         | 
| 651 850 | 
             
                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
         | 
| 851 | 
            +
                  _raise_record_not_touched_error unless persisted?
         | 
| 658 852 |  | 
| 659 853 | 
             
                  attribute_names = timestamp_attributes_for_update_in_model
         | 
| 660 | 
            -
                  attribute_names |= names.map | 
| 854 | 
            +
                  attribute_names |= names.map! do |name|
         | 
| 855 | 
            +
                    name = name.to_s
         | 
| 856 | 
            +
                    self.class.attribute_aliases[name] || name
         | 
| 857 | 
            +
                  end unless names.empty?
         | 
| 661 858 |  | 
| 662 859 | 
             
                  unless attribute_names.empty?
         | 
| 663 860 | 
             
                    affected_rows = _touch_row(attribute_names, time)
         | 
| @@ -668,7 +865,6 @@ module ActiveRecord | |
| 668 865 | 
             
                end
         | 
| 669 866 |  | 
| 670 867 | 
             
              private
         | 
| 671 | 
            -
             | 
| 672 868 | 
             
                # A hook to be overridden by association modules.
         | 
| 673 869 | 
             
                def destroy_associations
         | 
| 674 870 | 
             
                end
         | 
| @@ -678,15 +874,14 @@ module ActiveRecord | |
| 678 874 | 
             
                end
         | 
| 679 875 |  | 
| 680 876 | 
             
                def _delete_row
         | 
| 681 | 
            -
                  self.class._delete_record( | 
| 877 | 
            +
                  self.class._delete_record(@primary_key => id_in_database)
         | 
| 682 878 | 
             
                end
         | 
| 683 879 |  | 
| 684 880 | 
             
                def _touch_row(attribute_names, time)
         | 
| 685 881 | 
             
                  time ||= current_time_from_proper_timezone
         | 
| 686 882 |  | 
| 687 883 | 
             
                  attribute_names.each do |attr_name|
         | 
| 688 | 
            -
                     | 
| 689 | 
            -
                    clear_attribute_change(attr_name)
         | 
| 884 | 
            +
                    _write_attribute(attr_name, time)
         | 
| 690 885 | 
             
                  end
         | 
| 691 886 |  | 
| 692 887 | 
             
                  _update_row(attribute_names, "touch")
         | 
| @@ -695,21 +890,20 @@ module ActiveRecord | |
| 695 890 | 
             
                def _update_row(attribute_names, attempted_action = "update")
         | 
| 696 891 | 
             
                  self.class._update_record(
         | 
| 697 892 | 
             
                    attributes_with_values(attribute_names),
         | 
| 698 | 
            -
                     | 
| 893 | 
            +
                    @primary_key => id_in_database
         | 
| 699 894 | 
             
                  )
         | 
| 700 895 | 
             
                end
         | 
| 701 896 |  | 
| 702 | 
            -
                def create_or_update( | 
| 897 | 
            +
                def create_or_update(**, &block)
         | 
| 703 898 | 
             
                  _raise_readonly_record_error if readonly?
         | 
| 704 899 | 
             
                  return false if destroyed?
         | 
| 705 | 
            -
                  result = new_record? ? _create_record(&block) : _update_record( | 
| 900 | 
            +
                  result = new_record? ? _create_record(&block) : _update_record(&block)
         | 
| 706 901 | 
             
                  result != false
         | 
| 707 902 | 
             
                end
         | 
| 708 903 |  | 
| 709 904 | 
             
                # Updates the associated record with values matching those of the instance attributes.
         | 
| 710 905 | 
             
                # Returns the number of affected rows.
         | 
| 711 906 | 
             
                def _update_record(attribute_names = self.attribute_names)
         | 
| 712 | 
            -
                  attribute_names &= self.class.column_names
         | 
| 713 907 | 
             
                  attribute_names = attributes_for_update(attribute_names)
         | 
| 714 908 |  | 
| 715 909 | 
             
                  if attribute_names.empty?
         | 
| @@ -720,6 +914,8 @@ module ActiveRecord | |
| 720 914 | 
             
                    @_trigger_update_callback = affected_rows == 1
         | 
| 721 915 | 
             
                  end
         | 
| 722 916 |  | 
| 917 | 
            +
                  @previously_new_record = false
         | 
| 918 | 
            +
             | 
| 723 919 | 
             
                  yield(self) if block_given?
         | 
| 724 920 |  | 
| 725 921 | 
             
                  affected_rows
         | 
| @@ -728,13 +924,16 @@ module ActiveRecord | |
| 728 924 | 
             
                # Creates a record with values matching those of the instance attributes
         | 
| 729 925 | 
             
                # and returns its id.
         | 
| 730 926 | 
             
                def _create_record(attribute_names = self.attribute_names)
         | 
| 731 | 
            -
                  attribute_names  | 
| 732 | 
            -
                  attributes_values = attributes_with_values_for_create(attribute_names)
         | 
| 927 | 
            +
                  attribute_names = attributes_for_create(attribute_names)
         | 
| 733 928 |  | 
| 734 | 
            -
                  new_id = self.class._insert_record( | 
| 735 | 
            -
             | 
| 929 | 
            +
                  new_id = self.class._insert_record(
         | 
| 930 | 
            +
                    attributes_with_values(attribute_names)
         | 
| 931 | 
            +
                  )
         | 
| 932 | 
            +
             | 
| 933 | 
            +
                  self.id ||= new_id if @primary_key
         | 
| 736 934 |  | 
| 737 935 | 
             
                  @new_record = false
         | 
| 936 | 
            +
                  @previously_new_record = true
         | 
| 738 937 |  | 
| 739 938 | 
             
                  yield(self) if block_given?
         | 
| 740 939 |  | 
| @@ -742,7 +941,7 @@ module ActiveRecord | |
| 742 941 | 
             
                end
         | 
| 743 942 |  | 
| 744 943 | 
             
                def verify_readonly_attribute(name)
         | 
| 745 | 
            -
                  raise ActiveRecordError, "#{name} is marked as readonly" if self.class. | 
| 944 | 
            +
                  raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attribute?(name)
         | 
| 746 945 | 
             
                end
         | 
| 747 946 |  | 
| 748 947 | 
             
                def _raise_record_not_destroyed
         | 
| @@ -752,12 +951,21 @@ module ActiveRecord | |
| 752 951 | 
             
                  @_association_destroy_exception = nil
         | 
| 753 952 | 
             
                end
         | 
| 754 953 |  | 
| 755 | 
            -
                def belongs_to_touch_method
         | 
| 756 | 
            -
                  :touch
         | 
| 757 | 
            -
                end
         | 
| 758 | 
            -
             | 
| 759 954 | 
             
                def _raise_readonly_record_error
         | 
| 760 955 | 
             
                  raise ReadOnlyRecord, "#{self.class} is marked as readonly"
         | 
| 761 956 | 
             
                end
         | 
| 957 | 
            +
             | 
| 958 | 
            +
                def _raise_record_not_touched_error
         | 
| 959 | 
            +
                  raise ActiveRecordError, <<~MSG.squish
         | 
| 960 | 
            +
                    Cannot touch on a new or destroyed record object. Consider using
         | 
| 961 | 
            +
                    persisted?, new_record?, or destroyed? before touching.
         | 
| 962 | 
            +
                  MSG
         | 
| 963 | 
            +
                end
         | 
| 964 | 
            +
             | 
| 965 | 
            +
                # The name of the method used to touch a +belongs_to+ association when the
         | 
| 966 | 
            +
                # +:touch+ option is used.
         | 
| 967 | 
            +
                def belongs_to_touch_method
         | 
| 968 | 
            +
                  :touch
         | 
| 969 | 
            +
                end
         | 
| 762 970 | 
             
              end
         | 
| 763 971 | 
             
            end
         | 
| @@ -26,15 +26,32 @@ module ActiveRecord | |
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| 28 28 | 
             
                def self.run
         | 
| 29 | 
            -
                   | 
| 30 | 
            -
             | 
| 29 | 
            +
                  pools = []
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  if ActiveRecord::Base.legacy_connection_handling
         | 
| 32 | 
            +
                    ActiveRecord::Base.connection_handlers.each do |key, handler|
         | 
| 33 | 
            +
                      pools.concat(handler.connection_pool_list.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! })
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  else
         | 
| 36 | 
            +
                    pools.concat(ActiveRecord::Base.connection_handler.all_connection_pools.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! })
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  pools
         | 
| 31 40 | 
             
                end
         | 
| 32 41 |  | 
| 33 42 | 
             
                def self.complete(pools)
         | 
| 34 43 | 
             
                  pools.each { |pool| pool.disable_query_cache! }
         | 
| 35 44 |  | 
| 36 | 
            -
                  ActiveRecord::Base. | 
| 37 | 
            -
                     | 
| 45 | 
            +
                  if ActiveRecord::Base.legacy_connection_handling
         | 
| 46 | 
            +
                    ActiveRecord::Base.connection_handlers.each do |_, handler|
         | 
| 47 | 
            +
                      handler.connection_pool_list.each do |pool|
         | 
| 48 | 
            +
                        pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
         | 
| 49 | 
            +
                      end
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
                  else
         | 
| 52 | 
            +
                    ActiveRecord::Base.connection_handler.all_connection_pools.each do |pool|
         | 
| 53 | 
            +
                      pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
         | 
| 54 | 
            +
                    end
         | 
| 38 55 | 
             
                  end
         | 
| 39 56 | 
             
                end
         | 
| 40 57 |  |