activerecord 5.2.4.3 → 6.0.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 +614 -588
 - data/MIT-LICENSE +3 -1
 - data/README.rdoc +4 -2
 - data/examples/performance.rb +1 -1
 - data/lib/active_record.rb +9 -2
 - data/lib/active_record/aggregations.rb +4 -2
 - data/lib/active_record/associations.rb +19 -14
 - data/lib/active_record/associations/association.rb +52 -19
 - data/lib/active_record/associations/association_scope.rb +4 -6
 - data/lib/active_record/associations/belongs_to_association.rb +36 -42
 - data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
 - data/lib/active_record/associations/builder/association.rb +14 -18
 - data/lib/active_record/associations/builder/belongs_to.rb +19 -52
 - data/lib/active_record/associations/builder/collection_association.rb +3 -13
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
 - data/lib/active_record/associations/builder/has_many.rb +2 -0
 - data/lib/active_record/associations/builder/has_one.rb +35 -1
 - data/lib/active_record/associations/builder/singular_association.rb +2 -0
 - data/lib/active_record/associations/collection_association.rb +6 -21
 - data/lib/active_record/associations/collection_proxy.rb +12 -15
 - data/lib/active_record/associations/foreign_association.rb +7 -0
 - data/lib/active_record/associations/has_many_association.rb +2 -10
 - data/lib/active_record/associations/has_many_through_association.rb +14 -14
 - data/lib/active_record/associations/has_one_association.rb +28 -30
 - data/lib/active_record/associations/has_one_through_association.rb +5 -5
 - data/lib/active_record/associations/join_dependency.rb +24 -28
 - data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
 - data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
 - data/lib/active_record/associations/preloader.rb +40 -32
 - data/lib/active_record/associations/preloader/association.rb +38 -36
 - data/lib/active_record/associations/preloader/through_association.rb +48 -39
 - data/lib/active_record/associations/singular_association.rb +2 -16
 - data/lib/active_record/attribute_assignment.rb +7 -10
 - data/lib/active_record/attribute_methods.rb +28 -100
 - data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
 - data/lib/active_record/attribute_methods/dirty.rb +111 -40
 - data/lib/active_record/attribute_methods/primary_key.rb +15 -22
 - data/lib/active_record/attribute_methods/query.rb +2 -3
 - data/lib/active_record/attribute_methods/read.rb +15 -53
 - data/lib/active_record/attribute_methods/serialization.rb +1 -1
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
 - data/lib/active_record/attribute_methods/write.rb +17 -24
 - data/lib/active_record/attributes.rb +13 -0
 - data/lib/active_record/autosave_association.rb +5 -9
 - data/lib/active_record/base.rb +2 -3
 - data/lib/active_record/callbacks.rb +5 -19
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +94 -16
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +95 -123
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -8
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
 - data/lib/active_record/connection_adapters/abstract/schema_creation.rb +19 -12
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +76 -48
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +132 -53
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -56
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +180 -47
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +128 -194
 - data/lib/active_record/connection_adapters/column.rb +17 -13
 - data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
 - data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
 - data/lib/active_record/connection_adapters/mysql/database_statements.rb +73 -13
 - data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
 - data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
 - data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
 - data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
 - data/lib/active_record/connection_adapters/mysql/schema_statements.rb +129 -13
 - data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -9
 - data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +20 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/range.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 +6 -3
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
 - data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +12 -1
 - data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +55 -53
 - data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +160 -74
 - data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
 - data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
 - data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
 - data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -6
 - data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +42 -11
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +125 -141
 - data/lib/active_record/connection_handling.rb +149 -27
 - data/lib/active_record/core.rb +100 -60
 - data/lib/active_record/counter_cache.rb +4 -29
 - data/lib/active_record/database_configurations.rb +233 -0
 - data/lib/active_record/database_configurations/database_config.rb +37 -0
 - data/lib/active_record/database_configurations/hash_config.rb +50 -0
 - data/lib/active_record/database_configurations/url_config.rb +79 -0
 - data/lib/active_record/dynamic_matchers.rb +1 -1
 - data/lib/active_record/enum.rb +37 -7
 - data/lib/active_record/errors.rb +15 -7
 - data/lib/active_record/explain.rb +1 -1
 - data/lib/active_record/fixture_set/model_metadata.rb +33 -0
 - data/lib/active_record/fixture_set/render_context.rb +17 -0
 - data/lib/active_record/fixture_set/table_row.rb +153 -0
 - data/lib/active_record/fixture_set/table_rows.rb +47 -0
 - data/lib/active_record/fixtures.rb +145 -472
 - data/lib/active_record/gem_version.rb +4 -4
 - data/lib/active_record/inheritance.rb +13 -3
 - data/lib/active_record/insert_all.rb +179 -0
 - data/lib/active_record/integration.rb +68 -16
 - data/lib/active_record/internal_metadata.rb +10 -2
 - data/lib/active_record/locking/optimistic.rb +5 -6
 - data/lib/active_record/locking/pessimistic.rb +3 -3
 - data/lib/active_record/log_subscriber.rb +7 -26
 - data/lib/active_record/middleware/database_selector.rb +75 -0
 - data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
 - data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
 - data/lib/active_record/migration.rb +100 -81
 - data/lib/active_record/migration/command_recorder.rb +50 -6
 - data/lib/active_record/migration/compatibility.rb +76 -49
 - data/lib/active_record/model_schema.rb +30 -9
 - data/lib/active_record/nested_attributes.rb +2 -2
 - data/lib/active_record/no_touching.rb +7 -0
 - data/lib/active_record/persistence.rb +228 -24
 - data/lib/active_record/query_cache.rb +11 -4
 - data/lib/active_record/querying.rb +32 -20
 - data/lib/active_record/railtie.rb +80 -43
 - data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
 - data/lib/active_record/railties/controller_runtime.rb +30 -35
 - data/lib/active_record/railties/databases.rake +196 -46
 - data/lib/active_record/reflection.rb +32 -30
 - data/lib/active_record/relation.rb +310 -80
 - data/lib/active_record/relation/batches.rb +13 -10
 - data/lib/active_record/relation/calculations.rb +53 -47
 - data/lib/active_record/relation/delegation.rb +26 -43
 - data/lib/active_record/relation/finder_methods.rb +13 -26
 - data/lib/active_record/relation/merger.rb +11 -20
 - data/lib/active_record/relation/predicate_builder.rb +4 -6
 - data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
 - data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
 - data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
 - data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
 - data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
 - data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
 - data/lib/active_record/relation/query_attribute.rb +13 -8
 - data/lib/active_record/relation/query_methods.rb +189 -63
 - data/lib/active_record/relation/spawn_methods.rb +1 -1
 - data/lib/active_record/relation/where_clause.rb +14 -10
 - data/lib/active_record/relation/where_clause_factory.rb +1 -2
 - data/lib/active_record/result.rb +30 -11
 - data/lib/active_record/sanitization.rb +32 -40
 - data/lib/active_record/schema.rb +2 -11
 - data/lib/active_record/schema_dumper.rb +22 -7
 - data/lib/active_record/schema_migration.rb +5 -1
 - data/lib/active_record/scoping.rb +8 -8
 - data/lib/active_record/scoping/default.rb +4 -5
 - data/lib/active_record/scoping/named.rb +19 -15
 - data/lib/active_record/statement_cache.rb +30 -3
 - data/lib/active_record/store.rb +87 -8
 - data/lib/active_record/table_metadata.rb +10 -17
 - data/lib/active_record/tasks/database_tasks.rb +194 -25
 - data/lib/active_record/tasks/mysql_database_tasks.rb +5 -5
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
 - data/lib/active_record/test_databases.rb +23 -0
 - data/lib/active_record/test_fixtures.rb +224 -0
 - data/lib/active_record/timestamp.rb +39 -25
 - data/lib/active_record/touch_later.rb +4 -2
 - data/lib/active_record/transactions.rb +57 -66
 - data/lib/active_record/translation.rb +1 -1
 - data/lib/active_record/type.rb +3 -4
 - data/lib/active_record/type/adapter_specific_registry.rb +1 -8
 - data/lib/active_record/type_caster/connection.rb +15 -14
 - data/lib/active_record/type_caster/map.rb +1 -4
 - data/lib/active_record/validations.rb +1 -0
 - data/lib/active_record/validations/uniqueness.rb +15 -27
 - data/lib/arel.rb +51 -0
 - data/lib/arel/alias_predication.rb +9 -0
 - data/lib/arel/attributes.rb +22 -0
 - data/lib/arel/attributes/attribute.rb +37 -0
 - data/lib/arel/collectors/bind.rb +24 -0
 - data/lib/arel/collectors/composite.rb +31 -0
 - data/lib/arel/collectors/plain_string.rb +20 -0
 - data/lib/arel/collectors/sql_string.rb +20 -0
 - data/lib/arel/collectors/substitute_binds.rb +28 -0
 - data/lib/arel/crud.rb +42 -0
 - data/lib/arel/delete_manager.rb +18 -0
 - data/lib/arel/errors.rb +9 -0
 - data/lib/arel/expressions.rb +29 -0
 - data/lib/arel/factory_methods.rb +49 -0
 - data/lib/arel/insert_manager.rb +49 -0
 - data/lib/arel/math.rb +45 -0
 - data/lib/arel/nodes.rb +68 -0
 - data/lib/arel/nodes/and.rb +32 -0
 - data/lib/arel/nodes/ascending.rb +23 -0
 - data/lib/arel/nodes/binary.rb +52 -0
 - data/lib/arel/nodes/bind_param.rb +36 -0
 - data/lib/arel/nodes/case.rb +55 -0
 - data/lib/arel/nodes/casted.rb +50 -0
 - data/lib/arel/nodes/comment.rb +29 -0
 - data/lib/arel/nodes/count.rb +12 -0
 - data/lib/arel/nodes/delete_statement.rb +45 -0
 - data/lib/arel/nodes/descending.rb +23 -0
 - data/lib/arel/nodes/equality.rb +18 -0
 - data/lib/arel/nodes/extract.rb +24 -0
 - data/lib/arel/nodes/false.rb +16 -0
 - data/lib/arel/nodes/full_outer_join.rb +8 -0
 - data/lib/arel/nodes/function.rb +44 -0
 - data/lib/arel/nodes/grouping.rb +8 -0
 - data/lib/arel/nodes/in.rb +8 -0
 - data/lib/arel/nodes/infix_operation.rb +80 -0
 - data/lib/arel/nodes/inner_join.rb +8 -0
 - data/lib/arel/nodes/insert_statement.rb +37 -0
 - data/lib/arel/nodes/join_source.rb +20 -0
 - data/lib/arel/nodes/matches.rb +18 -0
 - data/lib/arel/nodes/named_function.rb +23 -0
 - data/lib/arel/nodes/node.rb +50 -0
 - data/lib/arel/nodes/node_expression.rb +13 -0
 - data/lib/arel/nodes/outer_join.rb +8 -0
 - data/lib/arel/nodes/over.rb +15 -0
 - data/lib/arel/nodes/regexp.rb +16 -0
 - data/lib/arel/nodes/right_outer_join.rb +8 -0
 - data/lib/arel/nodes/select_core.rb +67 -0
 - data/lib/arel/nodes/select_statement.rb +41 -0
 - data/lib/arel/nodes/sql_literal.rb +16 -0
 - data/lib/arel/nodes/string_join.rb +11 -0
 - data/lib/arel/nodes/table_alias.rb +27 -0
 - data/lib/arel/nodes/terminal.rb +16 -0
 - data/lib/arel/nodes/true.rb +16 -0
 - data/lib/arel/nodes/unary.rb +45 -0
 - data/lib/arel/nodes/unary_operation.rb +20 -0
 - data/lib/arel/nodes/unqualified_column.rb +22 -0
 - data/lib/arel/nodes/update_statement.rb +41 -0
 - data/lib/arel/nodes/values_list.rb +9 -0
 - data/lib/arel/nodes/window.rb +126 -0
 - data/lib/arel/nodes/with.rb +11 -0
 - data/lib/arel/order_predications.rb +13 -0
 - data/lib/arel/predications.rb +257 -0
 - data/lib/arel/select_manager.rb +271 -0
 - data/lib/arel/table.rb +110 -0
 - data/lib/arel/tree_manager.rb +72 -0
 - data/lib/arel/update_manager.rb +34 -0
 - data/lib/arel/visitors.rb +20 -0
 - data/lib/arel/visitors/depth_first.rb +204 -0
 - data/lib/arel/visitors/dot.rb +297 -0
 - data/lib/arel/visitors/ibm_db.rb +34 -0
 - data/lib/arel/visitors/informix.rb +62 -0
 - data/lib/arel/visitors/mssql.rb +157 -0
 - data/lib/arel/visitors/mysql.rb +83 -0
 - data/lib/arel/visitors/oracle.rb +159 -0
 - data/lib/arel/visitors/oracle12.rb +66 -0
 - data/lib/arel/visitors/postgresql.rb +110 -0
 - data/lib/arel/visitors/sqlite.rb +39 -0
 - data/lib/arel/visitors/to_sql.rb +889 -0
 - data/lib/arel/visitors/visitor.rb +46 -0
 - data/lib/arel/visitors/where_sql.rb +23 -0
 - data/lib/arel/window_predications.rb +9 -0
 - data/lib/rails/generators/active_record/migration.rb +14 -1
 - data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
 - data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
 - data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
 - data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
 - data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
 - metadata +108 -26
 - data/lib/active_record/collection_cache_key.rb +0 -53
 
