activerecord 5.2.3 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +898 -532
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +5 -4
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +95 -42
- data/lib/active_record/associations/association_scope.rb +21 -21
- data/lib/active_record/associations/belongs_to_association.rb +50 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -5
- data/lib/active_record/associations/builder/association.rb +23 -21
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +10 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +31 -29
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +27 -28
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -12
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +71 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +48 -35
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +133 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +45 -8
- data/lib/active_record/autosave_association.rb +76 -47
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +293 -132
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +21 -17
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +203 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +381 -146
- data/lib/active_record/connection_adapters/abstract/transaction.rb +155 -68
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +86 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +38 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +222 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +127 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +19 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +175 -187
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_handling.rb +285 -33
- data/lib/active_record/core.rb +308 -100
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +71 -17
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +197 -481
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +26 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +26 -22
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +34 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +141 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +205 -156
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +115 -58
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +402 -78
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +113 -101
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +157 -93
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +65 -40
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -7
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +58 -40
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +487 -199
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +108 -58
- data/lib/active_record/relation.rb +375 -104
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +6 -8
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +51 -8
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -43
- data/lib/active_record/tasks/database_tasks.rb +276 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +246 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +59 -117
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +10 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +117 -32
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
| @@ -102,6 +102,30 @@ 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. Records are subsorted
         | 
| 119 | 
            +
                # by the primary key if it exists to ensure deterministic results.
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                ##
         | 
| 122 | 
            +
                # :singleton-method: immutable_strings_by_default=
         | 
| 123 | 
            +
                # :call-seq: immutable_strings_by_default=(bool)
         | 
| 124 | 
            +
                #
         | 
| 125 | 
            +
                # Determines whether columns should infer their type as `:string` or
         | 
| 126 | 
            +
                # `:immutable_string`. This setting does not affect the behavior of
         | 
| 127 | 
            +
                # `attribute :foo, :string`. Defaults to false.
         | 
| 128 | 
            +
             | 
| 105 129 | 
             
                included do
         | 
| 106 130 | 
             
                  mattr_accessor :primary_key_prefix_type, instance_writer: false
         | 
| 107 131 |  | 
| @@ -110,12 +134,14 @@ module ActiveRecord | |
| 110 134 | 
             
                  class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
         | 
| 111 135 | 
             
                  class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
         | 
| 112 136 | 
             
                  class_attribute :pluralize_table_names, instance_writer: false, default: true
         | 
| 137 | 
            +
                  class_attribute :implicit_order_column, instance_accessor: false
         | 
| 138 | 
            +
                  class_attribute :immutable_strings_by_default, instance_accessor: false
         | 
| 113 139 |  | 
| 114 140 | 
             
                  self.protected_environments = ["production"]
         | 
| 115 141 | 
             
                  self.inheritance_column = "type"
         | 
| 116 142 | 
             
                  self.ignored_columns = [].freeze
         | 
| 117 143 |  | 
| 118 | 
            -
                  delegate :type_for_attribute, to: :class
         | 
| 144 | 
            +
                  delegate :type_for_attribute, :column_for_attribute, to: :class
         | 
| 119 145 |  | 
| 120 146 | 
             
                  initialize_load_schema_monitor
         | 
| 121 147 | 
             
                end
         | 
| @@ -218,11 +244,11 @@ module ActiveRecord | |
| 218 244 | 
             
                  end
         | 
| 219 245 |  | 
| 220 246 | 
             
                  def full_table_name_prefix #:nodoc:
         | 
