activerecord 4.2.0 → 6.1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1221 -796
- data/MIT-LICENSE +4 -2
- data/README.rdoc +15 -14
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +267 -249
- data/lib/active_record/association_relation.rb +45 -7
- data/lib/active_record/associations/alias_tracker.rb +40 -43
- data/lib/active_record/associations/association.rb +172 -67
- data/lib/active_record/associations/association_scope.rb +105 -129
- data/lib/active_record/associations/belongs_to_association.rb +85 -59
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +57 -43
- data/lib/active_record/associations/builder/belongs_to.rb +74 -57
- data/lib/active_record/associations/builder/collection_association.rb +15 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
- data/lib/active_record/associations/builder/has_many.rb +13 -5
- data/lib/active_record/associations/builder/has_one.rb +44 -6
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +168 -279
- data/lib/active_record/associations/collection_proxy.rb +263 -155
- data/lib/active_record/associations/foreign_association.rb +33 -0
- data/lib/active_record/associations/has_many_association.rb +57 -84
- data/lib/active_record/associations/has_many_through_association.rb +70 -82
- data/lib/active_record/associations/has_one_association.rb +74 -47
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/join_dependency.rb +175 -164
- data/lib/active_record/associations/preloader/association.rb +107 -112
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +99 -96
- data/lib/active_record/associations/singular_association.rb +18 -45
- data/lib/active_record/associations/through_association.rb +49 -24
- data/lib/active_record/associations.rb +1845 -1597
- data/lib/active_record/attribute_assignment.rb +59 -185
- data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
- data/lib/active_record/attribute_methods/dirty.rb +168 -138
- data/lib/active_record/attribute_methods/primary_key.rb +93 -83
- data/lib/active_record/attribute_methods/query.rb +8 -10
- data/lib/active_record/attribute_methods/read.rb +19 -79
- data/lib/active_record/attribute_methods/serialization.rb +49 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
- data/lib/active_record/attribute_methods/write.rb +25 -56
- data/lib/active_record/attribute_methods.rb +153 -162
- data/lib/active_record/attributes.rb +234 -70
- data/lib/active_record/autosave_association.rb +157 -69
- data/lib/active_record/base.rb +49 -50
- data/lib/active_record/callbacks.rb +234 -79
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +46 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
- data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
- data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
- data/lib/active_record/connection_adapters/column.rb +67 -40
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
- data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +314 -41
- data/lib/active_record/core.rb +488 -243
- data/lib/active_record/counter_cache.rb +71 -50
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -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 +273 -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 +87 -106
- data/lib/active_record/enum.rb +212 -94
- data/lib/active_record/errors.rb +225 -54
- data/lib/active_record/explain.rb +27 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +33 -14
- 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 +273 -496
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +175 -110
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +121 -29
- data/lib/active_record/internal_metadata.rb +64 -0
- data/lib/active_record/legacy_yaml_adapter.rb +52 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +103 -95
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +93 -31
- 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 +185 -90
- data/lib/active_record/migration/compatibility.rb +298 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +685 -309
- data/lib/active_record/model_schema.rb +420 -113
- data/lib/active_record/nested_attributes.rb +265 -216
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +574 -135
- data/lib/active_record/query_cache.rb +29 -23
- data/lib/active_record/querying.rb +50 -31
- data/lib/active_record/railtie.rb +175 -54
- data/lib/active_record/railties/console_sandbox.rb +3 -3
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +533 -216
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +485 -310
- data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
- data/lib/active_record/relation/batches.rb +217 -59
- data/lib/active_record/relation/calculations.rb +326 -244
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +318 -256
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +99 -84
- data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +139 -96
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +757 -409
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +23 -21
- data/lib/active_record/relation/where_clause.rb +239 -0
- data/lib/active_record/relation.rb +554 -342
- data/lib/active_record/result.rb +91 -47
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +134 -122
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +141 -92
- data/lib/active_record/schema_migration.rb +24 -26
- data/lib/active_record/scoping/default.rb +96 -82
- data/lib/active_record/scoping/named.rb +78 -36
- data/lib/active_record/scoping.rb +45 -27
- data/lib/active_record/secure_token.rb +48 -0
- data/lib/active_record/serialization.rb +8 -6
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +89 -36
- data/lib/active_record/store.rb +133 -43
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +81 -0
- data/lib/active_record/tasks/database_tasks.rb +366 -129
- data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
- data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +291 -0
- data/lib/active_record/timestamp.rb +86 -43
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +181 -152
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +126 -0
- data/lib/active_record/type/date.rb +4 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +33 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +21 -16
- data/lib/active_record/type/type_map.rb +16 -19
- data/lib/active_record/type/unsigned_integer.rb +9 -8
- data/lib/active_record/type.rb +84 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +12 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +65 -48
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +44 -28
- 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 +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +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 +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
- data/lib/rails/generators/active_record/migration.rb +35 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
- 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 +22 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +175 -65
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -149
- data/lib/active_record/attribute_decorators.rb +0 -66
- data/lib/active_record/attribute_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -30
- data/lib/active_record/type/decimal.rb +0 -40
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -55
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
data/lib/active_record/core.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/enumerable"
|
4
|
+
require "active_support/core_ext/hash/indifferent_access"
|
5
|
+
require "active_support/core_ext/string/filters"
|
6
|
+
require "active_support/parameter_filter"
|
7
|
+
require "concurrent/map"
|
5
8
|
|
6
9
|
module ActiveRecord
|
7
10
|
module Core
|
@@ -16,9 +19,28 @@ module ActiveRecord
|
|
16
19
|
# retrieved on both a class and instance level by calling +logger+.
|
17
20
|
mattr_accessor :logger, instance_writer: false
|
18
21
|
|
22
|
+
##
|
23
|
+
# :singleton-method:
|
24
|
+
#
|
25
|
+
# Specifies if the methods calling database queries should be logged below
|
26
|
+
# their relevant queries. Defaults to false.
|
27
|
+
mattr_accessor :verbose_query_logs, instance_writer: false, default: false
|
28
|
+
|
29
|
+
##
|
30
|
+
# :singleton-method:
|
31
|
+
#
|
32
|
+
# Specifies the names of the queues used by background jobs.
|
33
|
+
mattr_accessor :queues, instance_accessor: false, default: {}
|
34
|
+
|
35
|
+
##
|
36
|
+
# :singleton-method:
|
37
|
+
#
|
38
|
+
# Specifies the job used to destroy associations in the background
|
39
|
+
class_attribute :destroy_association_async_job, instance_writer: false, instance_predicate: false, default: false
|
40
|
+
|
19
41
|
##
|
20
42
|
# Contains the database configuration - as is typically stored in config/database.yml -
|
21
|
-
# as
|
43
|
+
# as an ActiveRecord::DatabaseConfigurations object.
|
22
44
|
#
|
23
45
|
# For example, the following database.yml...
|
24
46
|
#
|
@@ -32,22 +54,18 @@ module ActiveRecord
|
|
32
54
|
#
|
33
55
|
# ...would result in ActiveRecord::Base.configurations to look like this:
|
34
56
|
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
# 'adapter' => 'sqlite3',
|
42
|
-
# 'database' => 'db/production.sqlite3'
|
43
|
-
# }
|
44
|
-
# }
|
57
|
+
# #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
|
58
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
|
59
|
+
# @name="primary", @config={adapter: "sqlite3", database: "db/development.sqlite3"}>,
|
60
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
|
61
|
+
# @name="primary", @config={adapter: "sqlite3", database: "db/production.sqlite3"}>
|
62
|
+
# ]>
|
45
63
|
def self.configurations=(config)
|
46
|
-
@@configurations = ActiveRecord::
|
64
|
+
@@configurations = ActiveRecord::DatabaseConfigurations.new(config)
|
47
65
|
end
|
48
66
|
self.configurations = {}
|
49
67
|
|
50
|
-
# Returns fully resolved
|
68
|
+
# Returns fully resolved ActiveRecord::DatabaseConfigurations object
|
51
69
|
def self.configurations
|
52
70
|
@@configurations
|
53
71
|
end
|
@@ -56,8 +74,7 @@ module ActiveRecord
|
|
56
74
|
# :singleton-method:
|
57
75
|
# Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
|
58
76
|
# dates and times from the database. This is set to :utc by default.
|
59
|
-
mattr_accessor :default_timezone, instance_writer: false
|
60
|
-
self.default_timezone = :utc
|
77
|
+
mattr_accessor :default_timezone, instance_writer: false, default: :utc
|
61
78
|
|
62
79
|
##
|
63
80
|
# :singleton-method:
|
@@ -67,148 +84,363 @@ module ActiveRecord
|
|
67
84
|
# ActiveRecord::Schema file which can be loaded into any database that
|
68
85
|
# supports migrations. Use :ruby if you want to have different database
|
69
86
|
# adapters for, e.g., your development and test environments.
|
70
|
-
mattr_accessor :schema_format, instance_writer: false
|
71
|
-
|
87
|
+
mattr_accessor :schema_format, instance_writer: false, default: :ruby
|
88
|
+
|
89
|
+
##
|
90
|
+
# :singleton-method:
|
91
|
+
# Specifies if an error should be raised if the query has an order being
|
92
|
+
# ignored when doing batch queries. Useful in applications where the
|
93
|
+
# scope being ignored is error-worthy, rather than a warning.
|
94
|
+
mattr_accessor :error_on_ignored_order, instance_writer: false, default: false
|
72
95
|
|
73
96
|
##
|
74
97
|
# :singleton-method:
|
75
98
|
# Specify whether or not to use timestamps for migration versions
|
76
|
-
mattr_accessor :timestamped_migrations, instance_writer: false
|
77
|
-
self.timestamped_migrations = true
|
99
|
+
mattr_accessor :timestamped_migrations, instance_writer: false, default: true
|
78
100
|
|
79
101
|
##
|
80
102
|
# :singleton-method:
|
81
103
|
# Specify whether schema dump should happen at the end of the
|
82
|
-
# db:migrate
|
104
|
+
# db:migrate rails command. This is true by default, which is useful for the
|
83
105
|
# development environment. This should ideally be false in the production
|
84
106
|
# environment where dumping schema is rarely needed.
|
85
|
-
mattr_accessor :dump_schema_after_migration, instance_writer: false
|
86
|
-
|
107
|
+
mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true
|
108
|
+
|
109
|
+
##
|
110
|
+
# :singleton-method:
|
111
|
+
# Specifies which database schemas to dump when calling db:schema:dump.
|
112
|
+
# If the value is :schema_search_path (the default), any schemas listed in
|
113
|
+
# schema_search_path are dumped. Use :all to dump all schemas regardless
|
114
|
+
# of schema_search_path, or a string of comma separated schemas for a
|
115
|
+
# custom list.
|
116
|
+
mattr_accessor :dump_schemas, instance_writer: false, default: :schema_search_path
|
117
|
+
|
118
|
+
##
|
119
|
+
# :singleton-method:
|
120
|
+
# Specify a threshold for the size of query result sets. If the number of
|
121
|
+
# records in the set exceeds the threshold, a warning is logged. This can
|
122
|
+
# be used to identify queries which load thousands of records and
|
123
|
+
# potentially cause memory bloat.
|
124
|
+
mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
|
125
|
+
|
126
|
+
##
|
127
|
+
# :singleton-method:
|
128
|
+
# Show a warning when Rails couldn't parse your database.yml
|
129
|
+
# for multiple databases.
|
130
|
+
mattr_accessor :suppress_multiple_database_warning, instance_writer: false, default: false
|
87
131
|
|
88
132
|
mattr_accessor :maintain_test_schema, instance_accessor: false
|
89
133
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
134
|
+
class_attribute :belongs_to_required_by_default, instance_accessor: false
|
135
|
+
|
136
|
+
##
|
137
|
+
# :singleton-method:
|
138
|
+
# Set the application to log or raise when an association violates strict loading.
|
139
|
+
# Defaults to :raise.
|
140
|
+
mattr_accessor :action_on_strict_loading_violation, instance_accessor: false, default: :raise
|
141
|
+
|
142
|
+
class_attribute :strict_loading_by_default, instance_accessor: false, default: false
|
143
|
+
|
144
|
+
mattr_accessor :writing_role, instance_accessor: false, default: :writing
|
145
|
+
|
146
|
+
mattr_accessor :reading_role, instance_accessor: false, default: :reading
|
147
|
+
|
148
|
+
mattr_accessor :has_many_inversing, instance_accessor: false, default: false
|
96
149
|
|
97
150
|
class_attribute :default_connection_handler, instance_writer: false
|
98
|
-
|
151
|
+
|
152
|
+
class_attribute :default_role, instance_writer: false
|
153
|
+
|
154
|
+
class_attribute :default_shard, instance_writer: false
|
155
|
+
|
156
|
+
mattr_accessor :legacy_connection_handling, instance_writer: false, default: true
|
157
|
+
|
158
|
+
# Application configurable boolean that instructs the YAML Coder to use
|
159
|
+
# an unsafe load if set to true.
|
160
|
+
mattr_accessor :use_yaml_unsafe_load, instance_writer: false, default: false
|
161
|
+
|
162
|
+
# Application configurable array that provides additional permitted classes
|
163
|
+
# to Psych safe_load in the YAML Coder
|
164
|
+
mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: [Symbol]
|
165
|
+
|
166
|
+
##
|
167
|
+
# :singleton-method:
|
168
|
+
# Application configurable boolean that denotes whether or not to raise
|
169
|
+
# an exception when the PostgreSQLAdapter is provided with an integer that is
|
170
|
+
# wider than signed 64bit representation
|
171
|
+
mattr_accessor :raise_int_wider_than_64bit, instance_writer: false, default: true
|
172
|
+
|
173
|
+
self.filter_attributes = []
|
99
174
|
|
100
175
|
def self.connection_handler
|
101
|
-
|
176
|
+
Thread.current.thread_variable_get(:ar_connection_handler) || default_connection_handler
|
102
177
|
end
|
103
178
|
|
104
179
|
def self.connection_handler=(handler)
|
105
|
-
|
180
|
+
Thread.current.thread_variable_set(:ar_connection_handler, handler)
|
181
|
+
end
|
182
|
+
|
183
|
+
def self.connection_handlers
|
184
|
+
unless legacy_connection_handling
|
185
|
+
raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
|
186
|
+
end
|
187
|
+
|
188
|
+
@@connection_handlers ||= {}
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.connection_handlers=(handlers)
|
192
|
+
unless legacy_connection_handling
|
193
|
+
raise NotImplementedError, "The new connection handling does not setting support multiple connection handlers."
|
194
|
+
end
|
195
|
+
|
196
|
+
@@connection_handlers = handlers
|
197
|
+
end
|
198
|
+
|
199
|
+
# Returns the symbol representing the current connected role.
|
200
|
+
#
|
201
|
+
# ActiveRecord::Base.connected_to(role: :writing) do
|
202
|
+
# ActiveRecord::Base.current_role #=> :writing
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
206
|
+
# ActiveRecord::Base.current_role #=> :reading
|
207
|
+
# end
|
208
|
+
def self.current_role
|
209
|
+
if ActiveRecord::Base.legacy_connection_handling
|
210
|
+
connection_handlers.key(connection_handler) || default_role
|
211
|
+
else
|
212
|
+
connected_to_stack.reverse_each do |hash|
|
213
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
|
214
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_classes)
|
215
|
+
end
|
216
|
+
|
217
|
+
default_role
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Returns the symbol representing the current connected shard.
|
222
|
+
#
|
223
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
224
|
+
# ActiveRecord::Base.current_shard #=> :default
|
225
|
+
# end
|
226
|
+
#
|
227
|
+
# ActiveRecord::Base.connected_to(role: :writing, shard: :one) do
|
228
|
+
# ActiveRecord::Base.current_shard #=> :one
|
229
|
+
# end
|
230
|
+
def self.current_shard
|
231
|
+
connected_to_stack.reverse_each do |hash|
|
232
|
+
return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
|
233
|
+
return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_classes)
|
234
|
+
end
|
235
|
+
|
236
|
+
default_shard
|
237
|
+
end
|
238
|
+
|
239
|
+
# Returns the symbol representing the current setting for
|
240
|
+
# preventing writes.
|
241
|
+
#
|
242
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
243
|
+
# ActiveRecord::Base.current_preventing_writes #=> true
|
244
|
+
# end
|
245
|
+
#
|
246
|
+
# ActiveRecord::Base.connected_to(role: :writing) do
|
247
|
+
# ActiveRecord::Base.current_preventing_writes #=> false
|
248
|
+
# end
|
249
|
+
def self.current_preventing_writes
|
250
|
+
if legacy_connection_handling
|
251
|
+
connection_handler.prevent_writes
|
252
|
+
else
|
253
|
+
connected_to_stack.reverse_each do |hash|
|
254
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
|
255
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_classes)
|
256
|
+
end
|
257
|
+
|
258
|
+
false
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def self.connected_to_stack # :nodoc:
|
263
|
+
if connected_to_stack = Thread.current.thread_variable_get(:ar_connected_to_stack)
|
264
|
+
connected_to_stack
|
265
|
+
else
|
266
|
+
connected_to_stack = Concurrent::Array.new
|
267
|
+
Thread.current.thread_variable_set(:ar_connected_to_stack, connected_to_stack)
|
268
|
+
connected_to_stack
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def self.connection_class=(b) # :nodoc:
|
273
|
+
@connection_class = b
|
274
|
+
end
|
275
|
+
|
276
|
+
def self.connection_class # :nodoc
|
277
|
+
@connection_class ||= false
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.connection_class? # :nodoc:
|
281
|
+
self.connection_class
|
282
|
+
end
|
283
|
+
|
284
|
+
def self.connection_classes # :nodoc:
|
285
|
+
klass = self
|
286
|
+
|
287
|
+
until klass == Base
|
288
|
+
break if klass.connection_class?
|
289
|
+
klass = klass.superclass
|
290
|
+
end
|
291
|
+
|
292
|
+
klass
|
293
|
+
end
|
294
|
+
|
295
|
+
def self.allow_unsafe_raw_sql # :nodoc:
|
296
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails 7.0")
|
297
|
+
end
|
298
|
+
|
299
|
+
def self.allow_unsafe_raw_sql=(value) # :nodoc:
|
300
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails 7.0")
|
106
301
|
end
|
107
302
|
|
108
303
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
304
|
+
self.default_role = writing_role
|
305
|
+
self.default_shard = :default
|
306
|
+
|
307
|
+
def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
|
308
|
+
case action_on_strict_loading_violation
|
309
|
+
when :raise
|
310
|
+
message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
|
311
|
+
raise ActiveRecord::StrictLoadingViolationError.new(message)
|
312
|
+
when :log
|
313
|
+
name = "strict_loading_violation.active_record"
|
314
|
+
ActiveSupport::Notifications.instrument(name, owner: owner, reflection: reflection)
|
315
|
+
end
|
316
|
+
end
|
109
317
|
end
|
110
318
|
|
111
319
|
module ClassMethods
|
112
|
-
def
|
113
|
-
|
114
|
-
super
|
115
|
-
end
|
116
|
-
|
117
|
-
def initialize_find_by_cache
|
118
|
-
self.find_by_statement_cache = {}.extend(Mutex_m)
|
320
|
+
def initialize_find_by_cache # :nodoc:
|
321
|
+
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
119
322
|
end
|
120
323
|
|
121
|
-
def inherited(child_class)
|
324
|
+
def inherited(child_class) # :nodoc:
|
325
|
+
# initialize cache at class definition for thread safety
|
122
326
|
child_class.initialize_find_by_cache
|
327
|
+
unless child_class.base_class?
|
328
|
+
klass = self
|
329
|
+
until klass.base_class?
|
330
|
+
klass.initialize_find_by_cache
|
331
|
+
klass = klass.superclass
|
332
|
+
end
|
333
|
+
end
|
123
334
|
super
|
124
335
|
end
|
125
336
|
|
126
|
-
def find(*ids)
|
337
|
+
def find(*ids) # :nodoc:
|
127
338
|
# We don't have cache keys for this stuff yet
|
128
339
|
return super unless ids.length == 1
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
ids.first.kind_of?(Array)
|
136
|
-
|
137
|
-
id = ids.first
|
138
|
-
if ActiveRecord::Base === id
|
139
|
-
id = id.id
|
140
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
141
|
-
You are passing an instance of ActiveRecord::Base to `find`.
|
142
|
-
Please pass the id of the object by calling `.id`
|
143
|
-
MSG
|
144
|
-
end
|
340
|
+
return super if block_given? || primary_key.nil? || scope_attributes?
|
341
|
+
|
342
|
+
id = ids.first
|
343
|
+
|
344
|
+
return super if StatementCache.unsupported_value?(id)
|
345
|
+
|
145
346
|
key = primary_key
|
146
347
|
|
147
|
-
|
148
|
-
|
149
|
-
where(key => params.bind).limit(1)
|
150
|
-
}
|
348
|
+
statement = cached_find_by_statement(key) { |params|
|
349
|
+
where(key => params.bind).limit(1)
|
151
350
|
}
|
152
|
-
|
153
|
-
|
154
|
-
raise
|
155
|
-
end
|
156
|
-
record
|
157
|
-
rescue RangeError
|
158
|
-
raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
|
351
|
+
|
352
|
+
statement.execute([id], connection).first ||
|
353
|
+
raise(RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id))
|
159
354
|
end
|
160
355
|
|
161
|
-
def find_by(*args)
|
162
|
-
return super if
|
163
|
-
return super if default_scopes.any?
|
356
|
+
def find_by(*args) # :nodoc:
|
357
|
+
return super if scope_attributes?
|
164
358
|
|
165
359
|
hash = args.first
|
360
|
+
return super unless Hash === hash
|
166
361
|
|
167
|
-
|
168
|
-
|
169
|
-
|
362
|
+
hash = hash.each_with_object({}) do |(key, value), h|
|
363
|
+
key = key.to_s
|
364
|
+
key = attribute_aliases[key] || key
|
170
365
|
|
171
|
-
|
172
|
-
return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
|
366
|
+
return super if reflect_on_aggregation(key)
|
173
367
|
|
174
|
-
|
368
|
+
reflection = _reflect_on_association(key)
|
175
369
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
370
|
+
if !reflection
|
371
|
+
value = value.id if value.respond_to?(:id)
|
372
|
+
elsif reflection.belongs_to? && !reflection.polymorphic?
|
373
|
+
key = reflection.join_foreign_key
|
374
|
+
pkey = reflection.join_primary_key
|
375
|
+
value = value.public_send(pkey) if value.respond_to?(pkey)
|
376
|
+
end
|
377
|
+
|
378
|
+
if !columns_hash.key?(key) || StatementCache.unsupported_value?(value)
|
379
|
+
return super
|
380
|
+
end
|
381
|
+
|
382
|
+
h[key] = value
|
383
|
+
end
|
384
|
+
|
385
|
+
keys = hash.keys
|
386
|
+
statement = cached_find_by_statement(keys) { |params|
|
387
|
+
wheres = keys.index_with { params.bind }
|
388
|
+
where(wheres).limit(1)
|
184
389
|
}
|
390
|
+
|
185
391
|
begin
|
186
|
-
|
187
|
-
rescue TypeError
|
188
|
-
raise ActiveRecord::StatementInvalid
|
189
|
-
rescue RangeError
|
190
|
-
nil
|
392
|
+
statement.execute(hash.values, connection).first
|
393
|
+
rescue TypeError
|
394
|
+
raise ActiveRecord::StatementInvalid
|
191
395
|
end
|
192
396
|
end
|
193
397
|
|
194
|
-
def find_by!(*args)
|
195
|
-
find_by(*args)
|
398
|
+
def find_by!(*args) # :nodoc:
|
399
|
+
find_by(*args) || raise(RecordNotFound.new("Couldn't find #{name}", name))
|
196
400
|
end
|
197
401
|
|
198
|
-
def initialize_generated_modules
|
402
|
+
def initialize_generated_modules # :nodoc:
|
199
403
|
generated_association_methods
|
200
404
|
end
|
201
405
|
|
202
|
-
def generated_association_methods
|
406
|
+
def generated_association_methods # :nodoc:
|
203
407
|
@generated_association_methods ||= begin
|
204
408
|
mod = const_set(:GeneratedAssociationMethods, Module.new)
|
409
|
+
private_constant :GeneratedAssociationMethods
|
205
410
|
include mod
|
411
|
+
|
206
412
|
mod
|
207
413
|
end
|
208
414
|
end
|
209
415
|
|
416
|
+
# Returns columns which shouldn't be exposed while calling +#inspect+.
|
417
|
+
def filter_attributes
|
418
|
+
if defined?(@filter_attributes)
|
419
|
+
@filter_attributes
|
420
|
+
else
|
421
|
+
superclass.filter_attributes
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
# Specifies columns which shouldn't be exposed while calling +#inspect+.
|
426
|
+
def filter_attributes=(filter_attributes)
|
427
|
+
@inspection_filter = nil
|
428
|
+
@filter_attributes = filter_attributes
|
429
|
+
end
|
430
|
+
|
431
|
+
def inspection_filter # :nodoc:
|
432
|
+
if defined?(@filter_attributes)
|
433
|
+
@inspection_filter ||= begin
|
434
|
+
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
435
|
+
ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
|
436
|
+
end
|
437
|
+
else
|
438
|
+
superclass.inspection_filter
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
210
442
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
211
|
-
def inspect
|
443
|
+
def inspect # :nodoc:
|
212
444
|
if self == Base
|
213
445
|
super
|
214
446
|
elsif abstract_class?
|
@@ -216,48 +448,63 @@ module ActiveRecord
|
|
216
448
|
elsif !connected?
|
217
449
|
"#{super} (call '#{super}.connection' to establish a connection)"
|
218
450
|
elsif table_exists?
|
219
|
-
attr_list =
|
451
|
+
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
|
220
452
|
"#{super}(#{attr_list})"
|
221
453
|
else
|
222
454
|
"#{super}(Table doesn't exist)"
|
223
455
|
end
|
224
456
|
end
|
225
457
|
|
226
|
-
# Overwrite the default class equality method to provide support for
|
227
|
-
def ===(object)
|
458
|
+
# Overwrite the default class equality method to provide support for decorated models.
|
459
|
+
def ===(object) # :nodoc:
|
228
460
|
object.is_a?(self)
|
229
461
|
end
|
230
462
|
|
231
463
|
# Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
|
232
464
|
#
|
233
465
|
# class Post < ActiveRecord::Base
|
234
|
-
# scope :published_and_commented, -> { published.and(
|
466
|
+
# scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
|
235
467
|
# end
|
236
468
|
def arel_table # :nodoc:
|
237
|
-
@arel_table ||= Arel::Table.new(table_name,
|
469
|
+
@arel_table ||= Arel::Table.new(table_name, klass: self)
|
238
470
|
end
|
239
471
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
472
|
+
def arel_attribute(name, table = arel_table) # :nodoc:
|
473
|
+
table[name]
|
474
|
+
end
|
475
|
+
deprecate :arel_attribute
|
476
|
+
|
477
|
+
def predicate_builder # :nodoc:
|
478
|
+
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
479
|
+
end
|
480
|
+
|
481
|
+
def type_caster # :nodoc:
|
482
|
+
TypeCaster::Map.new(self)
|
483
|
+
end
|
484
|
+
|
485
|
+
def _internal? # :nodoc:
|
486
|
+
false
|
487
|
+
end
|
488
|
+
|
489
|
+
def cached_find_by_statement(key, &block) # :nodoc:
|
490
|
+
cache = @find_by_statement_cache[connection.prepared_statements]
|
491
|
+
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
248
492
|
end
|
249
493
|
|
250
494
|
private
|
495
|
+
def relation
|
496
|
+
relation = Relation.create(self)
|
251
497
|
|
252
|
-
|
253
|
-
|
498
|
+
if finder_needs_type_condition? && !ignore_default_scope?
|
499
|
+
relation.where!(type_condition)
|
500
|
+
else
|
501
|
+
relation
|
502
|
+
end
|
503
|
+
end
|
254
504
|
|
255
|
-
|
256
|
-
|
257
|
-
else
|
258
|
-
relation
|
505
|
+
def table_metadata
|
506
|
+
TableMetadata.new(self, arel_table)
|
259
507
|
end
|
260
|
-
end
|
261
508
|
end
|
262
509
|
|
263
510
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
@@ -268,39 +515,50 @@ module ActiveRecord
|
|
268
515
|
# ==== Example:
|
269
516
|
# # Instantiates a single new object
|
270
517
|
# User.new(first_name: 'Jamie')
|
271
|
-
def initialize(attributes = nil
|
272
|
-
@
|
518
|
+
def initialize(attributes = nil)
|
519
|
+
@new_record = true
|
520
|
+
@attributes = self.class._default_attributes.deep_dup
|
273
521
|
|
274
522
|
init_internals
|
275
523
|
initialize_internals_callback
|
276
524
|
|
277
|
-
|
278
|
-
# +options+ argument is only needed to make protected_attributes gem easier to hook.
|
279
|
-
# Remove it when we drop support to this gem.
|
280
|
-
init_attributes(attributes, options) if attributes
|
525
|
+
assign_attributes(attributes) if attributes
|
281
526
|
|
282
527
|
yield self if block_given?
|
283
528
|
_run_initialize_callbacks
|
284
529
|
end
|
285
530
|
|
286
|
-
# Initialize an empty model object from +coder+. +coder+
|
287
|
-
# the
|
288
|
-
#
|
531
|
+
# Initialize an empty model object from +coder+. +coder+ should be
|
532
|
+
# the result of previously encoding an Active Record model, using
|
533
|
+
# #encode_with.
|
289
534
|
#
|
290
535
|
# class Post < ActiveRecord::Base
|
291
536
|
# end
|
292
537
|
#
|
538
|
+
# old_post = Post.new(title: "hello world")
|
539
|
+
# coder = {}
|
540
|
+
# old_post.encode_with(coder)
|
541
|
+
#
|
293
542
|
# post = Post.allocate
|
294
|
-
# post.init_with(
|
543
|
+
# post.init_with(coder)
|
295
544
|
# post.title # => 'hello world'
|
296
|
-
def init_with(coder)
|
297
|
-
|
545
|
+
def init_with(coder, &block)
|
546
|
+
coder = LegacyYamlAdapter.convert(self.class, coder)
|
547
|
+
attributes = self.class.yaml_encoder.decode(coder)
|
548
|
+
init_with_attributes(attributes, coder["new_record"], &block)
|
549
|
+
end
|
298
550
|
|
299
|
-
|
551
|
+
##
|
552
|
+
# Initialize an empty model object from +attributes+.
|
553
|
+
# +attributes+ should be an attributes object, and unlike the
|
554
|
+
# `initialize` method, no assignment calls are made per attribute.
|
555
|
+
def init_with_attributes(attributes, new_record = false) # :nodoc:
|
556
|
+
@new_record = new_record
|
557
|
+
@attributes = attributes
|
300
558
|
|
301
|
-
|
559
|
+
init_internals
|
302
560
|
|
303
|
-
self
|
561
|
+
yield self if block_given?
|
304
562
|
|
305
563
|
_run_find_callbacks
|
306
564
|
_run_initialize_callbacks
|
@@ -336,23 +594,22 @@ module ActiveRecord
|
|
336
594
|
|
337
595
|
##
|
338
596
|
def initialize_dup(other) # :nodoc:
|
339
|
-
@attributes = @attributes.
|
340
|
-
@attributes.reset(
|
597
|
+
@attributes = @attributes.deep_dup
|
598
|
+
@attributes.reset(@primary_key)
|
341
599
|
|
342
600
|
_run_initialize_callbacks
|
343
601
|
|
344
|
-
@
|
345
|
-
@
|
346
|
-
|
347
|
-
@
|
348
|
-
@destroyed = false
|
602
|
+
@new_record = true
|
603
|
+
@previously_new_record = false
|
604
|
+
@destroyed = false
|
605
|
+
@_start_transaction_state = nil
|
349
606
|
|
350
607
|
super
|
351
608
|
end
|
352
609
|
|
353
610
|
# Populate +coder+ with attributes about this record that should be
|
354
611
|
# serialized. The structure of +coder+ defined in this method is
|
355
|
-
# guaranteed to match the structure of +coder+ passed to the
|
612
|
+
# guaranteed to match the structure of +coder+ passed to the #init_with
|
356
613
|
# method.
|
357
614
|
#
|
358
615
|
# Example:
|
@@ -363,10 +620,9 @@ module ActiveRecord
|
|
363
620
|
# Post.new.encode_with(coder)
|
364
621
|
# coder # => {"attributes" => {"id" => nil, ... }}
|
365
622
|
def encode_with(coder)
|
366
|
-
|
367
|
-
coder[
|
368
|
-
coder[
|
369
|
-
coder['new_record'] = new_record?
|
623
|
+
self.class.yaml_encoder.encode(@attributes, coder)
|
624
|
+
coder["new_record"] = new_record?
|
625
|
+
coder["active_record_yaml_version"] = 2
|
370
626
|
end
|
371
627
|
|
372
628
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
@@ -390,7 +646,7 @@ module ActiveRecord
|
|
390
646
|
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
391
647
|
def hash
|
392
648
|
if id
|
393
|
-
id.hash
|
649
|
+
self.class.hash ^ id.hash
|
394
650
|
else
|
395
651
|
super
|
396
652
|
end
|
@@ -412,18 +668,41 @@ module ActiveRecord
|
|
412
668
|
# Allows sort on objects
|
413
669
|
def <=>(other_object)
|
414
670
|
if other_object.is_a?(self.class)
|
415
|
-
|
671
|
+
to_key <=> other_object.to_key
|
416
672
|
else
|
417
673
|
super
|
418
674
|
end
|
419
675
|
end
|
420
676
|
|
421
|
-
|
422
|
-
|
677
|
+
def present? # :nodoc:
|
678
|
+
true
|
679
|
+
end
|
680
|
+
|
681
|
+
def blank? # :nodoc:
|
682
|
+
false
|
683
|
+
end
|
684
|
+
|
685
|
+
# Returns +true+ if the record is read only.
|
423
686
|
def readonly?
|
424
687
|
@readonly
|
425
688
|
end
|
426
689
|
|
690
|
+
# Returns +true+ if the record is in strict_loading mode.
|
691
|
+
def strict_loading?
|
692
|
+
@strict_loading
|
693
|
+
end
|
694
|
+
|
695
|
+
# Sets the record to strict_loading mode. This will raise an error
|
696
|
+
# if the record tries to lazily load an association.
|
697
|
+
#
|
698
|
+
# user = User.first
|
699
|
+
# user.strict_loading!
|
700
|
+
# user.comments.to_a
|
701
|
+
# => ActiveRecord::StrictLoadingViolationError
|
702
|
+
def strict_loading!
|
703
|
+
@strict_loading = true
|
704
|
+
end
|
705
|
+
|
427
706
|
# Marks this record as read only.
|
428
707
|
def readonly!
|
429
708
|
@readonly = true
|
@@ -438,129 +717,95 @@ module ActiveRecord
|
|
438
717
|
# We check defined?(@attributes) not to issue warnings if the object is
|
439
718
|
# allocated but not initialized.
|
440
719
|
inspection = if defined?(@attributes) && @attributes
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
720
|
+
self.class.attribute_names.collect do |name|
|
721
|
+
if _has_attribute?(name)
|
722
|
+
"#{name}: #{attribute_for_inspect(name)}"
|
723
|
+
end
|
724
|
+
end.compact.join(", ")
|
725
|
+
else
|
726
|
+
"not initialized"
|
727
|
+
end
|
728
|
+
|
449
729
|
"#<#{self.class} #{inspection}>"
|
450
730
|
end
|
451
731
|
|
452
|
-
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from
|
732
|
+
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
|
453
733
|
# when pp is required.
|
454
734
|
def pretty_print(pp)
|
735
|
+
return super if custom_inspect_method_defined?
|
455
736
|
pp.object_address_group(self) do
|
456
737
|
if defined?(@attributes) && @attributes
|
457
|
-
|
458
|
-
pp.seplist(
|
459
|
-
|
460
|
-
pp.breakable ' '
|
738
|
+
attr_names = self.class.attribute_names.select { |name| _has_attribute?(name) }
|
739
|
+
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
740
|
+
pp.breakable " "
|
461
741
|
pp.group(1) do
|
462
|
-
pp.text
|
463
|
-
pp.text
|
742
|
+
pp.text attr_name
|
743
|
+
pp.text ":"
|
464
744
|
pp.breakable
|
465
|
-
|
745
|
+
value = _read_attribute(attr_name)
|
746
|
+
value = inspection_filter.filter_param(attr_name, value) unless value.nil?
|
747
|
+
pp.pp value
|
466
748
|
end
|
467
749
|
end
|
468
750
|
else
|
469
|
-
pp.breakable
|
470
|
-
pp.text
|
751
|
+
pp.breakable " "
|
752
|
+
pp.text "not initialized"
|
471
753
|
end
|
472
754
|
end
|
473
755
|
end
|
474
756
|
|
475
757
|
# Returns a hash of the given methods with their names as keys and returned values as values.
|
476
758
|
def slice(*methods)
|
477
|
-
|
478
|
-
end
|
479
|
-
|
480
|
-
def set_transaction_state(state) # :nodoc:
|
481
|
-
@transaction_state = state
|
759
|
+
methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
|
482
760
|
end
|
483
761
|
|
484
|
-
|
485
|
-
|
762
|
+
# Returns an array of the values returned by the given methods.
|
763
|
+
def values_at(*methods)
|
764
|
+
methods.flatten.map! { |method| public_send(method) }
|
486
765
|
end
|
487
766
|
|
488
767
|
private
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
#
|
500
|
-
# This method checks to see if the ActiveRecord object's state reflects
|
501
|
-
# the TransactionState, and rolls back or commits the ActiveRecord object
|
502
|
-
# as appropriate.
|
503
|
-
#
|
504
|
-
# Since ActiveRecord objects can be inside multiple transactions, this
|
505
|
-
# method recursively goes through the parent of the TransactionState and
|
506
|
-
# checks if the ActiveRecord object reflects the state of the object.
|
507
|
-
def sync_with_transaction_state
|
508
|
-
update_attributes_from_transaction_state(@transaction_state, 0)
|
509
|
-
end
|
510
|
-
|
511
|
-
def update_attributes_from_transaction_state(transaction_state, depth)
|
512
|
-
if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
|
513
|
-
unless @reflects_state[depth]
|
514
|
-
restore_transaction_record_state if transaction_state.rolledback?
|
515
|
-
clear_transaction_record_state
|
516
|
-
@reflects_state[depth] = true
|
517
|
-
end
|
518
|
-
|
519
|
-
if transaction_state.parent && !@reflects_state[depth+1]
|
520
|
-
update_attributes_from_transaction_state(transaction_state.parent, depth+1)
|
521
|
-
end
|
768
|
+
# +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
|
769
|
+
# the array, and then rescues from the possible +NoMethodError+. If those elements are
|
770
|
+
# +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have,
|
771
|
+
# which significantly impacts upon performance.
|
772
|
+
#
|
773
|
+
# So we can avoid the +method_missing+ hit by explicitly defining +#to_ary+ as +nil+ here.
|
774
|
+
#
|
775
|
+
# See also https://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
|
776
|
+
def to_ary
|
777
|
+
nil
|
522
778
|
end
|
523
|
-
end
|
524
779
|
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
780
|
+
def init_internals
|
781
|
+
@primary_key = self.class.primary_key
|
782
|
+
@readonly = false
|
783
|
+
@previously_new_record = false
|
784
|
+
@destroyed = false
|
785
|
+
@marked_for_destruction = false
|
786
|
+
@destroyed_by_association = nil
|
787
|
+
@_start_transaction_state = nil
|
788
|
+
@strict_loading = self.class.strict_loading_by_default
|
789
|
+
|
790
|
+
self.class.define_attribute_methods
|
791
|
+
end
|
536
792
|
|
537
|
-
|
538
|
-
|
539
|
-
@association_cache = {}
|
540
|
-
@readonly = false
|
541
|
-
@destroyed = false
|
542
|
-
@marked_for_destruction = false
|
543
|
-
@destroyed_by_association = nil
|
544
|
-
@new_record = true
|
545
|
-
@txn = nil
|
546
|
-
@_start_transaction_state = {}
|
547
|
-
@transaction_state = nil
|
548
|
-
@reflects_state = [false]
|
549
|
-
end
|
793
|
+
def initialize_internals_callback
|
794
|
+
end
|
550
795
|
|
551
|
-
|
552
|
-
|
796
|
+
def custom_inspect_method_defined?
|
797
|
+
self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
|
798
|
+
end
|
553
799
|
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
800
|
+
class InspectionMask < DelegateClass(::String)
|
801
|
+
def pretty_print(pp)
|
802
|
+
pp.text __getobj__
|
803
|
+
end
|
804
|
+
end
|
805
|
+
private_constant :InspectionMask
|
559
806
|
|
560
|
-
|
561
|
-
|
562
|
-
@attributes = @attributes.dup
|
807
|
+
def inspection_filter
|
808
|
+
self.class.inspection_filter
|
563
809
|
end
|
564
|
-
end
|
565
810
|
end
|
566
811
|
end
|