| 
         @@ -14,6 +14,8 @@ module ActiveRecord 
     | 
|
| 
       14 
14 
     | 
    
         
             
                # * change_column
         
     | 
| 
       15 
15 
     | 
    
         
             
                # * change_column_default (must supply a :from and :to option)
         
     | 
| 
       16 
16 
     | 
    
         
             
                # * change_column_null
         
     | 
| 
      
 17 
     | 
    
         
            +
                # * change_column_comment (must supply a :from and :to option)
         
     | 
| 
      
 18 
     | 
    
         
            +
                # * change_table_comment (must supply a :from and :to option)
         
     | 
| 
       17 
19 
     | 
    
         
             
                # * create_join_table
         
     | 
| 
       18 
20 
     | 
    
         
             
                # * create_table
         
     | 
| 
       19 
21 
     | 
    
         
             
                # * disable_extension
         
     | 
| 
         @@ -35,7 +37,8 @@ module ActiveRecord 
     | 
|
| 
       35 
37 
     | 
    
         
             
                    :change_column_default, :add_reference, :remove_reference, :transaction,
         
     | 
| 
       36 
38 
     | 
    
         
             
                    :drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension,
         
     | 
| 
       37 
39 
     | 
    
         
             
                    :change_column, :execute, :remove_columns, :change_column_null,
         
     | 