| 221 | 
            -
                    ( | 
| 247 | 
            +
                    (module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
         | 
| 222 248 | 
             
                  end
         | 
| 223 249 |  | 
| 224 250 | 
             
                  def full_table_name_suffix #:nodoc:
         | 
| 225 | 
            -
                    ( | 
| 251 | 
            +
                    (module_parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
         | 
| 226 252 | 
             
                  end
         | 
| 227 253 |  | 
| 228 254 | 
             
                  # The array of names of environments where destructive actions should be prohibited. By default,
         | 
| @@ -271,12 +297,42 @@ module ActiveRecord | |
| 271 297 |  | 
| 272 298 | 
             
                  # Sets the columns names the model should ignore. Ignored columns won't have attribute
         | 
| 273 299 | 
             
                  # accessors defined, and won't be referenced in SQL queries.
         | 
| 300 | 
            +
                  #
         | 
| 301 | 
            +
                  # A common usage pattern for this method is to ensure all references to an attribute
         | 
| 302 | 
            +
                  # have been removed and deployed, before a migration to drop the column from the database
         | 
| 303 | 
            +
                  # has been deployed and run. Using this two step approach to dropping columns ensures there
         | 
| 304 | 
            +
                  # is no code that raises errors due to having a cached schema in memory at the time the
         | 
| 305 | 
            +
                  # schema migration is run.
         | 
| 306 | 
            +
                  #
         | 
| 307 | 
            +
                  # For example, given a model where you want to drop the "category" attribute, first mark it
         | 
| 308 | 
            +
                  # as ignored:
         | 
| 309 | 
            +
                  #
         | 
| 310 | 
            +
                  #   class Project < ActiveRecord::Base
         | 
| 311 | 
            +
                  #     # schema:
         | 
| 312 | 
            +
                  #     #   id         :bigint
         | 
| 313 | 
            +
                  #     #   name       :string, limit: 255
         | 
| 314 | 
            +
                  #     #   category   :string, limit: 255
         | 
| 315 | 
            +
                  #
         | 
| 316 | 
            +
                  #     self.ignored_columns = [:category]
         | 
| 317 | 
            +
                  #   end
         | 
| 318 | 
            +
                  #
         | 
| 319 | 
            +
                  # The schema still contains `category`, but now the model omits it, so any meta-driven code or
         | 
| 320 | 
            +
                  # schema caching will not attempt to use the column:
         | 
| 321 | 
            +
                  #
         | 
| 322 | 
            +
                  #   Project.columns_hash["category"] => nil
         | 
| 323 | 
            +
                  #
         | 
| 324 | 
            +
                  # You will get an error if accessing that attribute directly, so ensure all usages of the
         | 
| 325 | 
            +
                  # column are removed (automated tests can help you find any usages).
         | 
| 326 | 
            +
                  #
         | 
| 327 | 
            +
                  #   user = Project.create!(name: "First Project")
         | 
| 328 | 
            +
                  #   user.category # => raises NoMethodError
         | 
| 274 329 | 
             
                  def ignored_columns=(columns)
         | 
| 275 | 
            -
                     | 
| 330 | 
            +
                    reload_schema_from_cache
         | 
| 331 | 
            +
                    @ignored_columns = columns.map(&:to_s).freeze
         | 
| 276 332 | 
             
                  end
         | 
| 277 333 |  | 
| 278 334 | 
             
                  def sequence_name
         | 
| 279 | 
            -
                    if base_class | 
| 335 | 
            +
                    if base_class?
         | 
| 280 336 | 
             
                      @sequence_name ||= reset_sequence_name
         | 
| 281 337 | 
             
                    else
         | 
| 282 338 | 
             
                      (@sequence_name ||= nil) || base_class.sequence_name
         | 
| @@ -339,7 +395,7 @@ module ActiveRecord | |
| 339 395 |  | 
| 340 396 | 
             
                  def columns
         | 
| 341 397 | 
             
                    load_schema
         | 
| 342 | 
            -
                    @columns ||= columns_hash.values
         | 
| 398 | 
            +
                    @columns ||= columns_hash.values.freeze
         | 
| 343 399 | 
             
                  end
         | 
| 344 400 |  | 
| 345 401 | 
             
                  def attribute_types # :nodoc:
         | 
| @@ -364,6 +420,8 @@ module ActiveRecord | |
| 364 420 | 
             
                  # a string or a symbol.
         | 
| 365 421 | 
             
                  def type_for_attribute(attr_name, &block)
         | 
| 366 422 | 
             
                    attr_name = attr_name.to_s
         | 
| 423 | 
            +
                    attr_name = attribute_aliases[attr_name] || attr_name
         | 
| 424 | 
            +
             | 
| 367 425 | 
             
                    if block
         | 
| 368 426 | 
             
                      attribute_types.fetch(attr_name, &block)
         | 
| 369 427 | 
             
                    else
         | 
| @@ -371,11 +429,31 @@ module ActiveRecord | |
| 371 429 | 
             
                    end
         | 
| 372 430 | 
             
                  end
         | 
| 373 431 |  | 
| 432 | 
            +
                  # Returns the column object for the named attribute.
         | 
| 433 | 
            +
                  # Returns an +ActiveRecord::ConnectionAdapters::NullColumn+ if the
         | 
| 434 | 
            +
                  # named attribute does not exist.
         | 
| 435 | 
            +
                  #
         | 
| 436 | 
            +
                  #   class Person < ActiveRecord::Base
         | 
| 437 | 
            +
                  #   end
         | 
| 438 | 
            +
                  #
         | 
| 439 | 
            +
                  #   person = Person.new
         | 
| 440 | 
            +
                  #   person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
         | 
| 441 | 
            +
                  #   # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
         | 
| 442 | 
            +
                  #
         | 
| 443 | 
            +
                  #   person.column_for_attribute(:nothing)
         | 
| 444 | 
            +
                  #   # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
         | 
| 445 | 
            +
                  def column_for_attribute(name)
         | 
| 446 | 
            +
                    name = name.to_s
         | 
| 447 | 
            +
                    columns_hash.fetch(name) do
         | 
| 448 | 
            +
                      ConnectionAdapters::NullColumn.new(name)
         | 
| 449 | 
            +
                    end
         | 
| 450 | 
            +
                  end
         | 
| 451 | 
            +
             | 
| 374 452 | 
             
                  # Returns a hash where the keys are column names and the values are
         | 
| 375 453 | 
             
                  # default values when instantiating the Active Record object for this table.
         | 
| 376 454 | 
             
                  def column_defaults
         | 
| 377 455 | 
             
                    load_schema
         | 
| 378 | 
            -
                    @column_defaults ||= _default_attributes.deep_dup.to_hash
         | 
| 456 | 
            +
                    @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
         | 
| 379 457 | 
             
                  end
         | 
| 380 458 |  | 
| 381 459 | 
             
                  def _default_attributes # :nodoc:
         | 
| @@ -385,7 +463,12 @@ module ActiveRecord | |
| 385 463 |  | 
| 386 464 | 
             
                  # Returns an array of column names as strings.
         | 
| 387 465 | 
             
                  def column_names
         | 
| 388 | 
            -
                    @column_names ||= columns.map(&:name)
         | 
| 466 | 
            +
                    @column_names ||= columns.map(&:name).freeze
         | 
| 467 | 
            +
                  end
         | 
| 468 | 
            +
             | 
| 469 | 
            +
                  def symbol_column_to_string(name_symbol) # :nodoc:
         | 
| 470 | 
            +
                    @symbol_column_to_string_name_hash ||= column_names.index_by(&:to_sym)
         | 
| 471 | 
            +
                    @symbol_column_to_string_name_hash[name_symbol]
         | 
| 389 472 | 
             
                  end
         | 
| 390 473 |  | 
| 391 474 | 
             
                  # Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
         | 
| @@ -394,9 +477,8 @@ module ActiveRecord | |
| 394 477 | 
             
                    @content_columns ||= columns.reject do |c|
         | 
| 395 478 | 
             
                      c.name == primary_key ||
         | 
| 396 479 | 
             
                      c.name == inheritance_column ||
         | 
| 397 | 
            -
                      c.name.end_with?("_id") | 
| 398 | 
            -
             | 
| 399 | 
            -
                    end
         | 
| 480 | 
            +
                      c.name.end_with?("_id", "_count")
         | 
| 481 | 
            +
                    end.freeze
         | 
| 400 482 | 
             
                  end
         | 
| 401 483 |  | 
| 402 484 | 
             
                  # Resets all the cached information about columns, which will cause them
         | 
| @@ -406,7 +488,7 @@ module ActiveRecord | |
| 406 488 | 
             
                  # when just after creating a table you want to populate it with some default
         | 
| 407 489 | 
             
                  # values, eg:
         | 
| 408 490 | 
             
                  #
         | 
| 409 | 
            -
                  #  class CreateJobLevels < ActiveRecord::Migration[ | 
| 491 | 
            +
                  #  class CreateJobLevels < ActiveRecord::Migration[6.0]
         | 
| 410 492 | 
             
                  #    def up
         | 
| 411 493 | 
             
                  #      create_table :job_levels do |t|
         | 
| 412 494 | 
             
                  #        t.integer :id
         | 
| @@ -435,13 +517,11 @@ module ActiveRecord | |
| 435 517 | 
             
                  end
         | 
| 436 518 |  | 
| 437 519 | 
             
                  protected
         | 
| 438 | 
            -
             | 
| 439 520 | 
             
                    def initialize_load_schema_monitor
         | 
| 440 521 | 
             
                      @load_schema_monitor = Monitor.new
         | 
| 441 522 | 
             
                    end
         | 
| 442 523 |  | 
| 443 524 | 
             
                  private
         | 
| 444 | 
            -
             | 
| 445 525 | 
             
                    def inherited(child_class)
         | 
| 446 526 | 
             
                      super
         | 
| 447 527 | 
             
                      child_class.initialize_load_schema_monitor
         | 
| @@ -459,15 +539,27 @@ module ActiveRecord | |
| 459 539 | 
             
                        load_schema!
         | 
| 460 540 |  | 
| 461 541 | 
             
                        @schema_loaded = true
         | 
| 542 | 
            +
                      rescue
         | 
| 543 | 
            +
                        reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
         | 
| 544 | 
            +
                        raise
         | 
| 462 545 | 
             
                      end
         | 
| 463 546 | 
             
                    end
         | 
| 464 547 |  | 
| 465 548 | 
             
                    def load_schema!
         | 
| 466 | 
            -
                       | 
| 549 | 
            +
                      unless table_name
         | 
| 550 | 
            +
                        raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
         | 
| 551 | 
            +
                      end
         | 
| 552 | 
            +
             | 
| 553 | 
            +
                      columns_hash = connection.schema_cache.columns_hash(table_name)
         | 
| 554 | 
            +
                      columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
         | 
| 555 | 
            +
                      @columns_hash = columns_hash.freeze
         | 
| 467 556 | 
             
                      @columns_hash.each do |name, column|
         | 
| 557 | 
            +
                        type = connection.lookup_cast_type_from_column(column)
         | 
| 558 | 
            +
                        type = _convert_type_from_options(type)
         | 
| 559 | 
            +
                        warn_if_deprecated_type(column)
         | 
| 468 560 | 
             
                        define_attribute(
         | 
| 469 561 | 
             
                          name,
         | 
| 470 | 
            -
                           | 
| 562 | 
            +
                          type,
         | 
| 471 563 | 
             
                          default: column.default,
         | 
| 472 564 | 
             
                          user_provided_default: false
         | 
| 473 565 | 
             
                        )
         | 
| @@ -477,6 +569,7 @@ module ActiveRecord | |
| 477 569 | 
             
                    def reload_schema_from_cache
         | 
| 478 570 | 
             
                      @arel_table = nil
         | 
| 479 571 | 
             
                      @column_names = nil
         | 
| 572 | 
            +
                      @symbol_column_to_string_name_hash = nil
         | 
| 480 573 | 
             
                      @attribute_types = nil
         | 
| 481 574 | 
             
                      @content_columns = nil
         | 
| 482 575 | 
             
                      @default_attributes = nil
         | 
| @@ -501,19 +594,52 @@ module ActiveRecord | |
| 501 594 |  | 
| 502 595 | 
             
                    # Computes and returns a table name according to default conventions.
         | 
| 503 596 | 
             
                    def compute_table_name
         | 
| 504 | 
            -
                       | 
| 505 | 
            -
                      if self == base
         | 
| 597 | 
            +
                      if base_class?
         | 
| 506 598 | 
             
                        # Nested classes are prefixed with singular parent table name.
         | 
| 507 | 
            -
                        if  | 
| 508 | 
            -
                          contained =  | 
| 509 | 
            -
                          contained = contained.singularize if  | 
| 599 | 
            +
                        if module_parent < Base && !module_parent.abstract_class?
         | 
| 600 | 
            +
                          contained = module_parent.table_name
         | 
| 601 | 
            +
                          contained = contained.singularize if module_parent.pluralize_table_names
         | 
| 510 602 | 
             
                          contained += "_"
         | 
| 511 603 | 
             
                        end
         | 
| 512 604 |  | 
| 513 605 | 
             
                        "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
         | 
| 514 606 | 
             
                      else
         | 
| 515 607 | 
             
                        # STI subclasses always use their superclass' table.
         | 
| 516 | 
            -
                         | 
| 608 | 
            +
                        base_class.table_name
         | 
| 609 | 
            +
                      end
         | 
| 610 | 
            +
                    end
         | 
| 611 | 
            +
             | 
| 612 | 
            +
                    def _convert_type_from_options(type)
         | 
| 613 | 
            +
                      if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
         | 
| 614 | 
            +
                        type.to_immutable_string
         | 
| 615 | 
            +
                      else
         | 
| 616 | 
            +
                        type
         | 
| 617 | 
            +
                      end
         | 
| 618 | 
            +
                    end
         | 
| 619 | 
            +
             | 
| 620 | 
            +
                    def warn_if_deprecated_type(column)
         | 
| 621 | 
            +
                      return if attributes_to_define_after_schema_loads.key?(column.name)
         | 
| 622 | 
            +
                      return unless column.respond_to?(:oid)
         | 
| 623 | 
            +
             | 
| 624 | 
            +
                      if column.array?
         | 
| 625 | 
            +
                        array_arguments = ", array: true"
         | 
| 626 | 
            +
                      else
         | 
| 627 | 
            +
                        array_arguments = ""
         | 
| 628 | 
            +
                      end
         | 
| 629 | 
            +
             | 
| 630 | 
            +
                      if column.sql_type.start_with?("interval")
         | 
| 631 | 
            +
                        precision_arguments = column.precision.presence && ", precision: #{column.precision}"
         | 
| 632 | 
            +
                        ActiveSupport::Deprecation.warn(<<~WARNING)
         | 
| 633 | 
            +
                          The behavior of the `:interval` type will be changing in Rails 6.2
         | 
| 634 | 
            +
                          to return an `ActiveSupport::Duration` object. If you'd like to keep
         | 
| 635 | 
            +
                          the old behavior, you can add this line to #{self.name} model:
         | 
| 636 | 
            +
             | 
| 637 | 
            +
                            attribute :#{column.name}, :string#{precision_arguments}#{array_arguments}
         | 
| 638 | 
            +
             | 
| 639 | 
            +
                          If you'd like the new behavior today, you can add this line:
         | 
| 640 | 
            +
             | 
| 641 | 
            +
                            attribute :#{column.name}, :interval#{precision_arguments}#{array_arguments}
         | 
| 642 | 
            +
                        WARNING
         | 
| 517 643 | 
             
                      end
         | 
| 518 644 | 
             
                    end
         | 
| 519 645 | 
             
                end
         | 
| @@ -2,7 +2,6 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require "active_support/core_ext/hash/except"
         | 
| 4 4 | 
             
            require "active_support/core_ext/module/redefine_method"
         | 
| 5 | 
            -
            require "active_support/core_ext/object/try"
         | 
| 6 5 | 
             
            require "active_support/core_ext/hash/indifferent_access"
         | 
| 7 6 |  | 
| 8 7 | 
             
            module ActiveRecord
         | 
| @@ -289,7 +288,7 @@ module ActiveRecord | |
| 289 288 | 
             
                  # [:allow_destroy]
         | 
| 290 289 | 
             
                  #   If true, destroys any members from the attributes hash with a
         | 
| 291 290 | 
             
                  #   <tt>_destroy</tt> key and a value that evaluates to +true+
         | 
| 292 | 
            -
                  #   ( | 
| 291 | 
            +
                  #   (e.g. 1, '1', true, or 'true'). This option is off by default.
         | 
| 293 292 | 
             
                  # [:reject_if]
         | 
| 294 293 | 
             
                  #   Allows you to specify a Proc or a Symbol pointing to a method
         | 
| 295 294 | 
             
                  #   that checks whether a record should be built for a certain attribute
         | 
| @@ -354,7 +353,6 @@ module ActiveRecord | |
| 354 353 | 
             
                  end
         | 
| 355 354 |  | 
| 356 355 | 
             
                  private
         | 
| 357 | 
            -
             | 
| 358 356 | 
             
                    # Generates a writer method for this association. Serves as a point for
         | 
| 359 357 | 
             
                    # accessing the objects in the association. For example, this method
         | 
| 360 358 | 
             
                    # could generate the following:
         | 
| @@ -386,7 +384,6 @@ module ActiveRecord | |
| 386 384 | 
             
                end
         | 
| 387 385 |  | 
| 388 386 | 
             
                private
         | 
| 389 | 
            -
             | 
| 390 387 | 
             
                  # Attribute hash keys that should not be assigned as normal attributes.
         | 
| 391 388 | 
             
                  # These hash keys are nested attributes implementation details.
         | 
| 392 389 | 
             
                  UNASSIGNABLE_KEYS = %w( id _destroy )
         | 
| @@ -426,7 +423,7 @@ module ActiveRecord | |
| 426 423 | 
             
                        existing_record.assign_attributes(assignable_attributes)
         | 
| 427 424 | 
             
                        association(association_name).initialize_attributes(existing_record)
         | 
| 428 425 | 
             
                      else
         | 
| 429 | 
            -
                        method = "build_#{association_name}"
         | 
| 426 | 
            +
                        method = :"build_#{association_name}"
         | 
| 430 427 | 
             
                        if respond_to?(method)
         | 
| 431 428 | 
             
                          send(method, assignable_attributes)
         | 
| 432 429 | 
             
                        else
         | 
| @@ -501,7 +498,7 @@ module ActiveRecord | |
| 501 498 |  | 
| 502 499 | 
             
                      if attributes["id"].blank?
         | 
| 503 500 | 
             
                        unless reject_new_record?(association_name, attributes)
         | 
| 504 | 
            -
                          association.build(attributes.except(*UNASSIGNABLE_KEYS))
         | 
| 501 | 
            +
                          association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
         | 
| 505 502 | 
             
                        end
         | 
| 506 503 | 
             
                      elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes["id"].to_s }
         | 
| 507 504 | 
             
                        unless call_reject_if(association_name, attributes)
         | 
| @@ -512,7 +509,7 @@ module ActiveRecord | |
| 512 509 | 
             
                          if target_record
         | 
| 513 510 | 
             
                            existing_record = target_record
         | 
| 514 511 | 
             
                          else
         | 
| 515 | 
            -
                            association.add_to_target(existing_record, : | 
| 512 | 
            +
                            association.add_to_target(existing_record, skip_callbacks: true)
         | 
| 516 513 | 
             
                          end
         | 
| 517 514 |  | 
| 518 515 | 
             
                          assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
         | 
| @@ -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
         | 
| @@ -51,7 +58,7 @@ module ActiveRecord | |
| 51 58 | 
             
                  super unless no_touching?
         | 
| 52 59 | 
             
                end
         | 
| 53 60 |  | 
| 54 | 
            -
                def touch( | 
| 61 | 
            +
                def touch(*, **) # :nodoc:
         | 
| 55 62 | 
             
                  super unless no_touching?
         | 
| 56 63 | 
             
                end
         | 
| 57 64 | 
             
              end
         |