activerecord 5.0.7.2 → 6.0.3.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +708 -2040
- data/MIT-LICENSE +3 -1
- data/README.rdoc +9 -7
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record.rb +37 -22
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +18 -14
- data/lib/active_record/associations.rb +1603 -1592
- data/lib/active_record/associations/alias_tracker.rb +24 -34
- data/lib/active_record/associations/association.rb +114 -55
- data/lib/active_record/associations/association_scope.rb +94 -94
- data/lib/active_record/associations/belongs_to_association.rb +58 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +18 -25
- data/lib/active_record/associations/builder/belongs_to.rb +43 -54
- data/lib/active_record/associations/builder/collection_association.rb +7 -18
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
- data/lib/active_record/associations/builder/has_many.rb +4 -0
- data/lib/active_record/associations/builder/has_one.rb +37 -1
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +86 -254
- data/lib/active_record/associations/collection_proxy.rb +158 -122
- data/lib/active_record/associations/foreign_association.rb +9 -0
- data/lib/active_record/associations/has_many_association.rb +23 -30
- data/lib/active_record/associations/has_many_through_association.rb +58 -44
- data/lib/active_record/associations/has_one_association.rb +59 -54
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +143 -176
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -87
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/preloader.rb +90 -103
- data/lib/active_record/associations/preloader/association.rb +86 -100
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +26 -14
- data/lib/active_record/attribute_assignment.rb +54 -61
- data/lib/active_record/attribute_decorators.rb +38 -17
- data/lib/active_record/attribute_methods.rb +66 -106
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
- data/lib/active_record/attribute_methods/dirty.rb +179 -109
- data/lib/active_record/attribute_methods/primary_key.rb +85 -92
- data/lib/active_record/attribute_methods/query.rb +4 -3
- data/lib/active_record/attribute_methods/read.rb +20 -49
- data/lib/active_record/attribute_methods/serialization.rb +29 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
- data/lib/active_record/attribute_methods/write.rb +34 -33
- data/lib/active_record/attributes.rb +38 -25
- data/lib/active_record/autosave_association.rb +54 -35
- data/lib/active_record/base.rb +27 -24
- data/lib/active_record/callbacks.rb +64 -35
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +11 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +552 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +228 -147
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
- data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +396 -562
- data/lib/active_record/connection_adapters/column.rb +41 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
- data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -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/money.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -31
- 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 +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
- data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
- 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 +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +259 -266
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +143 -40
- data/lib/active_record/core.rb +201 -163
- data/lib/active_record/counter_cache.rb +60 -28
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +78 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -87
- data/lib/active_record/enum.rb +60 -23
- data/lib/active_record/errors.rb +114 -18
- data/lib/active_record/explain.rb +4 -4
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +13 -8
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +194 -504
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +150 -99
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +116 -25
- data/lib/active_record/internal_metadata.rb +16 -19
- data/lib/active_record/legacy_yaml_adapter.rb +4 -2
- data/lib/active_record/locking/optimistic.rb +77 -87
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +48 -29
- data/lib/active_record/middleware/database_selector.rb +74 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +369 -302
- data/lib/active_record/migration/command_recorder.rb +134 -100
- data/lib/active_record/migration/compatibility.rb +174 -56
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/model_schema.rb +131 -127
- data/lib/active_record/nested_attributes.rb +213 -202
- data/lib/active_record/no_touching.rb +12 -3
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +446 -77
- data/lib/active_record/query_cache.rb +13 -12
- data/lib/active_record/querying.rb +37 -24
- data/lib/active_record/railtie.rb +128 -36
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +312 -177
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +214 -252
- data/lib/active_record/relation.rb +440 -318
- data/lib/active_record/relation/batches.rb +98 -52
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/calculations.rb +212 -173
- data/lib/active_record/relation/delegation.rb +72 -69
- data/lib/active_record/relation/finder_methods.rb +207 -247
- data/lib/active_record/relation/from_clause.rb +6 -8
- data/lib/active_record/relation/merger.rb +78 -62
- data/lib/active_record/relation/predicate_builder.rb +83 -105
- data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +476 -334
- data/lib/active_record/relation/record_fetch_warning.rb +5 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +111 -96
- data/lib/active_record/relation/where_clause_factory.rb +6 -11
- data/lib/active_record/result.rb +69 -40
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +83 -99
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +71 -69
- data/lib/active_record/schema_migration.rb +16 -6
- data/lib/active_record/scoping.rb +20 -20
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +47 -27
- data/lib/active_record/secure_token.rb +4 -2
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +63 -28
- data/lib/active_record/store.rb +121 -41
- data/lib/active_record/suppressor.rb +6 -3
- data/lib/active_record/table_metadata.rb +39 -18
- data/lib/active_record/tasks/database_tasks.rb +271 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
- data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +225 -0
- data/lib/active_record/timestamp.rb +70 -36
- data/lib/active_record/touch_later.rb +8 -6
- data/lib/active_record/transactions.rb +141 -157
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +23 -18
- data/lib/active_record/type/adapter_specific_registry.rb +44 -48
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +16 -9
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +2 -1
- data/lib/active_record/type/type_map.rb +14 -17
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/type_caster/connection.rb +17 -12
- data/lib/active_record/type_caster/map.rb +5 -4
- data/lib/active_record/validations.rb +7 -5
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +4 -3
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +29 -42
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +62 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +256 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +203 -0
- data/lib/arel/visitors/dot.rb +296 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +156 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +158 -0
- data/lib/arel/visitors/oracle12.rb +65 -0
- data/lib/arel/visitors/postgresql.rb +109 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +888 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors/where_sql.rb +22 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +17 -3
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +137 -52
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- 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 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/attribute_set/builder.rb +0 -132
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
class StatementPool # :nodoc:
|
@@ -6,7 +8,7 @@ module ActiveRecord
|
|
6
8
|
DEFAULT_STATEMENT_LIMIT = 1000
|
7
9
|
|
8
10
|
def initialize(statement_limit = nil)
|
9
|
-
@cache = Hash.new { |h,pid| h[pid] = {} }
|
11
|
+
@cache = Hash.new { |h, pid| h[pid] = {} }
|
10
12
|
@statement_limit = statement_limit || DEFAULT_STATEMENT_LIMIT
|
11
13
|
end
|
12
14
|
|
@@ -46,14 +48,13 @@ module ActiveRecord
|
|
46
48
|
end
|
47
49
|
|
48
50
|
private
|
51
|
+
def cache
|
52
|
+
@cache[Process.pid]
|
53
|
+
end
|
49
54
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
def dealloc(stmt)
|
55
|
-
raise NotImplementedError
|
56
|
-
end
|
55
|
+
def dealloc(stmt)
|
56
|
+
raise NotImplementedError
|
57
|
+
end
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionHandling
|
3
|
-
RAILS_ENV = -> { (Rails.env if defined?(Rails.env)) || ENV["RAILS_ENV"] || ENV["RACK_ENV"] }
|
5
|
+
RAILS_ENV = -> { (Rails.env if defined?(Rails.env)) || ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence }
|
4
6
|
DEFAULT_ENV = -> { RAILS_ENV.call || "default_env" }
|
5
7
|
|
6
8
|
# Establishes the connection to the database. Accepts a hash as input where
|
@@ -44,44 +46,140 @@ module ActiveRecord
|
|
44
46
|
#
|
45
47
|
# The exceptions AdapterNotSpecified, AdapterNotFound and +ArgumentError+
|
46
48
|
# may be returned on an error.
|
47
|
-
def establish_connection(
|
48
|
-
|
49
|
+
def establish_connection(config_or_env = nil)
|
50
|
+
config_hash = resolve_config_for_connection(config_or_env)
|
51
|
+
connection_handler.establish_connection(config_hash)
|
52
|
+
end
|
49
53
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
+
# Connects a model to the databases specified. The +database+ keyword
|
55
|
+
# takes a hash consisting of a +role+ and a +database_key+.
|
56
|
+
#
|
57
|
+
# This will create a connection handler for switching between connections,
|
58
|
+
# look up the config hash using the +database_key+ and finally
|
59
|
+
# establishes a connection to that config.
|
60
|
+
#
|
61
|
+
# class AnimalsModel < ApplicationRecord
|
62
|
+
# self.abstract_class = true
|
63
|
+
#
|
64
|
+
# connects_to database: { writing: :primary, reading: :primary_replica }
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# Returns an array of established connections.
|
68
|
+
def connects_to(database: {})
|
69
|
+
connections = []
|
54
70
|
|
55
|
-
|
56
|
-
|
71
|
+
database.each do |role, database_key|
|
72
|
+
config_hash = resolve_config_for_connection(database_key)
|
73
|
+
handler = lookup_connection_handler(role.to_sym)
|
74
|
+
|
75
|
+
connections << handler.establish_connection(config_hash)
|
57
76
|
end
|
58
77
|
|
59
|
-
|
60
|
-
self.connection_specification_name = spec.name
|
61
|
-
connection_handler.establish_connection spec
|
78
|
+
connections
|
62
79
|
end
|
63
80
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
81
|
+
# Connects to a database or role (ex writing, reading, or another
|
82
|
+
# custom role) for the duration of the block.
|
83
|
+
#
|
84
|
+
# If a role is passed, Active Record will look up the connection
|
85
|
+
# based on the requested role:
|
86
|
+
#
|
87
|
+
# ActiveRecord::Base.connected_to(role: :writing) do
|
88
|
+
# Dog.create! # creates dog using dog writing connection
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
92
|
+
# Dog.create! # throws exception because we're on a replica
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# ActiveRecord::Base.connected_to(role: :unknown_role) do
|
96
|
+
# # raises exception due to non-existent role
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# The `database` kwarg is deprecated in 6.1 and will be removed in 6.2
|
100
|
+
#
|
101
|
+
# It is not recommended for use as it re-establishes a connection every
|
102
|
+
# time it is called.
|
103
|
+
def connected_to(database: nil, role: nil, prevent_writes: false, &blk)
|
104
|
+
if database && role
|
105
|
+
raise ArgumentError, "connected_to can only accept a `database` or a `role` argument, but not both arguments."
|
106
|
+
elsif database
|
107
|
+
if database.is_a?(Hash)
|
108
|
+
role, database = database.first
|
109
|
+
role = role.to_sym
|
110
|
+
end
|
111
|
+
|
112
|
+
config_hash = resolve_config_for_connection(database)
|
113
|
+
handler = lookup_connection_handler(role)
|
69
114
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
115
|
+
handler.establish_connection(config_hash)
|
116
|
+
|
117
|
+
with_handler(role, &blk)
|
118
|
+
elsif role
|
119
|
+
prevent_writes = true if role == reading_role
|
120
|
+
|
121
|
+
with_handler(role.to_sym) do
|
122
|
+
connection_handler.while_preventing_writes(prevent_writes, &blk)
|
123
|
+
end
|
124
|
+
else
|
125
|
+
raise ArgumentError, "must provide a `database` or a `role`."
|
74
126
|
end
|
127
|
+
end
|
75
128
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
129
|
+
# Returns true if role is the current connected role.
|
130
|
+
#
|
131
|
+
# ActiveRecord::Base.connected_to(role: :writing) do
|
132
|
+
# ActiveRecord::Base.connected_to?(role: :writing) #=> true
|
133
|
+
# ActiveRecord::Base.connected_to?(role: :reading) #=> false
|
134
|
+
# end
|
135
|
+
def connected_to?(role:)
|
136
|
+
current_role == role.to_sym
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns the symbol representing the current connected role.
|
140
|
+
#
|
141
|
+
# ActiveRecord::Base.connected_to(role: :writing) do
|
142
|
+
# ActiveRecord::Base.current_role #=> :writing
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
146
|
+
# ActiveRecord::Base.current_role #=> :reading
|
147
|
+
# end
|
148
|
+
def current_role
|
149
|
+
connection_handlers.key(connection_handler)
|
150
|
+
end
|
151
|
+
|
152
|
+
def lookup_connection_handler(handler_key) # :nodoc:
|
153
|
+
handler_key ||= ActiveRecord::Base.writing_role
|
154
|
+
connection_handlers[handler_key] ||= ActiveRecord::ConnectionAdapters::ConnectionHandler.new
|
155
|
+
end
|
156
|
+
|
157
|
+
def with_handler(handler_key, &blk) # :nodoc:
|
158
|
+
handler = lookup_connection_handler(handler_key)
|
159
|
+
swap_connection_handler(handler, &blk)
|
160
|
+
end
|
161
|
+
|
162
|
+
def resolve_config_for_connection(config_or_env) # :nodoc:
|
163
|
+
raise "Anonymous class is not allowed." unless name
|
164
|
+
|
165
|
+
config_or_env ||= DEFAULT_ENV.call.to_sym
|
166
|
+
pool_name = primary_class? ? "primary" : name
|
167
|
+
self.connection_specification_name = pool_name
|
168
|
+
|
169
|
+
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new(Base.configurations)
|
170
|
+
config_hash = resolver.resolve(config_or_env, pool_name).symbolize_keys
|
171
|
+
config_hash[:name] = pool_name
|
172
|
+
|
173
|
+
config_hash
|
174
|
+
end
|
175
|
+
|
176
|
+
# Clears the query cache for all connections associated with the current thread.
|
177
|
+
def clear_query_caches_for_current_thread
|
178
|
+
ActiveRecord::Base.connection_handlers.each_value do |handler|
|
179
|
+
handler.connection_pool_list.each do |pool|
|
180
|
+
pool.connection.clear_query_cache if pool.active_connection?
|
84
181
|
end
|
182
|
+
end
|
85
183
|
end
|
86
184
|
|
87
185
|
# Returns the connection currently associated with the class. This can
|
@@ -93,8 +191,7 @@ module ActiveRecord
|
|
93
191
|
|
94
192
|
attr_writer :connection_specification_name
|
95
193
|
|
96
|
-
# Return the specification
|
97
|
-
# in the parent.
|
194
|
+
# Return the specification name from the current class or its parent.
|
98
195
|
def connection_specification_name
|
99
196
|
if !defined?(@connection_specification_name) || @connection_specification_name.nil?
|
100
197
|
return self == Base ? "primary" : superclass.connection_specification_name
|
@@ -102,12 +199,8 @@ module ActiveRecord
|
|
102
199
|
@connection_specification_name
|
103
200
|
end
|
104
201
|
|
105
|
-
def
|
106
|
-
|
107
|
-
end
|
108
|
-
|
109
|
-
def connection_id=(connection_id)
|
110
|
-
ActiveRecord::RuntimeRegistry.connection_id = connection_id
|
202
|
+
def primary_class? # :nodoc:
|
203
|
+
self == Base || defined?(ApplicationRecord) && self == ApplicationRecord
|
111
204
|
end
|
112
205
|
|
113
206
|
# Returns the configuration of the associated connection as a hash:
|
@@ -121,7 +214,7 @@ module ActiveRecord
|
|
121
214
|
end
|
122
215
|
|
123
216
|
def connection_pool
|
124
|
-
connection_handler.retrieve_connection_pool(connection_specification_name)
|
217
|
+
connection_handler.retrieve_connection_pool(connection_specification_name) || raise(ConnectionNotEstablished)
|
125
218
|
end
|
126
219
|
|
127
220
|
def retrieve_connection
|
@@ -135,7 +228,7 @@ module ActiveRecord
|
|
135
228
|
|
136
229
|
def remove_connection(name = nil)
|
137
230
|
name ||= @connection_specification_name if defined?(@connection_specification_name)
|
138
|
-
# if removing a connection that
|
231
|
+
# if removing a connection that has a pool, we reset the
|
139
232
|
# connection_specification_name so it will use the parent
|
140
233
|
# pool.
|
141
234
|
if connection_handler.retrieve_connection_pool(name)
|
@@ -150,6 +243,16 @@ module ActiveRecord
|
|
150
243
|
end
|
151
244
|
|
152
245
|
delegate :clear_active_connections!, :clear_reloadable_connections!,
|
153
|
-
:clear_all_connections!, :to
|
246
|
+
:clear_all_connections!, :flush_idle_connections!, to: :connection_handler
|
247
|
+
|
248
|
+
private
|
249
|
+
def swap_connection_handler(handler, &blk) # :nodoc:
|
250
|
+
old_handler, ActiveRecord::Base.connection_handler = ActiveRecord::Base.connection_handler, handler
|
251
|
+
return_value = yield
|
252
|
+
return_value.load if return_value.is_a? ActiveRecord::Relation
|
253
|
+
return_value
|
254
|
+
ensure
|
255
|
+
ActiveRecord::Base.connection_handler = old_handler
|
256
|
+
end
|
154
257
|
end
|
155
258
|
end
|
data/lib/active_record/core.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/indifferent_access"
|
4
|
+
require "active_support/core_ext/string/filters"
|
5
|
+
require "active_support/parameter_filter"
|
6
|
+
require "concurrent/map"
|
5
7
|
|
6
8
|
module ActiveRecord
|
7
9
|
module Core
|
@@ -16,9 +18,16 @@ module ActiveRecord
|
|
16
18
|
# retrieved on both a class and instance level by calling +logger+.
|
17
19
|
mattr_accessor :logger, instance_writer: false
|
18
20
|
|
21
|
+
##
|
22
|
+
# :singleton-method:
|
23
|
+
#
|
24
|
+
# Specifies if the methods calling database queries should be logged below
|
25
|
+
# their relevant queries. Defaults to false.
|
26
|
+
mattr_accessor :verbose_query_logs, instance_writer: false, default: false
|
27
|
+
|
19
28
|
##
|
20
29
|
# Contains the database configuration - as is typically stored in config/database.yml -
|
21
|
-
# as
|
30
|
+
# as an ActiveRecord::DatabaseConfigurations object.
|
22
31
|
#
|
23
32
|
# For example, the following database.yml...
|
24
33
|
#
|
@@ -32,22 +41,18 @@ module ActiveRecord
|
|
32
41
|
#
|
33
42
|
# ...would result in ActiveRecord::Base.configurations to look like this:
|
34
43
|
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
# 'adapter' => 'sqlite3',
|
42
|
-
# 'database' => 'db/production.sqlite3'
|
43
|
-
# }
|
44
|
-
# }
|
44
|
+
# #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
|
45
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
|
46
|
+
# @spec_name="primary", @config={"adapter"=>"sqlite3", "database"=>"db/development.sqlite3"}>,
|
47
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
|
48
|
+
# @spec_name="primary", @config={"adapter"=>"mysql2", "database"=>"db/production.sqlite3"}>
|
49
|
+
# ]>
|
45
50
|
def self.configurations=(config)
|
46
|
-
@@configurations = ActiveRecord::
|
51
|
+
@@configurations = ActiveRecord::DatabaseConfigurations.new(config)
|
47
52
|
end
|
48
53
|
self.configurations = {}
|
49
54
|
|
50
|
-
# Returns fully resolved
|
55
|
+
# Returns fully resolved ActiveRecord::DatabaseConfigurations object
|
51
56
|
def self.configurations
|
52
57
|
@@configurations
|
53
58
|
end
|
@@ -56,8 +61,7 @@ module ActiveRecord
|
|
56
61
|
# :singleton-method:
|
57
62
|
# Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
|
58
63
|
# 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
|
64
|
+
mattr_accessor :default_timezone, instance_writer: false, default: :utc
|
61
65
|
|
62
66
|
##
|
63
67
|
# :singleton-method:
|
@@ -67,31 +71,35 @@ module ActiveRecord
|
|
67
71
|
# ActiveRecord::Schema file which can be loaded into any database that
|
68
72
|
# supports migrations. Use :ruby if you want to have different database
|
69
73
|
# adapters for, e.g., your development and test environments.
|
70
|
-
mattr_accessor :schema_format, instance_writer: false
|
71
|
-
self.schema_format = :ruby
|
74
|
+
mattr_accessor :schema_format, instance_writer: false, default: :ruby
|
72
75
|
|
73
76
|
##
|
74
77
|
# :singleton-method:
|
75
|
-
# Specifies if an error should be raised
|
78
|
+
# Specifies if an error should be raised if the query has an order being
|
76
79
|
# ignored when doing batch queries. Useful in applications where the
|
77
|
-
#
|
78
|
-
mattr_accessor :
|
79
|
-
|
80
|
+
# scope being ignored is error-worthy, rather than a warning.
|
81
|
+
mattr_accessor :error_on_ignored_order, instance_writer: false, default: false
|
82
|
+
|
83
|
+
# :singleton-method:
|
84
|
+
# Specify the behavior for unsafe raw query methods. Values are as follows
|
85
|
+
# deprecated - Warnings are logged when unsafe raw SQL is passed to
|
86
|
+
# query methods.
|
87
|
+
# disabled - Unsafe raw SQL passed to query methods results in
|
88
|
+
# UnknownAttributeReference exception.
|
89
|
+
mattr_accessor :allow_unsafe_raw_sql, instance_writer: false, default: :deprecated
|
80
90
|
|
81
91
|
##
|
82
92
|
# :singleton-method:
|
83
93
|
# Specify whether or not to use timestamps for migration versions
|
84
|
-
mattr_accessor :timestamped_migrations, instance_writer: false
|
85
|
-
self.timestamped_migrations = true
|
94
|
+
mattr_accessor :timestamped_migrations, instance_writer: false, default: true
|
86
95
|
|
87
96
|
##
|
88
97
|
# :singleton-method:
|
89
98
|
# Specify whether schema dump should happen at the end of the
|
90
|
-
# db:migrate
|
99
|
+
# db:migrate rails command. This is true by default, which is useful for the
|
91
100
|
# development environment. This should ideally be false in the production
|
92
101
|
# environment where dumping schema is rarely needed.
|
93
|
-
mattr_accessor :dump_schema_after_migration, instance_writer: false
|
94
|
-
self.dump_schema_after_migration = true
|
102
|
+
mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true
|
95
103
|
|
96
104
|
##
|
97
105
|
# :singleton-method:
|
@@ -100,8 +108,7 @@ module ActiveRecord
|
|
100
108
|
# schema_search_path are dumped. Use :all to dump all schemas regardless
|
101
109
|
# of schema_search_path, or a string of comma separated schemas for a
|
102
110
|
# custom list.
|
103
|
-
mattr_accessor :dump_schemas, instance_writer: false
|
104
|
-
self.dump_schemas = :schema_search_path
|
111
|
+
mattr_accessor :dump_schemas, instance_writer: false, default: :schema_search_path
|
105
112
|
|
106
113
|
##
|
107
114
|
# :singleton-method:
|
@@ -110,33 +117,35 @@ module ActiveRecord
|
|
110
117
|
# be used to identify queries which load thousands of records and
|
111
118
|
# potentially cause memory bloat.
|
112
119
|
mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
|
113
|
-
self.warn_on_records_fetched_greater_than = nil
|
114
120
|
|
115
121
|
mattr_accessor :maintain_test_schema, instance_accessor: false
|
116
122
|
|
117
123
|
mattr_accessor :belongs_to_required_by_default, instance_accessor: false
|
118
124
|
|
125
|
+
mattr_accessor :connection_handlers, instance_accessor: false, default: {}
|
126
|
+
|
127
|
+
mattr_accessor :writing_role, instance_accessor: false, default: :writing
|
128
|
+
|
129
|
+
mattr_accessor :reading_role, instance_accessor: false, default: :reading
|
130
|
+
|
119
131
|
class_attribute :default_connection_handler, instance_writer: false
|
120
132
|
|
133
|
+
self.filter_attributes = []
|
134
|
+
|
121
135
|
def self.connection_handler
|
122
|
-
|
136
|
+
Thread.current.thread_variable_get("ar_connection_handler") || default_connection_handler
|
123
137
|
end
|
124
138
|
|
125
139
|
def self.connection_handler=(handler)
|
126
|
-
|
140
|
+
Thread.current.thread_variable_set("ar_connection_handler", handler)
|
127
141
|
end
|
128
142
|
|
129
143
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
130
144
|
end
|
131
145
|
|
132
146
|
module ClassMethods
|
133
|
-
def allocate
|
134
|
-
define_attribute_methods
|
135
|
-
super
|
136
|
-
end
|
137
|
-
|
138
147
|
def initialize_find_by_cache # :nodoc:
|
139
|
-
@find_by_statement_cache = { true =>
|
148
|
+
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
140
149
|
end
|
141
150
|
|
142
151
|
def inherited(child_class) # :nodoc:
|
@@ -151,41 +160,33 @@ module ActiveRecord
|
|
151
160
|
return super if block_given? ||
|
152
161
|
primary_key.nil? ||
|
153
162
|
scope_attributes? ||
|
154
|
-
columns_hash.
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
id = id.id
|
160
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
161
|
-
You are passing an instance of ActiveRecord::Base to `find`.
|
162
|
-
Please pass the id of the object by calling `.id`.
|
163
|
-
MSG
|
164
|
-
end
|
163
|
+
columns_hash.key?(inheritance_column) && !base_class?
|
164
|
+
|
165
|
+
id = ids.first
|
166
|
+
|
167
|
+
return super if StatementCache.unsupported_value?(id)
|
165
168
|
|
166
169
|
key = primary_key
|
167
170
|
|
168
171
|
statement = cached_find_by_statement(key) { |params|
|
169
172
|
where(key => params.bind).limit(1)
|
170
173
|
}
|
171
|
-
|
174
|
+
|
175
|
+
record = statement.execute([id], connection)&.first
|
172
176
|
unless record
|
173
|
-
raise RecordNotFound.new("Couldn't find #{name} with '#{
|
174
|
-
name, primary_key, id)
|
177
|
+
raise RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id)
|
175
178
|
end
|
176
179
|
record
|
177
|
-
rescue RangeError
|
178
|
-
raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
|
179
|
-
name, primary_key)
|
180
180
|
end
|
181
181
|
|
182
182
|
def find_by(*args) # :nodoc:
|
183
|
-
return super if scope_attributes? || reflect_on_all_aggregations.any?
|
183
|
+
return super if scope_attributes? || reflect_on_all_aggregations.any? ||
|
184
|
+
columns_hash.key?(inheritance_column) && !base_class?
|
184
185
|
|
185
186
|
hash = args.first
|
186
187
|
|
187
188
|
return super if !(Hash === hash) || hash.values.any? { |v|
|
188
|
-
|
189
|
+
StatementCache.unsupported_value?(v)
|
189
190
|
}
|
190
191
|
|
191
192
|
# We can't cache Post.find_by(author: david) ...yet
|
@@ -200,32 +201,44 @@ module ActiveRecord
|
|
200
201
|
where(wheres).limit(1)
|
201
202
|
}
|
202
203
|
begin
|
203
|
-
statement.execute(hash.values,
|
204
|
+
statement.execute(hash.values, connection)&.first
|
204
205
|
rescue TypeError
|
205
206
|
raise ActiveRecord::StatementInvalid
|
206
|
-
rescue RangeError
|
207
|
-
nil
|
208
207
|
end
|
209
208
|
end
|
210
209
|
|
211
210
|
def find_by!(*args) # :nodoc:
|
212
|
-
find_by(*args)
|
211
|
+
find_by(*args) || raise(RecordNotFound.new("Couldn't find #{name}", name))
|
213
212
|
end
|
214
213
|
|
215
214
|
def initialize_generated_modules # :nodoc:
|
216
215
|
generated_association_methods
|
217
216
|
end
|
218
217
|
|
219
|
-
def generated_association_methods
|
218
|
+
def generated_association_methods # :nodoc:
|
220
219
|
@generated_association_methods ||= begin
|
221
220
|
mod = const_set(:GeneratedAssociationMethods, Module.new)
|
221
|
+
private_constant :GeneratedAssociationMethods
|
222
222
|
include mod
|
223
|
+
|
223
224
|
mod
|
224
225
|
end
|
225
226
|
end
|
226
227
|
|
228
|
+
# Returns columns which shouldn't be exposed while calling +#inspect+.
|
229
|
+
def filter_attributes
|
230
|
+
if defined?(@filter_attributes)
|
231
|
+
@filter_attributes
|
232
|
+
else
|
233
|
+
superclass.filter_attributes
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Specifies columns which shouldn't be exposed while calling +#inspect+.
|
238
|
+
attr_writer :filter_attributes
|
239
|
+
|
227
240
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
228
|
-
def inspect
|
241
|
+
def inspect # :nodoc:
|
229
242
|
if self == Base
|
230
243
|
super
|
231
244
|
elsif abstract_class?
|
@@ -233,39 +246,30 @@ module ActiveRecord
|
|
233
246
|
elsif !connected?
|
234
247
|
"#{super} (call '#{super}.connection' to establish a connection)"
|
235
248
|
elsif table_exists?
|
236
|
-
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } *
|
249
|
+
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
|
237
250
|
"#{super}(#{attr_list})"
|
238
251
|
else
|
239
252
|
"#{super}(Table doesn't exist)"
|
240
253
|
end
|
241
254
|
end
|
242
255
|
|
243
|
-
# Overwrite the default class equality method to provide support for
|
244
|
-
def ===(object)
|
256
|
+
# Overwrite the default class equality method to provide support for decorated models.
|
257
|
+
def ===(object) # :nodoc:
|
245
258
|
object.is_a?(self)
|
246
259
|
end
|
247
260
|
|
248
261
|
# Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
|
249
262
|
#
|
250
263
|
# class Post < ActiveRecord::Base
|
251
|
-
# scope :published_and_commented, -> { published.and(
|
264
|
+
# scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
|
252
265
|
# end
|
253
266
|
def arel_table # :nodoc:
|
254
267
|
@arel_table ||= Arel::Table.new(table_name, type_caster: type_caster)
|
255
268
|
end
|
256
269
|
|
257
|
-
# Returns the Arel engine.
|
258
|
-
def arel_engine # :nodoc:
|
259
|
-
@arel_engine ||=
|
260
|
-
if Base == self || connection_handler.retrieve_connection_pool(connection_specification_name)
|
261
|
-
self
|
262
|
-
else
|
263
|
-
superclass.arel_engine
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
270
|
def arel_attribute(name, table = arel_table) # :nodoc:
|
268
|
-
name =
|
271
|
+
name = name.to_s
|
272
|
+
name = attribute_aliases[name] || name
|
269
273
|
table[name]
|
270
274
|
end
|
271
275
|
|
@@ -277,28 +281,30 @@ module ActiveRecord
|
|
277
281
|
TypeCaster::Map.new(self)
|
278
282
|
end
|
279
283
|
|
280
|
-
|
281
|
-
|
282
|
-
def cached_find_by_statement(key, &block) # :nodoc:
|
283
|
-
cache = @find_by_statement_cache[connection.prepared_statements]
|
284
|
-
cache[key] || cache.synchronize {
|
285
|
-
cache[key] ||= StatementCache.create(connection, &block)
|
286
|
-
}
|
284
|
+
def _internal? # :nodoc:
|
285
|
+
false
|
287
286
|
end
|
288
287
|
|
289
|
-
|
290
|
-
|
288
|
+
private
|
289
|
+
def cached_find_by_statement(key, &block)
|
290
|
+
cache = @find_by_statement_cache[connection.prepared_statements]
|
291
|
+
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
292
|
+
end
|
291
293
|
|
292
|
-
|
293
|
-
relation.
|
294
|
-
|
295
|
-
|
294
|
+
def relation
|
295
|
+
relation = Relation.create(self)
|
296
|
+
|
297
|
+
if finder_needs_type_condition? && !ignore_default_scope?
|
298
|
+
relation.where!(type_condition)
|
299
|
+
relation.create_with!(inheritance_column.to_s => sti_name)
|
300
|
+
else
|
301
|
+
relation
|
302
|
+
end
|
296
303
|
end
|
297
|
-
end
|
298
304
|
|
299
|
-
|
300
|
-
|
301
|
-
|
305
|
+
def table_metadata
|
306
|
+
TableMetadata.new(self, arel_table)
|
307
|
+
end
|
302
308
|
end
|
303
309
|
|
304
310
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
@@ -310,7 +316,7 @@ module ActiveRecord
|
|
310
316
|
# # Instantiates a single new object
|
311
317
|
# User.new(first_name: 'Jamie')
|
312
318
|
def initialize(attributes = nil)
|
313
|
-
|
319
|
+
@new_record = true
|
314
320
|
@attributes = self.class._default_attributes.deep_dup
|
315
321
|
|
316
322
|
init_internals
|
@@ -336,15 +342,21 @@ module ActiveRecord
|
|
336
342
|
# post = Post.allocate
|
337
343
|
# post.init_with(coder)
|
338
344
|
# post.title # => 'hello world'
|
339
|
-
def init_with(coder)
|
345
|
+
def init_with(coder, &block)
|
340
346
|
coder = LegacyYamlAdapter.convert(self.class, coder)
|
341
|
-
|
342
|
-
|
343
|
-
|
347
|
+
attributes = self.class.yaml_encoder.decode(coder)
|
348
|
+
init_with_attributes(attributes, coder["new_record"], &block)
|
349
|
+
end
|
344
350
|
|
345
|
-
|
351
|
+
##
|
352
|
+
# Initialize an empty model object from +attributes+.
|
353
|
+
# +attributes+ should be an attributes object, and unlike the
|
354
|
+
# `initialize` method, no assignment calls are made per attribute.
|
355
|
+
def init_with_attributes(attributes, new_record = false) # :nodoc:
|
356
|
+
@new_record = new_record
|
357
|
+
@attributes = attributes
|
346
358
|
|
347
|
-
|
359
|
+
init_internals
|
348
360
|
|
349
361
|
yield self if block_given?
|
350
362
|
|
@@ -383,12 +395,14 @@ module ActiveRecord
|
|
383
395
|
##
|
384
396
|
def initialize_dup(other) # :nodoc:
|
385
397
|
@attributes = @attributes.deep_dup
|
386
|
-
@attributes.reset(
|
398
|
+
@attributes.reset(@primary_key)
|
387
399
|
|
388
400
|
_run_initialize_callbacks
|
389
401
|
|
390
|
-
@new_record
|
391
|
-
@destroyed
|
402
|
+
@new_record = true
|
403
|
+
@destroyed = false
|
404
|
+
@_start_transaction_state = nil
|
405
|
+
@transaction_state = nil
|
392
406
|
|
393
407
|
super
|
394
408
|
end
|
@@ -406,11 +420,9 @@ module ActiveRecord
|
|
406
420
|
# Post.new.encode_with(coder)
|
407
421
|
# coder # => {"attributes" => {"id" => nil, ... }}
|
408
422
|
def encode_with(coder)
|
409
|
-
|
410
|
-
coder[
|
411
|
-
coder[
|
412
|
-
coder['new_record'] = new_record?
|
413
|
-
coder['active_record_yaml_version'] = 1
|
423
|
+
self.class.yaml_encoder.encode(@attributes, coder)
|
424
|
+
coder["new_record"] = new_record?
|
425
|
+
coder["active_record_yaml_version"] = 2
|
414
426
|
end
|
415
427
|
|
416
428
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
@@ -434,7 +446,7 @@ module ActiveRecord
|
|
434
446
|
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
435
447
|
def hash
|
436
448
|
if id
|
437
|
-
id.hash
|
449
|
+
self.class.hash ^ id.hash
|
438
450
|
else
|
439
451
|
super
|
440
452
|
end
|
@@ -450,18 +462,27 @@ module ActiveRecord
|
|
450
462
|
|
451
463
|
# Returns +true+ if the attributes hash has been frozen.
|
452
464
|
def frozen?
|
465
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
453
466
|
@attributes.frozen?
|
454
467
|
end
|
455
468
|
|
456
469
|
# Allows sort on objects
|
457
470
|
def <=>(other_object)
|
458
471
|
if other_object.is_a?(self.class)
|
459
|
-
|
472
|
+
to_key <=> other_object.to_key
|
460
473
|
else
|
461
474
|
super
|
462
475
|
end
|
463
476
|
end
|
464
477
|
|
478
|
+
def present? # :nodoc:
|
479
|
+
true
|
480
|
+
end
|
481
|
+
|
482
|
+
def blank? # :nodoc:
|
483
|
+
false
|
484
|
+
end
|
485
|
+
|
465
486
|
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
|
466
487
|
# attributes will be marked as read only since they cannot be saved.
|
467
488
|
def readonly?
|
@@ -482,14 +503,22 @@ module ActiveRecord
|
|
482
503
|
# We check defined?(@attributes) not to issue warnings if the object is
|
483
504
|
# allocated but not initialized.
|
484
505
|
inspection = if defined?(@attributes) && @attributes
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
506
|
+
self.class.attribute_names.collect do |name|
|
507
|
+
if has_attribute?(name)
|
508
|
+
attr = _read_attribute(name)
|
509
|
+
value = if attr.nil?
|
510
|
+
attr.inspect
|
511
|
+
else
|
512
|
+
attr = format_for_inspect(attr)
|
513
|
+
inspection_filter.filter_param(name, attr)
|
514
|
+
end
|
515
|
+
"#{name}: #{value}"
|
516
|
+
end
|
517
|
+
end.compact.join(", ")
|
518
|
+
else
|
519
|
+
"not initialized"
|
520
|
+
end
|
521
|
+
|
493
522
|
"#<#{self.class} #{inspection}>"
|
494
523
|
end
|
495
524
|
|
@@ -499,65 +528,74 @@ module ActiveRecord
|
|
499
528
|
return super if custom_inspect_method_defined?
|
500
529
|
pp.object_address_group(self) do
|
501
530
|
if defined?(@attributes) && @attributes
|
502
|
-
|
503
|
-
pp.seplist(
|
504
|
-
|
505
|
-
pp.breakable ' '
|
531
|
+
attr_names = self.class.attribute_names.select { |name| has_attribute?(name) }
|
532
|
+
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
533
|
+
pp.breakable " "
|
506
534
|
pp.group(1) do
|
507
|
-
pp.text
|
508
|
-
pp.text
|
535
|
+
pp.text attr_name
|
536
|
+
pp.text ":"
|
509
537
|
pp.breakable
|
510
|
-
|
538
|
+
value = _read_attribute(attr_name)
|
539
|
+
value = inspection_filter.filter_param(attr_name, value) unless value.nil?
|
540
|
+
pp.pp value
|
511
541
|
end
|
512
542
|
end
|
513
543
|
else
|
514
|
-
pp.breakable
|
515
|
-
pp.text
|
544
|
+
pp.breakable " "
|
545
|
+
pp.text "not initialized"
|
516
546
|
end
|
517
547
|
end
|
518
548
|
end
|
519
549
|
|
520
550
|
# Returns a hash of the given methods with their names as keys and returned values as values.
|
521
551
|
def slice(*methods)
|
522
|
-
Hash[methods.map! { |method| [method, public_send(method)] }].with_indifferent_access
|
552
|
+
Hash[methods.flatten.map! { |method| [method, public_send(method)] }].with_indifferent_access
|
523
553
|
end
|
524
554
|
|
525
555
|
private
|
556
|
+
# +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
|
557
|
+
# the array, and then rescues from the possible +NoMethodError+. If those elements are
|
558
|
+
# +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have,
|
559
|
+
# which significantly impacts upon performance.
|
560
|
+
#
|
561
|
+
# So we can avoid the +method_missing+ hit by explicitly defining +#to_ary+ as +nil+ here.
|
562
|
+
#
|
563
|
+
# See also https://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
|
564
|
+
def to_ary
|
565
|
+
nil
|
566
|
+
end
|
526
567
|
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
def to_ary # :nodoc:
|
536
|
-
nil
|
537
|
-
end
|
568
|
+
def init_internals
|
569
|
+
@primary_key = self.class.primary_key
|
570
|
+
@readonly = false
|
571
|
+
@destroyed = false
|
572
|
+
@marked_for_destruction = false
|
573
|
+
@destroyed_by_association = nil
|
574
|
+
@_start_transaction_state = nil
|
575
|
+
@transaction_state = nil
|
538
576
|
|
539
|
-
|
540
|
-
|
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
|
-
end
|
577
|
+
self.class.define_attribute_methods
|
578
|
+
end
|
549
579
|
|
550
|
-
|
551
|
-
|
580
|
+
def initialize_internals_callback
|
581
|
+
end
|
552
582
|
|
553
|
-
|
554
|
-
|
555
|
-
@attributes = @attributes.dup
|
583
|
+
def custom_inspect_method_defined?
|
584
|
+
self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
|
556
585
|
end
|
557
|
-
end
|
558
586
|
|
559
|
-
|
560
|
-
|
561
|
-
|
587
|
+
class InspectionMask < DelegateClass(::String)
|
588
|
+
def pretty_print(pp)
|
589
|
+
pp.text __getobj__
|
590
|
+
end
|
591
|
+
end
|
592
|
+
private_constant :InspectionMask
|
593
|
+
|
594
|
+
def inspection_filter
|
595
|
+
@inspection_filter ||= begin
|
596
|
+
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
597
|
+
ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
|
598
|
+
end
|
599
|
+
end
|
562
600
|
end
|
563
601
|
end
|