| 
       38 
     | 
    
         
            -
                    :add_foreign_key, :remove_foreign_key
         
     | 
| 
      
 40 
     | 
    
         
            +
                    :add_foreign_key, :remove_foreign_key,
         
     | 
| 
      
 41 
     | 
    
         
            +
                    :change_column_comment, :change_table_comment
         
     | 
| 
       39 
42 
     | 
    
         
             
                  ]
         
     | 
| 
       40 
43 
     | 
    
         
             
                  include JoinTable
         
     | 
| 
       41 
44 
     | 
    
         | 
| 
         @@ -85,7 +88,7 @@ module ActiveRecord 
     | 
|
| 
       85 
88 
     | 
    
         
             
                  # invert the +command+.
         
     | 
| 
       86 
89 
     | 
    
         
             
                  def inverse_of(command, args, &block)
         
     | 
| 
       87 
90 
     | 
    
         
             
                    method = :"invert_#{command}"
         
     | 
| 
       88 
     | 
    
         
            -
                    raise IrreversibleMigration,  
     | 
| 
      
 91 
     | 
    
         
            +
                    raise IrreversibleMigration, <<~MSG unless respond_to?(method, true)
         
     | 
| 
       89 
92 
     | 
    
         
             
                      This migration uses #{command}, which is not automatically reversible.
         
     | 
| 
       90 
93 
     | 
    
         
             
                      To make the migration reversible you can either:
         
     | 
| 
       91 
94 
     | 
    
         
             
                      1. Define #up and #down methods in place of the #change method.
         
     | 
| 
         @@ -108,11 +111,17 @@ module ActiveRecord 
     | 
|
| 
       108 
111 
     | 
    
         
             
                    yield delegate.update_table_definition(table_name, self)
         
     | 
| 
       109 
112 
     | 
    
         
             
                  end
         
     | 
| 
       110 
113 
     | 
    
         | 
| 
      
 114 
     | 
    
         
            +
                  def replay(migration)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    commands.each do |cmd, args, block|
         
     | 
| 
      
 116 
     | 
    
         
            +
                      migration.send(cmd, *args, &block)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    end
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
       111 
120 
     | 
    
         
             
                  private
         
     | 
| 
       112 
121 
     | 
    
         | 
| 
       113 
122 
     | 
    
         
             
                    module StraightReversions # :nodoc:
         
     | 
| 
       114 
123 
     | 
    
         
             
                      private
         
     | 
| 
       115 
     | 
    
         
            -
                        { 
     | 
| 
      
 124 
     | 
    
         
            +
                        {
         
     | 
| 
       116 
125 
     | 
    
         
             
                          execute_block:     :execute_block,
         
     | 
| 
       117 
126 
     | 
    
         
             
                          create_table:      :drop_table,
         
     | 
| 
       118 
127 
     | 
    
         
             
                          create_join_table: :drop_join_table,
         
     | 
| 
         @@ -133,6 +142,17 @@ module ActiveRecord 
     | 
|
| 
       133 
142 
     | 
    
         | 
| 
       134 
143 
     | 
    
         
             
                    include StraightReversions
         
     | 
| 
       135 
144 
     | 
    
         | 
| 
      
 145 
     | 
    
         
            +
                    def invert_transaction(args)
         
     | 
| 
      
 146 
     | 
    
         
            +
                      sub_recorder = CommandRecorder.new(delegate)
         
     | 
| 
      
 147 
     | 
    
         
            +
                      sub_recorder.revert { yield }
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                      invertions_proc = proc {
         
     | 
| 
      
 150 
     | 
    
         
            +
                        sub_recorder.replay(self)
         
     | 
| 
      
 151 
     | 
    
         
            +
                      }
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                      [:transaction, args, invertions_proc]
         
     | 
| 
      
 154 
     | 
    
         
            +
                    end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
       136 
156 
     | 
    
         
             
                    def invert_drop_table(args, &block)
         
     | 
| 
       137 
157 
     | 
    
         
             
                      if args.size == 1 && block == nil
         
     | 
| 
       138 
158 
     | 
    
         
             
                        raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
         
     | 
| 
         @@ -214,15 +234,39 @@ module ActiveRecord 
     | 
|
| 
       214 
234 
     | 
    
         
             
                    end
         
     | 
| 
       215 
235 
     | 
    
         | 
| 
       216 
236 
     | 
    
         
             
                    def invert_remove_foreign_key(args)
         
     | 
| 
       217 
     | 
    
         
            -
                       
     | 
| 
       218 
     | 
    
         
            -
                       
     | 
| 
      
 237 
     | 
    
         
            +
                      options = args.extract_options!
         
     | 
| 
      
 238 
     | 
    
         
            +
                      from_table, to_table = args
         
     | 
| 
      
 239 
     | 
    
         
            +
             
     | 
| 
      
 240 
     | 
    
         
            +
                      to_table ||= options.delete(:to_table)
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                      raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil?
         
     | 
| 
       219 
243 
     | 
    
         | 
| 
       220 
244 
     | 
    
         
             
                      reversed_args = [from_table, to_table]
         
     | 
| 
       221 
     | 
    
         
            -
                      reversed_args <<  
     | 
| 
      
 245 
     | 
    
         
            +
                      reversed_args << options unless options.empty?
         
     | 
| 
       222 
246 
     | 
    
         | 
| 
       223 
247 
     | 
    
         
             
                      [:add_foreign_key, reversed_args]
         
     | 
| 
       224 
248 
     | 
    
         
             
                    end
         
     | 
| 
       225 
249 
     | 
    
         | 
| 
      
 250 
     | 
    
         
            +
                    def invert_change_column_comment(args)
         
     | 
| 
      
 251 
     | 
    
         
            +
                      table, column, options = *args
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                      unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
         
     | 
| 
      
 254 
     | 
    
         
            +
                        raise ActiveRecord::IrreversibleMigration, "change_column_comment is only reversible if given a :from and :to option."
         
     | 
| 
      
 255 
     | 
    
         
            +
                      end
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
                      [:change_column_comment, [table, column, from: options[:to], to: options[:from]]]
         
     | 
| 
      
 258 
     | 
    
         
            +
                    end
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                    def invert_change_table_comment(args)
         
     | 
| 
      
 261 
     | 
    
         
            +
                      table, options = *args
         
     | 
| 
      
 262 
     | 
    
         
            +
             
     | 
| 
      
 263 
     | 
    
         
            +
                      unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
         
     | 
| 
      
 264 
     | 
    
         
            +
                        raise ActiveRecord::IrreversibleMigration, "change_table_comment is only reversible if given a :from and :to option."
         
     | 
| 
      
 265 
     | 
    
         
            +
                      end
         
     | 
| 
      
 266 
     | 
    
         
            +
             
     | 
| 
      
 267 
     | 
    
         
            +
                      [:change_table_comment, [table, from: options[:to], to: options[:from]]]
         
     | 
| 
      
 268 
     | 
    
         
            +
                    end
         
     | 
| 
      
 269 
     | 
    
         
            +
             
     | 
| 
       226 
270 
     | 
    
         
             
                    def respond_to_missing?(method, _)
         
     | 
| 
       227 
271 
     | 
    
         
             
                      super || delegate.respond_to?(method)
         
     | 
| 
       228 
272 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -13,7 +13,77 @@ module ActiveRecord 
     | 
|
| 
       13 
13 
     | 
    
         
             
                    const_get(name)
         
     | 
| 
       14 
14 
     | 
    
         
             
                  end
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                   
     | 
| 
      
 16 
     | 
    
         
            +
                  V6_0 = Current
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  class V5_2 < V6_0
         
     | 
| 
      
 19 
     | 
    
         
            +
                    module TableDefinition
         
     | 
| 
      
 20 
     | 
    
         
            +
                      def timestamps(**options)
         
     | 
| 
      
 21 
     | 
    
         
            +
                        options[:precision] ||= nil
         
     | 
| 
      
 22 
     | 
    
         
            +
                        super
         
     | 
| 
      
 23 
     | 
    
         
            +
                      end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    module CommandRecorder
         
     | 
| 
      
 27 
     | 
    
         
            +
                      def invert_transaction(args, &block)
         
     | 
| 
      
 28 
     | 
    
         
            +
                        [:transaction, args, block]
         
     | 
| 
      
 29 
     | 
    
         
            +
                      end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                      def invert_change_column_comment(args)
         
     | 
| 
      
 32 
     | 
    
         
            +
                        table_name, column_name, comment = args
         
     | 
| 
      
 33 
     | 
    
         
            +
                        [:change_column_comment, [table_name, column_name, from: comment, to: comment]]
         
     | 
| 
      
 34 
     | 
    
         
            +
                      end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                      def invert_change_table_comment(args)
         
     | 
| 
      
 37 
     | 
    
         
            +
                        table_name, comment = args
         
     | 
| 
      
 38 
     | 
    
         
            +
                        [:change_table_comment, [table_name, from: comment, to: comment]]
         
     | 
| 
      
 39 
     | 
    
         
            +
                      end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    def create_table(table_name, **options)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      if block_given?
         
     | 
| 
      
 44 
     | 
    
         
            +
                        super { |t| yield compatible_table_definition(t) }
         
     | 
| 
      
 45 
     | 
    
         
            +
                      else
         
     | 
| 
      
 46 
     | 
    
         
            +
                        super
         
     | 
| 
      
 47 
     | 
    
         
            +
                      end
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    def change_table(table_name, **options)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      if block_given?
         
     | 
| 
      
 52 
     | 
    
         
            +
                        super { |t| yield compatible_table_definition(t) }
         
     | 
| 
      
 53 
     | 
    
         
            +
                      else
         
     | 
| 
      
 54 
     | 
    
         
            +
                        super
         
     | 
| 
      
 55 
     | 
    
         
            +
                      end
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    def create_join_table(table_1, table_2, **options)
         
     | 
| 
      
 59 
     | 
    
         
            +
                      if block_given?
         
     | 
| 
      
 60 
     | 
    
         
            +
                        super { |t| yield compatible_table_definition(t) }
         
     | 
| 
      
 61 
     | 
    
         
            +
                      else
         
     | 
| 
      
 62 
     | 
    
         
            +
                        super
         
     | 
| 
      
 63 
     | 
    
         
            +
                      end
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    def add_timestamps(table_name, **options)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      options[:precision] ||= nil
         
     | 
| 
      
 68 
     | 
    
         
            +
                      super
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    private
         
     | 
| 
      
 72 
     | 
    
         
            +
                      def compatible_table_definition(t)
         
     | 
| 
      
 73 
     | 
    
         
            +
                        class << t
         
     | 
| 
      
 74 
     | 
    
         
            +
                          prepend TableDefinition
         
     | 
| 
      
 75 
     | 
    
         
            +
                        end
         
     | 
| 
      
 76 
     | 
    
         
            +
                        t
         
     | 
| 
      
 77 
     | 
    
         
            +
                      end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                      def command_recorder
         
     | 
| 
      
 80 
     | 
    
         
            +
                        recorder = super
         
     | 
| 
      
 81 
     | 
    
         
            +
                        class << recorder
         
     | 
| 
      
 82 
     | 
    
         
            +
                          prepend CommandRecorder
         
     | 
| 
      
 83 
     | 
    
         
            +
                        end
         
     | 
| 
      
 84 
     | 
    
         
            +
                        recorder
         
     | 
| 
      
 85 
     | 
    
         
            +
                      end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
       17 
87 
     | 
    
         | 
| 
       18 
88 
     | 
    
         
             
                  class V5_1 < V5_2
         
     | 
| 
       19 
89 
     | 
    
         
             
                    def change_column(table_name, column_name, type, options = {})
         
     | 
| 
         @@ -69,35 +139,12 @@ module ActiveRecord 
     | 
|
| 
       69 
139 
     | 
    
         
             
                        options[:id] = :integer
         
     | 
| 
       70 
140 
     | 
    
         
             
                      end
         
     | 
| 
       71 
141 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                       
     | 
| 
       73 
     | 
    
         
            -
                        super do |t|
         
     | 
| 
       74 
     | 
    
         
            -
                          yield compatible_table_definition(t)
         
     | 
| 
       75 
     | 
    
         
            -
                        end
         
     | 
| 
       76 
     | 
    
         
            -
                      else
         
     | 
| 
       77 
     | 
    
         
            -
                        super
         
     | 
| 
       78 
     | 
    
         
            -
                      end
         
     | 
| 
       79 
     | 
    
         
            -
                    end
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                    def change_table(table_name, options = {})
         
     | 
| 
       82 
     | 
    
         
            -
                      if block_given?
         
     | 
| 
       83 
     | 
    
         
            -
                        super do |t|
         
     | 
| 
       84 
     | 
    
         
            -
                          yield compatible_table_definition(t)
         
     | 
| 
       85 
     | 
    
         
            -
                        end
         
     | 
| 
       86 
     | 
    
         
            -
                      else
         
     | 
| 
       87 
     | 
    
         
            -
                        super
         
     | 
| 
       88 
     | 
    
         
            -
                      end
         
     | 
| 
      
 142 
     | 
    
         
            +
                      super
         
     | 
| 
       89 
143 
     | 
    
         
             
                    end
         
     | 
| 
       90 
144 
     | 
    
         | 
| 
       91 
145 
     | 
    
         
             
                    def create_join_table(table_1, table_2, column_options: {}, **options)
         
     | 
| 
       92 
146 
     | 
    
         
             
                      column_options.reverse_merge!(type: :integer)
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
                      if block_given?
         
     | 
| 
       95 
     | 
    
         
            -
                        super do |t|
         
     | 
| 
       96 
     | 
    
         
            -
                          yield compatible_table_definition(t)
         
     | 
| 
       97 
     | 
    
         
            -
                        end
         
     | 
| 
       98 
     | 
    
         
            -
                      else
         
     | 
| 
       99 
     | 
    
         
            -
                        super
         
     | 
| 
       100 
     | 
    
         
            -
                      end
         
     | 
| 
      
 147 
     | 
    
         
            +
                      super
         
     | 
| 
       101 
148 
     | 
    
         
             
                    end
         
     | 
| 
       102 
149 
     | 
    
         | 
| 
       103 
150 
     | 
    
         
             
                    def add_column(table_name, column_name, type, options = {})
         
     | 
| 
         @@ -118,7 +165,7 @@ module ActiveRecord 
     | 
|
| 
       118 
165 
     | 
    
         
             
                        class << t
         
     | 
| 
       119 
166 
     | 
    
         
             
                          prepend TableDefinition
         
     | 
| 
       120 
167 
     | 
    
         
             
                        end
         
     | 
| 
       121 
     | 
    
         
            -
                         
     | 
| 
      
 168 
     | 
    
         
            +
                        super
         
     | 
| 
       122 
169 
     | 
    
         
             
                      end
         
     | 
| 
       123 
170 
     | 
    
         
             
                  end
         
     | 
| 
       124 
171 
     | 
    
         | 
| 
         @@ -136,33 +183,13 @@ module ActiveRecord 
     | 
|
| 
       136 
183 
     | 
    
         
             
                      end
         
     | 
| 
       137 
184 
     | 
    
         
             
                    end
         
     | 
| 
       138 
185 
     | 
    
         | 
| 
       139 
     | 
    
         
            -
                    def  
     | 
| 
       140 
     | 
    
         
            -
                      if block_given?
         
     | 
| 
       141 
     | 
    
         
            -
                        super do |t|
         
     | 
| 
       142 
     | 
    
         
            -
                          yield compatible_table_definition(t)
         
     | 
| 
       143 
     | 
    
         
            -
                        end
         
     | 
| 
       144 
     | 
    
         
            -
                      else
         
     | 
| 
       145 
     | 
    
         
            -
                        super
         
     | 
| 
       146 
     | 
    
         
            -
                      end
         
     | 
| 
       147 
     | 
    
         
            -
                    end
         
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
                    def change_table(table_name, options = {})
         
     | 
| 
       150 
     | 
    
         
            -
                      if block_given?
         
     | 
| 
       151 
     | 
    
         
            -
                        super do |t|
         
     | 
| 
       152 
     | 
    
         
            -
                          yield compatible_table_definition(t)
         
     | 
| 
       153 
     | 
    
         
            -
                        end
         
     | 
| 
       154 
     | 
    
         
            -
                      else
         
     | 
| 
       155 
     | 
    
         
            -
                        super
         
     | 
| 
       156 
     | 
    
         
            -
                      end
         
     | 
| 
       157 
     | 
    
         
            -
                    end
         
     | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
       159 
     | 
    
         
            -
                    def add_reference(*, **options)
         
     | 
| 
      
 186 
     | 
    
         
            +
                    def add_reference(table_name, ref_name, **options)
         
     | 
| 
       160 
187 
     | 
    
         
             
                      options[:index] ||= false
         
     | 
| 
       161 
188 
     | 
    
         
             
                      super
         
     | 
| 
       162 
189 
     | 
    
         
             
                    end
         
     | 
| 
       163 
190 
     | 
    
         
             
                    alias :add_belongs_to :add_reference
         
     | 
| 
       164 
191 
     | 
    
         | 
| 
       165 
     | 
    
         
            -
                    def add_timestamps( 
     | 
| 
      
 192 
     | 
    
         
            +
                    def add_timestamps(table_name, **options)
         
     | 
| 
       166 
193 
     | 
    
         
             
                      options[:null] = true if options[:null].nil?
         
     | 
| 
       167 
194 
     | 
    
         
             
                      super
         
     | 
| 
       168 
195 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -102,6 +102,21 @@ module ActiveRecord 
     | 
|
| 
       102 
102 
     | 
    
         
             
                # If true, the default table name for a Product class will be "products". If false, it would just be "product".
         
     | 
| 
       103 
103 
     | 
    
         
             
                # See table_name for the full rules on table/class naming. This is true, by default.
         
     | 
| 
       104 
104 
     | 
    
         | 
| 
      
 105 
     | 
    
         
            +
                ##
         
     | 
| 
      
 106 
     | 
    
         
            +
                # :singleton-method: implicit_order_column
         
     | 
| 
      
 107 
     | 
    
         
            +
                # :call-seq: implicit_order_column
         
     | 
| 
      
 108 
     | 
    
         
            +
                #
         
     | 
| 
      
 109 
     | 
    
         
            +
                # The name of the column records are ordered by if no explicit order clause
         
     | 
| 
      
 110 
     | 
    
         
            +
                # is used during an ordered finder call. If not set the primary key is used.
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                ##
         
     | 
| 
      
 113 
     | 
    
         
            +
                # :singleton-method: implicit_order_column=
         
     | 
| 
      
 114 
     | 
    
         
            +
                # :call-seq: implicit_order_column=(column_name)
         
     | 
| 
      
 115 
     | 
    
         
            +
                #
         
     | 
| 
      
 116 
     | 
    
         
            +
                # Sets the column to sort records by when no explicit order clause is used
         
     | 
| 
      
 117 
     | 
    
         
            +
                # during an ordered finder call. Useful when the primary key is not an
         
     | 
| 
      
 118 
     | 
    
         
            +
                # auto-incrementing integer, for example when it's a UUID. Note that using
         
     | 
| 
      
 119 
     | 
    
         
            +
                # a non-unique column can result in non-deterministic results.
         
     | 
| 
       105 
120 
     | 
    
         
             
                included do
         
     | 
| 
       106 
121 
     | 
    
         
             
                  mattr_accessor :primary_key_prefix_type, instance_writer: false
         
     | 
| 
       107 
122 
     | 
    
         | 
| 
         @@ -110,6 +125,7 @@ module ActiveRecord 
     | 
|
| 
       110 
125 
     | 
    
         
             
                  class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
         
     | 
| 
       111 
126 
     | 
    
         
             
                  class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
         
     | 
| 
       112 
127 
     | 
    
         
             
                  class_attribute :pluralize_table_names, instance_writer: false, default: true
         
     | 
| 
      
 128 
     | 
    
         
            +
                  class_attribute :implicit_order_column, instance_accessor: false
         
     | 
| 
       113 
129 
     | 
    
         | 
| 
       114 
130 
     | 
    
         
             
                  self.protected_environments = ["production"]
         
     | 
| 
       115 
131 
     | 
    
         
             
                  self.inheritance_column = "type"
         
     | 
| 
         @@ -218,11 +234,11 @@ module ActiveRecord 
     | 
|
| 
       218 
234 
     | 
    
         
             
                  end
         
     | 
| 
       219 
235 
     | 
    
         | 
| 
       220 
236 
     | 
    
         
             
                  def full_table_name_prefix #:nodoc:
         
     | 
| 
       221 
     | 
    
         
            -
                    ( 
     | 
| 
      
 237 
     | 
    
         
            +
                    (module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
         
     | 
| 
       222 
238 
     | 
    
         
             
                  end
         
     | 
| 
       223 
239 
     | 
    
         | 
| 
       224 
240 
     | 
    
         
             
                  def full_table_name_suffix #:nodoc:
         
     | 
| 
       225 
     | 
    
         
            -
                    ( 
     | 
| 
      
 241 
     | 
    
         
            +
                    (module_parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
         
     | 
| 
       226 
242 
     | 
    
         
             
                  end
         
     | 
| 
       227 
243 
     | 
    
         | 
| 
       228 
244 
     | 
    
         
             
                  # The array of names of environments where destructive actions should be prohibited. By default,
         
     | 
| 
         @@ -276,7 +292,7 @@ module ActiveRecord 
     | 
|
| 
       276 
292 
     | 
    
         
             
                  end
         
     | 
| 
       277 
293 
     | 
    
         | 
| 
       278 
294 
     | 
    
         
             
                  def sequence_name
         
     | 
| 
       279 
     | 
    
         
            -
                    if base_class 
     | 
| 
      
 295 
     | 
    
         
            +
                    if base_class?
         
     | 
| 
       280 
296 
     | 
    
         
             
                      @sequence_name ||= reset_sequence_name
         
     | 
| 
       281 
297 
     | 
    
         
             
                    else
         
     | 
| 
       282 
298 
     | 
    
         
             
                      (@sequence_name ||= nil) || base_class.sequence_name
         
     | 
| 
         @@ -388,6 +404,11 @@ module ActiveRecord 
     | 
|
| 
       388 
404 
     | 
    
         
             
                    @column_names ||= columns.map(&:name)
         
     | 
| 
       389 
405 
     | 
    
         
             
                  end
         
     | 
| 
       390 
406 
     | 
    
         | 
| 
      
 407 
     | 
    
         
            +
                  def symbol_column_to_string(name_symbol) # :nodoc:
         
     | 
| 
      
 408 
     | 
    
         
            +
                    @symbol_column_to_string_name_hash ||= column_names.index_by(&:to_sym)
         
     | 
| 
      
 409 
     | 
    
         
            +
                    @symbol_column_to_string_name_hash[name_symbol]
         
     | 
| 
      
 410 
     | 
    
         
            +
                  end
         
     | 
| 
      
 411 
     | 
    
         
            +
             
     | 
| 
       391 
412 
     | 
    
         
             
                  # Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
         
     | 
| 
       392 
413 
     | 
    
         
             
                  # and columns used for single table inheritance have been removed.
         
     | 
| 
       393 
414 
     | 
    
         
             
                  def content_columns
         
     | 
| 
         @@ -477,6 +498,7 @@ module ActiveRecord 
     | 
|
| 
       477 
498 
     | 
    
         
             
                    def reload_schema_from_cache
         
     | 
| 
       478 
499 
     | 
    
         
             
                      @arel_table = nil
         
     | 
| 
       479 
500 
     | 
    
         
             
                      @column_names = nil
         
     | 
| 
      
 501 
     | 
    
         
            +
                      @symbol_column_to_string_name_hash = nil
         
     | 
| 
       480 
502 
     | 
    
         
             
                      @attribute_types = nil
         
     | 
| 
       481 
503 
     | 
    
         
             
                      @content_columns = nil
         
     | 
| 
       482 
504 
     | 
    
         
             
                      @default_attributes = nil
         
     | 
| 
         @@ -501,19 +523,18 @@ module ActiveRecord 
     | 
|
| 
       501 
523 
     | 
    
         | 
| 
       502 
524 
     | 
    
         
             
                    # Computes and returns a table name according to default conventions.
         
     | 
| 
       503 
525 
     | 
    
         
             
                    def compute_table_name
         
     | 
| 
       504 
     | 
    
         
            -
                       
     | 
| 
       505 
     | 
    
         
            -
                      if self == base
         
     | 
| 
      
 526 
     | 
    
         
            +
                      if base_class?
         
     | 
| 
       506 
527 
     | 
    
         
             
                        # Nested classes are prefixed with singular parent table name.
         
     | 
| 
       507 
     | 
    
         
            -
                        if  
     | 
| 
       508 
     | 
    
         
            -
                          contained =  
     | 
| 
       509 
     | 
    
         
            -
                          contained = contained.singularize if  
     | 
| 
      
 528 
     | 
    
         
            +
                        if module_parent < Base && !module_parent.abstract_class?
         
     | 
| 
      
 529 
     | 
    
         
            +
                          contained = module_parent.table_name
         
     | 
| 
      
 530 
     | 
    
         
            +
                          contained = contained.singularize if module_parent.pluralize_table_names
         
     | 
| 
       510 
531 
     | 
    
         
             
                          contained += "_"
         
     | 
| 
       511 
532 
     | 
    
         
             
                        end
         
     | 
| 
       512 
533 
     | 
    
         | 
| 
       513 
534 
     | 
    
         
             
                        "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
         
     | 
| 
       514 
535 
     | 
    
         
             
                      else
         
     | 
| 
       515 
536 
     | 
    
         
             
                        # STI subclasses always use their superclass' table.
         
     | 
| 
       516 
     | 
    
         
            -
                         
     | 
| 
      
 537 
     | 
    
         
            +
                        base_class.table_name
         
     | 
| 
       517 
538 
     | 
    
         
             
                      end
         
     | 
| 
       518 
539 
     | 
    
         
             
                    end
         
     | 
| 
       519 
540 
     | 
    
         
             
                end
         
     | 
| 
         @@ -426,7 +426,7 @@ module ActiveRecord 
     | 
|
| 
       426 
426 
     | 
    
         
             
                        existing_record.assign_attributes(assignable_attributes)
         
     | 
| 
       427 
427 
     | 
    
         
             
                        association(association_name).initialize_attributes(existing_record)
         
     | 
| 
       428 
428 
     | 
    
         
             
                      else
         
     | 
| 
       429 
     | 
    
         
            -
                        method = "build_#{association_name}"
         
     | 
| 
      
 429 
     | 
    
         
            +
                        method = :"build_#{association_name}"
         
     | 
| 
       430 
430 
     | 
    
         
             
                        if respond_to?(method)
         
     | 
| 
       431 
431 
     | 
    
         
             
                          send(method, assignable_attributes)
         
     | 
| 
       432 
432 
     | 
    
         
             
                        else
         
     | 
| 
         @@ -501,7 +501,7 @@ module ActiveRecord 
     | 
|
| 
       501 
501 
     | 
    
         | 
| 
       502 
502 
     | 
    
         
             
                      if attributes["id"].blank?
         
     | 
| 
       503 
503 
     | 
    
         
             
                        unless reject_new_record?(association_name, attributes)
         
     | 
| 
       504 
     | 
    
         
            -
                          association.build(attributes.except(*UNASSIGNABLE_KEYS))
         
     | 
| 
      
 504 
     | 
    
         
            +
                          association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
         
     | 
| 
       505 
505 
     | 
    
         
             
                        end
         
     | 
| 
       506 
506 
     | 
    
         
             
                      elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes["id"].to_s }
         
     | 
| 
       507 
507 
     | 
    
         
             
                        unless call_reject_if(association_name, attributes)
         
     | 
| 
         @@ -43,6 +43,13 @@ module ActiveRecord 
     | 
|
| 
       43 
43 
     | 
    
         
             
                    end
         
     | 
| 
       44 
44 
     | 
    
         
             
                end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
      
 46 
     | 
    
         
            +
                # Returns +true+ if the class has +no_touching+ set, +false+ otherwise.
         
     | 
| 
      
 47 
     | 
    
         
            +
                #
         
     | 
| 
      
 48 
     | 
    
         
            +
                #   Project.no_touching do
         
     | 
| 
      
 49 
     | 
    
         
            +
                #     Project.first.no_touching? # true
         
     | 
| 
      
 50 
     | 
    
         
            +
                #     Message.first.no_touching? # false
         
     | 
| 
      
 51 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 52 
     | 
    
         
            +
                #
         
     | 
| 
       46 
53 
     | 
    
         
             
                def no_touching?
         
     | 
| 
       47 
54 
     | 
    
         
             
                  NoTouching.applied_to?(self.class)
         
     | 
| 
       48 
55 
     | 
    
         
             
                end
         
     | 
| 
         @@ -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 
     | 
    
         
             
                    #
         
     | 
| 
         @@ -229,20 +424,20 @@ 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
         
     | 
| 
      
 427 
     | 
    
         
            +
                  sync_with_transaction_state if @transaction_state&.finalized?
         
     | 
| 
       233 
428 
     | 
    
         
             
                  @new_record
         
     | 
| 
       234 
429 
     | 
    
         
             
                end
         
     | 
| 
       235 
430 
     | 
    
         | 
| 
       236 
431 
     | 
    
         
             
                # Returns true if this object has been destroyed, otherwise returns false.
         
     | 
| 
       237 
432 
     | 
    
         
             
                def destroyed?
         
     | 
| 
       238 
     | 
    
         
            -
                  sync_with_transaction_state
         
     | 
| 
      
 433 
     | 
    
         
            +
                  sync_with_transaction_state if @transaction_state&.finalized?
         
     | 
| 
       239 
434 
     | 
    
         
             
                  @destroyed
         
     | 
| 
       240 
435 
     | 
    
         
             
                end
         
     | 
| 
       241 
436 
     | 
    
         | 
| 
       242 
437 
     | 
    
         
             
                # Returns true if the record is persisted, i.e. it's not a new record and it was
         
     | 
| 
       243 
438 
     | 
    
         
             
                # not destroyed, otherwise returns false.
         
     | 
| 
       244 
439 
     | 
    
         
             
                def persisted?
         
     | 
| 
       245 
     | 
    
         
            -
                  sync_with_transaction_state
         
     | 
| 
      
 440 
     | 
    
         
            +
                  sync_with_transaction_state if @transaction_state&.finalized?
         
     | 
| 
       246 
441 
     | 
    
         
             
                  !(@new_record || @destroyed)
         
     | 
| 
       247 
442 
     | 
    
         
             
                end
         
     | 
| 
       248 
443 
     | 
    
         | 
| 
         @@ -336,7 +531,6 @@ module ActiveRecord 
     | 
|
| 
       336 
531 
     | 
    
         
             
                def destroy
         
     | 
| 
       337 
532 
     | 
    
         
             
                  _raise_readonly_record_error if readonly?
         
     | 
| 
       338 
533 
     | 
    
         
             
                  destroy_associations
         
     | 
| 
       339 
     | 
    
         
            -
                  self.class.connection.add_transaction_record(self)
         
     | 
| 
       340 
534 
     | 
    
         
             
                  @_trigger_destroy_callback = if persisted?
         
     | 
| 
       341 
535 
     | 
    
         
             
                    destroy_row > 0
         
     | 
| 
       342 
536 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -374,7 +568,6 @@ module ActiveRecord 
     | 
|
| 
       374 
568 
     | 
    
         
             
                  became.send(:initialize)
         
     | 
| 
       375 
569 
     | 
    
         
             
                  became.instance_variable_set("@attributes", @attributes)
         
     | 
| 
       376 
570 
     | 
    
         
             
                  became.instance_variable_set("@mutations_from_database", @mutations_from_database ||= nil)
         
     | 
| 
       377 
     | 
    
         
            -
                  became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
         
     | 
| 
       378 
571 
     | 
    
         
             
                  became.instance_variable_set("@new_record", new_record?)
         
     | 
| 
       379 
572 
     | 
    
         
             
                  became.instance_variable_set("@destroyed", destroyed?)
         
     | 
| 
       380 
573 
     | 
    
         
             
                  became.errors.copy!(errors)
         
     | 
| 
         @@ -430,6 +623,7 @@ module ActiveRecord 
     | 
|
| 
       430 
623 
     | 
    
         
             
                end
         
     | 
| 
       431 
624 
     | 
    
         | 
| 
       432 
625 
     | 
    
         
             
                alias update_attributes update
         
     | 
| 
      
 626 
     | 
    
         
            +
                deprecate update_attributes: "please, use update instead"
         
     | 
| 
       433 
627 
     | 
    
         | 
| 
       434 
628 
     | 
    
         
             
                # Updates its receiver just like #update but calls #save! instead
         
     | 
| 
       435 
629 
     | 
    
         
             
                # of +save+, so an exception is raised if the record is invalid and saving will fail.
         
     | 
| 
         @@ -443,6 +637,7 @@ module ActiveRecord 
     | 
|
| 
       443 
637 
     | 
    
         
             
                end
         
     | 
| 
       444 
638 
     | 
    
         | 
| 
       445 
639 
     | 
    
         
             
                alias update_attributes! update!
         
     | 
| 
      
 640 
     | 
    
         
            +
                deprecate update_attributes!: "please, use update! instead"
         
     | 
| 
       446 
641 
     | 
    
         | 
| 
       447 
642 
     | 
    
         
             
                # Equivalent to <code>update_columns(name => value)</code>.
         
     | 
| 
       448 
643 
     | 
    
         
             
                def update_column(name, value)
         
     | 
| 
         @@ -469,8 +664,13 @@ module ActiveRecord 
     | 
|
| 
       469 
664 
     | 
    
         
             
                  raise ActiveRecordError, "cannot update a new record" if new_record?
         
     | 
| 
       470 
665 
     | 
    
         
             
                  raise ActiveRecordError, "cannot update a destroyed record" if destroyed?
         
     | 
| 
       471 
666 
     | 
    
         | 
| 
      
 667 
     | 
    
         
            +
                  attributes = attributes.transform_keys do |key|
         
     | 
| 
      
 668 
     | 
    
         
            +
                    name = key.to_s
         
     | 
| 
      
 669 
     | 
    
         
            +
                    self.class.attribute_aliases[name] || name
         
     | 
| 
      
 670 
     | 
    
         
            +
                  end
         
     | 
| 
      
 671 
     | 
    
         
            +
             
     | 
| 
       472 
672 
     | 
    
         
             
                  attributes.each_key do |key|
         
     | 
| 
       473 
     | 
    
         
            -
                    verify_readonly_attribute(key 
     | 
| 
      
 673 
     | 
    
         
            +
                    verify_readonly_attribute(key)
         
     | 
| 
       474 
674 
     | 
    
         
             
                  end
         
     | 
| 
       475 
675 
     | 
    
         | 
| 
       476 
676 
     | 
    
         
             
                  id_in_database = self.id_in_database
         
     | 
| 
         @@ -480,7 +680,7 @@ module ActiveRecord 
     | 
|
| 
       480 
680 
     | 
    
         | 
| 
       481 
681 
     | 
    
         
             
                  affected_rows = self.class._update_record(
         
     | 
| 
       482 
682 
     | 
    
         
             
                    attributes,
         
     | 
| 
       483 
     | 
    
         
            -
                     
     | 
| 
      
 683 
     | 
    
         
            +
                    @primary_key => id_in_database
         
     | 
| 
       484 
684 
     | 
    
         
             
                  )
         
     | 
| 
       485 
685 
     | 
    
         | 
| 
       486 
686 
     | 
    
         
             
                  affected_rows == 1
         
     | 
| 
         @@ -657,7 +857,9 @@ module ActiveRecord 
     | 
|
| 
       657 
857 
     | 
    
         
             
                  end
         
     | 
| 
       658 
858 
     | 
    
         | 
| 
       659 
859 
     | 
    
         
             
                  attribute_names = timestamp_attributes_for_update_in_model
         
     | 
| 
       660 
     | 
    
         
            -
                  attribute_names |= names.map(&:to_s)
         
     | 
| 
      
 860 
     | 
    
         
            +
                  attribute_names |= names.map!(&:to_s).map! { |name|
         
     | 
| 
      
 861 
     | 
    
         
            +
                    self.class.attribute_aliases[name] || name
         
     | 
| 
      
 862 
     | 
    
         
            +
                  }
         
     | 
| 
       661 
863 
     | 
    
         | 
| 
       662 
864 
     | 
    
         
             
                  unless attribute_names.empty?
         
     | 
| 
       663 
865 
     | 
    
         
             
                    affected_rows = _touch_row(attribute_names, time)
         
     | 
| 
         @@ -678,15 +880,14 @@ module ActiveRecord 
     | 
|
| 
       678 
880 
     | 
    
         
             
                end
         
     | 
| 
       679 
881 
     | 
    
         | 
| 
       680 
882 
     | 
    
         
             
                def _delete_row
         
     | 
| 
       681 
     | 
    
         
            -
                  self.class._delete_record( 
     | 
| 
      
 883 
     | 
    
         
            +
                  self.class._delete_record(@primary_key => id_in_database)
         
     | 
| 
       682 
884 
     | 
    
         
             
                end
         
     | 
| 
       683 
885 
     | 
    
         | 
| 
       684 
886 
     | 
    
         
             
                def _touch_row(attribute_names, time)
         
     | 
| 
       685 
887 
     | 
    
         
             
                  time ||= current_time_from_proper_timezone
         
     | 
| 
       686 
888 
     | 
    
         | 
| 
       687 
889 
     | 
    
         
             
                  attribute_names.each do |attr_name|
         
     | 
| 
       688 
     | 
    
         
            -
                     
     | 
| 
       689 
     | 
    
         
            -
                    clear_attribute_change(attr_name)
         
     | 
| 
      
 890 
     | 
    
         
            +
                    _write_attribute(attr_name, time)
         
     | 
| 
       690 
891 
     | 
    
         
             
                  end
         
     | 
| 
       691 
892 
     | 
    
         | 
| 
       692 
893 
     | 
    
         
             
                  _update_row(attribute_names, "touch")
         
     | 
| 
         @@ -695,21 +896,20 @@ module ActiveRecord 
     | 
|
| 
       695 
896 
     | 
    
         
             
                def _update_row(attribute_names, attempted_action = "update")
         
     | 
| 
       696 
897 
     | 
    
         
             
                  self.class._update_record(
         
     | 
| 
       697 
898 
     | 
    
         
             
                    attributes_with_values(attribute_names),
         
     | 
| 
       698 
     | 
    
         
            -
                     
     | 
| 
      
 899 
     | 
    
         
            +
                    @primary_key => id_in_database
         
     | 
| 
       699 
900 
     | 
    
         
             
                  )
         
     | 
| 
       700 
901 
     | 
    
         
             
                end
         
     | 
| 
       701 
902 
     | 
    
         | 
| 
       702 
     | 
    
         
            -
                def create_or_update( 
     | 
| 
      
 903 
     | 
    
         
            +
                def create_or_update(**, &block)
         
     | 
| 
       703 
904 
     | 
    
         
             
                  _raise_readonly_record_error if readonly?
         
     | 
| 
       704 
905 
     | 
    
         
             
                  return false if destroyed?
         
     | 
| 
       705 
     | 
    
         
            -
                  result = new_record? ? _create_record(&block) : _update_record( 
     | 
| 
      
 906 
     | 
    
         
            +
                  result = new_record? ? _create_record(&block) : _update_record(&block)
         
     | 
| 
       706 
907 
     | 
    
         
             
                  result != false
         
     | 
| 
       707 
908 
     | 
    
         
             
                end
         
     | 
| 
       708 
909 
     | 
    
         | 
| 
       709 
910 
     | 
    
         
             
                # Updates the associated record with values matching those of the instance attributes.
         
     | 
| 
       710 
911 
     | 
    
         
             
                # Returns the number of affected rows.
         
     | 
| 
       711 
912 
     | 
    
         
             
                def _update_record(attribute_names = self.attribute_names)
         
     | 
| 
       712 
     | 
    
         
            -
                  attribute_names &= self.class.column_names
         
     | 
| 
       713 
913 
     | 
    
         
             
                  attribute_names = attributes_for_update(attribute_names)
         
     | 
| 
       714 
914 
     | 
    
         | 
| 
       715 
915 
     | 
    
         
             
                  if attribute_names.empty?
         
     | 
| 
         @@ -728,11 +928,13 @@ module ActiveRecord 
     | 
|
| 
       728 
928 
     | 
    
         
             
                # Creates a record with values matching those of the instance attributes
         
     | 
| 
       729 
929 
     | 
    
         
             
                # and returns its id.
         
     | 
| 
       730 
930 
     | 
    
         
             
                def _create_record(attribute_names = self.attribute_names)
         
     | 
| 
       731 
     | 
    
         
            -
                  attribute_names  
     | 
| 
       732 
     | 
    
         
            -
             
     | 
| 
      
 931 
     | 
    
         
            +
                  attribute_names = attributes_for_create(attribute_names)
         
     | 
| 
      
 932 
     | 
    
         
            +
             
     | 
| 
      
 933 
     | 
    
         
            +
                  new_id = self.class._insert_record(
         
     | 
| 
      
 934 
     | 
    
         
            +
                    attributes_with_values(attribute_names)
         
     | 
| 
      
 935 
     | 
    
         
            +
                  )
         
     | 
| 
       733 
936 
     | 
    
         | 
| 
       734 
     | 
    
         
            -
                  new_id  
     | 
| 
       735 
     | 
    
         
            -
                  self.id ||= new_id if self.class.primary_key
         
     | 
| 
      
 937 
     | 
    
         
            +
                  self.id ||= new_id if @primary_key
         
     | 
| 
       736 
938 
     | 
    
         | 
| 
       737 
939 
     | 
    
         
             
                  @new_record = false
         
     | 
| 
       738 
940 
     | 
    
         | 
| 
         @@ -752,6 +954,8 @@ module ActiveRecord 
     | 
|
| 
       752 
954 
     | 
    
         
             
                  @_association_destroy_exception = nil
         
     | 
| 
       753 
955 
     | 
    
         
             
                end
         
     | 
| 
       754 
956 
     | 
    
         | 
| 
      
 957 
     | 
    
         
            +
                # The name of the method used to touch a +belongs_to+ association when the
         
     | 
| 
      
 958 
     | 
    
         
            +
                # +:touch+ option is used.
         
     | 
| 
       755 
959 
     | 
    
         
             
                def belongs_to_touch_method
         
     | 
| 
       756 
960 
     | 
    
         
             
                  :touch
         
     | 
| 
       757 
961 
     | 
    
         
             
                end
         
     |