activerecord 4.2.0 → 6.0.0
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 +5 -5
- data/CHANGELOG.md +612 -971
- data/MIT-LICENSE +4 -2
- data/README.rdoc +13 -12
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +267 -248
- data/lib/active_record/association_relation.rb +24 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +135 -56
- data/lib/active_record/associations/association_scope.rb +103 -131
- data/lib/active_record/associations/belongs_to_association.rb +67 -54
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +27 -40
- data/lib/active_record/associations/builder/belongs_to.rb +69 -55
- data/lib/active_record/associations/builder/collection_association.rb +10 -29
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +60 -70
- data/lib/active_record/associations/builder/has_many.rb +8 -4
- data/lib/active_record/associations/builder/has_one.rb +46 -5
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +138 -274
- data/lib/active_record/associations/collection_proxy.rb +252 -151
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +35 -83
- data/lib/active_record/associations/has_many_through_association.rb +62 -80
- data/lib/active_record/associations/has_one_association.rb +62 -49
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -80
- 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 +138 -162
- data/lib/active_record/associations/preloader/association.rb +90 -119
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +92 -94
- data/lib/active_record/associations/singular_association.rb +18 -45
- data/lib/active_record/associations/through_association.rb +48 -23
- data/lib/active_record/associations.rb +1737 -1596
- data/lib/active_record/attribute_assignment.rb +56 -183
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +15 -5
- data/lib/active_record/attribute_methods/dirty.rb +174 -134
- data/lib/active_record/attribute_methods/primary_key.rb +91 -83
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -76
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +62 -36
- data/lib/active_record/attribute_methods/write.rb +33 -55
- data/lib/active_record/attribute_methods.rb +124 -143
- data/lib/active_record/attributes.rb +214 -74
- data/lib/active_record/autosave_association.rb +115 -46
- data/lib/active_record/base.rb +60 -49
- data/lib/active_record/callbacks.rb +100 -74
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -290
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +247 -108
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +171 -53
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +366 -227
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +706 -222
- data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -87
- data/lib/active_record/connection_adapters/abstract_adapter.rb +468 -194
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +535 -597
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -195
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +65 -115
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -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 +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- 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 +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -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 +10 -5
- 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 +23 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +474 -286
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -363
- data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -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 +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +288 -359
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +176 -41
- data/lib/active_record/core.rb +266 -233
- data/lib/active_record/counter_cache.rb +68 -50
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +164 -88
- data/lib/active_record/errors.rb +189 -53
- data/lib/active_record/explain.rb +23 -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 +35 -9
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +226 -495
- data/lib/active_record/gem_version.rb +4 -2
- data/lib/active_record/inheritance.rb +158 -112
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +123 -29
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +91 -98
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +76 -33
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +177 -90
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +634 -288
- data/lib/active_record/model_schema.rb +314 -112
- data/lib/active_record/nested_attributes.rb +266 -214
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +559 -124
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +43 -29
- data/lib/active_record/railtie.rb +148 -47
- 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 +338 -202
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +460 -299
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +207 -55
- data/lib/active_record/relation/calculations.rb +269 -248
- data/lib/active_record/relation/delegation.rb +70 -80
- data/lib/active_record/relation/finder_methods.rb +279 -255
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +83 -69
- data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -25
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -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 +53 -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 +116 -92
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +574 -391
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -16
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/relation.rb +518 -340
- data/lib/active_record/result.rb +79 -42
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +144 -121
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +112 -93
- data/lib/active_record/schema_migration.rb +24 -20
- data/lib/active_record/scoping/default.rb +101 -84
- data/lib/active_record/scoping/named.rb +86 -33
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +73 -36
- data/lib/active_record/store.rb +127 -42
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +75 -0
- data/lib/active_record/tasks/database_tasks.rb +309 -99
- data/lib/active_record/tasks/mysql_database_tasks.rb +58 -88
- data/lib/active_record/tasks/postgresql_database_tasks.rb +82 -31
- data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +86 -40
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +215 -139
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +129 -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 +13 -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 +30 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type.rb +78 -23
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -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 +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +43 -46
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +43 -21
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -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/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/nodes.rb +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +51 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -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 +42 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -8
- data/lib/rails/generators/active_record/migration.rb +31 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +166 -60
- 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_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- 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/infinity.rb +0 -13
- 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,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,148 +71,174 @@ 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
|
-
|
74
|
+
mattr_accessor :schema_format, instance_writer: false, default: :ruby
|
75
|
+
|
76
|
+
##
|
77
|
+
# :singleton-method:
|
78
|
+
# Specifies if an error should be raised if the query has an order being
|
79
|
+
# ignored when doing batch queries. Useful in applications where the
|
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
|
72
90
|
|
73
91
|
##
|
74
92
|
# :singleton-method:
|
75
93
|
# Specify whether or not to use timestamps for migration versions
|
76
|
-
mattr_accessor :timestamped_migrations, instance_writer: false
|
77
|
-
self.timestamped_migrations = true
|
94
|
+
mattr_accessor :timestamped_migrations, instance_writer: false, default: true
|
78
95
|
|
79
96
|
##
|
80
97
|
# :singleton-method:
|
81
98
|
# Specify whether schema dump should happen at the end of the
|
82
|
-
# db:migrate
|
99
|
+
# db:migrate rails command. This is true by default, which is useful for the
|
83
100
|
# development environment. This should ideally be false in the production
|
84
101
|
# environment where dumping schema is rarely needed.
|
85
|
-
mattr_accessor :dump_schema_after_migration, instance_writer: false
|
86
|
-
|
102
|
+
mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true
|
103
|
+
|
104
|
+
##
|
105
|
+
# :singleton-method:
|
106
|
+
# Specifies which database schemas to dump when calling db:structure:dump.
|
107
|
+
# If the value is :schema_search_path (the default), any schemas listed in
|
108
|
+
# schema_search_path are dumped. Use :all to dump all schemas regardless
|
109
|
+
# of schema_search_path, or a string of comma separated schemas for a
|
110
|
+
# custom list.
|
111
|
+
mattr_accessor :dump_schemas, instance_writer: false, default: :schema_search_path
|
112
|
+
|
113
|
+
##
|
114
|
+
# :singleton-method:
|
115
|
+
# Specify a threshold for the size of query result sets. If the number of
|
116
|
+
# records in the set exceeds the threshold, a warning is logged. This can
|
117
|
+
# be used to identify queries which load thousands of records and
|
118
|
+
# potentially cause memory bloat.
|
119
|
+
mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
|
87
120
|
|
88
121
|
mattr_accessor :maintain_test_schema, instance_accessor: false
|
89
122
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
123
|
+
mattr_accessor :belongs_to_required_by_default, instance_accessor: false
|
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
|
96
130
|
|
97
131
|
class_attribute :default_connection_handler, instance_writer: false
|
98
|
-
|
132
|
+
|
133
|
+
self.filter_attributes = []
|
99
134
|
|
100
135
|
def self.connection_handler
|
101
|
-
|
136
|
+
Thread.current.thread_variable_get("ar_connection_handler") || default_connection_handler
|
102
137
|
end
|
103
138
|
|
104
139
|
def self.connection_handler=(handler)
|
105
|
-
|
140
|
+
Thread.current.thread_variable_set("ar_connection_handler", handler)
|
106
141
|
end
|
107
142
|
|
108
143
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
109
144
|
end
|
110
145
|
|
111
146
|
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)
|
147
|
+
def initialize_find_by_cache # :nodoc:
|
148
|
+
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
119
149
|
end
|
120
150
|
|
121
|
-
def inherited(child_class)
|
151
|
+
def inherited(child_class) # :nodoc:
|
152
|
+
# initialize cache at class definition for thread safety
|
122
153
|
child_class.initialize_find_by_cache
|
123
154
|
super
|
124
155
|
end
|
125
156
|
|
126
|
-
def find(*ids)
|
157
|
+
def find(*ids) # :nodoc:
|
127
158
|
# We don't have cache keys for this stuff yet
|
128
159
|
return super unless ids.length == 1
|
129
|
-
# Allow symbols to super to maintain compatibility for deprecated finders until Rails 5
|
130
|
-
return super if ids.first.kind_of?(Symbol)
|
131
160
|
return super if block_given? ||
|
132
161
|
primary_key.nil? ||
|
133
|
-
|
134
|
-
columns_hash.
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
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
|
162
|
+
scope_attributes? ||
|
163
|
+
columns_hash.key?(inheritance_column) && !base_class?
|
164
|
+
|
165
|
+
id = ids.first
|
166
|
+
|
167
|
+
return super if StatementCache.unsupported_value?(id)
|
168
|
+
|
145
169
|
key = primary_key
|
146
170
|
|
147
|
-
|
148
|
-
|
149
|
-
where(key => params.bind).limit(1)
|
150
|
-
}
|
171
|
+
statement = cached_find_by_statement(key) { |params|
|
172
|
+
where(key => params.bind).limit(1)
|
151
173
|
}
|
152
|
-
|
174
|
+
|
175
|
+
record = statement.execute([id], connection)&.first
|
153
176
|
unless record
|
154
|
-
raise RecordNotFound
|
177
|
+
raise RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id)
|
155
178
|
end
|
156
179
|
record
|
157
|
-
rescue RangeError
|
158
|
-
raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
|
159
180
|
end
|
160
181
|
|
161
|
-
def find_by(*args)
|
162
|
-
return super if
|
163
|
-
|
182
|
+
def find_by(*args) # :nodoc:
|
183
|
+
return super if scope_attributes? || reflect_on_all_aggregations.any? ||
|
184
|
+
columns_hash.key?(inheritance_column) && !base_class?
|
164
185
|
|
165
186
|
hash = args.first
|
166
187
|
|
167
|
-
return super if hash.values.any? { |v|
|
168
|
-
|
188
|
+
return super if !(Hash === hash) || hash.values.any? { |v|
|
189
|
+
StatementCache.unsupported_value?(v)
|
169
190
|
}
|
170
191
|
|
171
192
|
# We can't cache Post.find_by(author: david) ...yet
|
172
193
|
return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
|
173
194
|
|
174
|
-
|
195
|
+
keys = hash.keys
|
175
196
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
wheres = key.each_with_object({}) { |param,o|
|
180
|
-
o[param] = params.bind
|
181
|
-
}
|
182
|
-
klass.where(wheres).limit(1)
|
197
|
+
statement = cached_find_by_statement(keys) { |params|
|
198
|
+
wheres = keys.each_with_object({}) { |param, o|
|
199
|
+
o[param] = params.bind
|
183
200
|
}
|
201
|
+
where(wheres).limit(1)
|
184
202
|
}
|
185
203
|
begin
|
186
|
-
|
187
|
-
rescue TypeError
|
188
|
-
raise ActiveRecord::StatementInvalid
|
189
|
-
rescue RangeError
|
190
|
-
nil
|
204
|
+
statement.execute(hash.values, connection)&.first
|
205
|
+
rescue TypeError
|
206
|
+
raise ActiveRecord::StatementInvalid
|
191
207
|
end
|
192
208
|
end
|
193
209
|
|
194
|
-
def find_by!(*args)
|
195
|
-
find_by(*args)
|
210
|
+
def find_by!(*args) # :nodoc:
|
211
|
+
find_by(*args) || raise(RecordNotFound.new("Couldn't find #{name}", name))
|
196
212
|
end
|
197
213
|
|
198
|
-
def initialize_generated_modules
|
214
|
+
def initialize_generated_modules # :nodoc:
|
199
215
|
generated_association_methods
|
200
216
|
end
|
201
217
|
|
202
|
-
def generated_association_methods
|
218
|
+
def generated_association_methods # :nodoc:
|
203
219
|
@generated_association_methods ||= begin
|
204
220
|
mod = const_set(:GeneratedAssociationMethods, Module.new)
|
221
|
+
private_constant :GeneratedAssociationMethods
|
205
222
|
include mod
|
223
|
+
|
206
224
|
mod
|
207
225
|
end
|
208
226
|
end
|
209
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
|
+
|
210
240
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
211
|
-
def inspect
|
241
|
+
def inspect # :nodoc:
|
212
242
|
if self == Base
|
213
243
|
super
|
214
244
|
elsif abstract_class?
|
@@ -216,48 +246,66 @@ module ActiveRecord
|
|
216
246
|
elsif !connected?
|
217
247
|
"#{super} (call '#{super}.connection' to establish a connection)"
|
218
248
|
elsif table_exists?
|
219
|
-
attr_list =
|
249
|
+
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
|
220
250
|
"#{super}(#{attr_list})"
|
221
251
|
else
|
222
252
|
"#{super}(Table doesn't exist)"
|
223
253
|
end
|
224
254
|
end
|
225
255
|
|
226
|
-
# Overwrite the default class equality method to provide support for
|
227
|
-
def ===(object)
|
256
|
+
# Overwrite the default class equality method to provide support for decorated models.
|
257
|
+
def ===(object) # :nodoc:
|
228
258
|
object.is_a?(self)
|
229
259
|
end
|
230
260
|
|
231
261
|
# Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
|
232
262
|
#
|
233
263
|
# class Post < ActiveRecord::Base
|
234
|
-
# scope :published_and_commented, -> { published.and(
|
264
|
+
# scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
|
235
265
|
# end
|
236
266
|
def arel_table # :nodoc:
|
237
|
-
@arel_table ||= Arel::Table.new(table_name,
|
267
|
+
@arel_table ||= Arel::Table.new(table_name, type_caster: type_caster)
|
238
268
|
end
|
239
269
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
270
|
+
def arel_attribute(name, table = arel_table) # :nodoc:
|
271
|
+
name = name.to_s
|
272
|
+
name = attribute_aliases[name] || name
|
273
|
+
table[name]
|
274
|
+
end
|
275
|
+
|
276
|
+
def predicate_builder # :nodoc:
|
277
|
+
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
278
|
+
end
|
279
|
+
|
280
|
+
def type_caster # :nodoc:
|
281
|
+
TypeCaster::Map.new(self)
|
282
|
+
end
|
283
|
+
|
284
|
+
def _internal? # :nodoc:
|
285
|
+
false
|
248
286
|
end
|
249
287
|
|
250
288
|
private
|
251
289
|
|
252
|
-
|
253
|
-
|
290
|
+
def cached_find_by_statement(key, &block)
|
291
|
+
cache = @find_by_statement_cache[connection.prepared_statements]
|
292
|
+
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
293
|
+
end
|
294
|
+
|
295
|
+
def relation
|
296
|
+
relation = Relation.create(self)
|
254
297
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
298
|
+
if finder_needs_type_condition? && !ignore_default_scope?
|
299
|
+
relation.where!(type_condition)
|
300
|
+
relation.create_with!(inheritance_column.to_s => sti_name)
|
301
|
+
else
|
302
|
+
relation
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def table_metadata
|
307
|
+
TableMetadata.new(self, arel_table)
|
259
308
|
end
|
260
|
-
end
|
261
309
|
end
|
262
310
|
|
263
311
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
@@ -268,39 +316,50 @@ module ActiveRecord
|
|
268
316
|
# ==== Example:
|
269
317
|
# # Instantiates a single new object
|
270
318
|
# User.new(first_name: 'Jamie')
|
271
|
-
def initialize(attributes = nil
|
272
|
-
@
|
319
|
+
def initialize(attributes = nil)
|
320
|
+
@new_record = true
|
321
|
+
@attributes = self.class._default_attributes.deep_dup
|
273
322
|
|
274
323
|
init_internals
|
275
324
|
initialize_internals_callback
|
276
325
|
|
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
|
326
|
+
assign_attributes(attributes) if attributes
|
281
327
|
|
282
328
|
yield self if block_given?
|
283
329
|
_run_initialize_callbacks
|
284
330
|
end
|
285
331
|
|
286
|
-
# Initialize an empty model object from +coder+. +coder+
|
287
|
-
# the
|
288
|
-
#
|
332
|
+
# Initialize an empty model object from +coder+. +coder+ should be
|
333
|
+
# the result of previously encoding an Active Record model, using
|
334
|
+
# #encode_with.
|
289
335
|
#
|
290
336
|
# class Post < ActiveRecord::Base
|
291
337
|
# end
|
292
338
|
#
|
339
|
+
# old_post = Post.new(title: "hello world")
|
340
|
+
# coder = {}
|
341
|
+
# old_post.encode_with(coder)
|
342
|
+
#
|
293
343
|
# post = Post.allocate
|
294
|
-
# post.init_with(
|
344
|
+
# post.init_with(coder)
|
295
345
|
# post.title # => 'hello world'
|
296
|
-
def init_with(coder)
|
297
|
-
|
346
|
+
def init_with(coder, &block)
|
347
|
+
coder = LegacyYamlAdapter.convert(self.class, coder)
|
348
|
+
attributes = self.class.yaml_encoder.decode(coder)
|
349
|
+
init_with_attributes(attributes, coder["new_record"], &block)
|
350
|
+
end
|
298
351
|
|
299
|
-
|
352
|
+
##
|
353
|
+
# Initialize an empty model object from +attributes+.
|
354
|
+
# +attributes+ should be an attributes object, and unlike the
|
355
|
+
# `initialize` method, no assignment calls are made per attribute.
|
356
|
+
def init_with_attributes(attributes, new_record = false) # :nodoc:
|
357
|
+
@new_record = new_record
|
358
|
+
@attributes = attributes
|
300
359
|
|
301
|
-
|
360
|
+
init_internals
|
302
361
|
|
303
|
-
self
|
362
|
+
yield self if block_given?
|
304
363
|
|
305
364
|
_run_find_callbacks
|
306
365
|
_run_initialize_callbacks
|
@@ -336,23 +395,22 @@ module ActiveRecord
|
|
336
395
|
|
337
396
|
##
|
338
397
|
def initialize_dup(other) # :nodoc:
|
339
|
-
@attributes = @attributes.
|
340
|
-
@attributes.reset(
|
398
|
+
@attributes = @attributes.deep_dup
|
399
|
+
@attributes.reset(@primary_key)
|
341
400
|
|
342
401
|
_run_initialize_callbacks
|
343
402
|
|
344
|
-
@
|
345
|
-
@
|
346
|
-
|
347
|
-
@
|
348
|
-
@destroyed = false
|
403
|
+
@new_record = true
|
404
|
+
@destroyed = false
|
405
|
+
@_start_transaction_state = nil
|
406
|
+
@transaction_state = nil
|
349
407
|
|
350
408
|
super
|
351
409
|
end
|
352
410
|
|
353
411
|
# Populate +coder+ with attributes about this record that should be
|
354
412
|
# serialized. The structure of +coder+ defined in this method is
|
355
|
-
# guaranteed to match the structure of +coder+ passed to the
|
413
|
+
# guaranteed to match the structure of +coder+ passed to the #init_with
|
356
414
|
# method.
|
357
415
|
#
|
358
416
|
# Example:
|
@@ -363,10 +421,9 @@ module ActiveRecord
|
|
363
421
|
# Post.new.encode_with(coder)
|
364
422
|
# coder # => {"attributes" => {"id" => nil, ... }}
|
365
423
|
def encode_with(coder)
|
366
|
-
|
367
|
-
coder[
|
368
|
-
coder[
|
369
|
-
coder['new_record'] = new_record?
|
424
|
+
self.class.yaml_encoder.encode(@attributes, coder)
|
425
|
+
coder["new_record"] = new_record?
|
426
|
+
coder["active_record_yaml_version"] = 2
|
370
427
|
end
|
371
428
|
|
372
429
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
@@ -390,7 +447,7 @@ module ActiveRecord
|
|
390
447
|
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
391
448
|
def hash
|
392
449
|
if id
|
393
|
-
id.hash
|
450
|
+
self.class.hash ^ id.hash
|
394
451
|
else
|
395
452
|
super
|
396
453
|
end
|
@@ -406,18 +463,27 @@ module ActiveRecord
|
|
406
463
|
|
407
464
|
# Returns +true+ if the attributes hash has been frozen.
|
408
465
|
def frozen?
|
466
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
409
467
|
@attributes.frozen?
|
410
468
|
end
|
411
469
|
|
412
470
|
# Allows sort on objects
|
413
471
|
def <=>(other_object)
|
414
472
|
if other_object.is_a?(self.class)
|
415
|
-
|
473
|
+
to_key <=> other_object.to_key
|
416
474
|
else
|
417
475
|
super
|
418
476
|
end
|
419
477
|
end
|
420
478
|
|
479
|
+
def present? # :nodoc:
|
480
|
+
true
|
481
|
+
end
|
482
|
+
|
483
|
+
def blank? # :nodoc:
|
484
|
+
false
|
485
|
+
end
|
486
|
+
|
421
487
|
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
|
422
488
|
# attributes will be marked as read only since they cannot be saved.
|
423
489
|
def readonly?
|
@@ -438,129 +504,96 @@ module ActiveRecord
|
|
438
504
|
# We check defined?(@attributes) not to issue warnings if the object is
|
439
505
|
# allocated but not initialized.
|
440
506
|
inspection = if defined?(@attributes) && @attributes
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
507
|
+
self.class.attribute_names.collect do |name|
|
508
|
+
if has_attribute?(name)
|
509
|
+
attr = _read_attribute(name)
|
510
|
+
value = if attr.nil?
|
511
|
+
attr.inspect
|
512
|
+
else
|
513
|
+
attr = format_for_inspect(attr)
|
514
|
+
inspection_filter.filter_param(name, attr)
|
515
|
+
end
|
516
|
+
"#{name}: #{value}"
|
517
|
+
end
|
518
|
+
end.compact.join(", ")
|
519
|
+
else
|
520
|
+
"not initialized"
|
521
|
+
end
|
522
|
+
|
449
523
|
"#<#{self.class} #{inspection}>"
|
450
524
|
end
|
451
525
|
|
452
|
-
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from
|
526
|
+
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
|
453
527
|
# when pp is required.
|
454
528
|
def pretty_print(pp)
|
529
|
+
return super if custom_inspect_method_defined?
|
455
530
|
pp.object_address_group(self) do
|
456
531
|
if defined?(@attributes) && @attributes
|
457
|
-
|
458
|
-
pp.seplist(
|
459
|
-
|
460
|
-
pp.breakable ' '
|
532
|
+
attr_names = self.class.attribute_names.select { |name| has_attribute?(name) }
|
533
|
+
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
534
|
+
pp.breakable " "
|
461
535
|
pp.group(1) do
|
462
|
-
pp.text
|
463
|
-
pp.text
|
536
|
+
pp.text attr_name
|
537
|
+
pp.text ":"
|
464
538
|
pp.breakable
|
465
|
-
|
539
|
+
value = _read_attribute(attr_name)
|
540
|
+
value = inspection_filter.filter_param(attr_name, value) unless value.nil?
|
541
|
+
pp.pp value
|
466
542
|
end
|
467
543
|
end
|
468
544
|
else
|
469
|
-
pp.breakable
|
470
|
-
pp.text
|
545
|
+
pp.breakable " "
|
546
|
+
pp.text "not initialized"
|
471
547
|
end
|
472
548
|
end
|
473
549
|
end
|
474
550
|
|
475
551
|
# Returns a hash of the given methods with their names as keys and returned values as values.
|
476
552
|
def slice(*methods)
|
477
|
-
Hash[methods.map! { |method| [method, public_send(method)] }].with_indifferent_access
|
478
|
-
end
|
479
|
-
|
480
|
-
def set_transaction_state(state) # :nodoc:
|
481
|
-
@transaction_state = state
|
482
|
-
end
|
483
|
-
|
484
|
-
def has_transactional_callbacks? # :nodoc:
|
485
|
-
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_create_callbacks.empty?
|
553
|
+
Hash[methods.flatten.map! { |method| [method, public_send(method)] }].with_indifferent_access
|
486
554
|
end
|
487
555
|
|
488
556
|
private
|
489
557
|
|
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
|
558
|
+
# +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
|
559
|
+
# the array, and then rescues from the possible +NoMethodError+. If those elements are
|
560
|
+
# +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have,
|
561
|
+
# which significantly impacts upon performance.
|
562
|
+
#
|
563
|
+
# So we can avoid the +method_missing+ hit by explicitly defining +#to_ary+ as +nil+ here.
|
564
|
+
#
|
565
|
+
# See also https://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
|
566
|
+
def to_ary
|
567
|
+
nil
|
522
568
|
end
|
523
|
-
end
|
524
569
|
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
def to_ary # :nodoc:
|
534
|
-
nil
|
535
|
-
end
|
570
|
+
def init_internals
|
571
|
+
@primary_key = self.class.primary_key
|
572
|
+
@readonly = false
|
573
|
+
@destroyed = false
|
574
|
+
@marked_for_destruction = false
|
575
|
+
@destroyed_by_association = nil
|
576
|
+
@_start_transaction_state = nil
|
577
|
+
@transaction_state = nil
|
536
578
|
|
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
|
579
|
+
self.class.define_attribute_methods
|
580
|
+
end
|
550
581
|
|
551
|
-
|
552
|
-
|
582
|
+
def initialize_internals_callback
|
583
|
+
end
|
553
584
|
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
assign_attributes(attributes)
|
558
|
-
end
|
585
|
+
def custom_inspect_method_defined?
|
586
|
+
self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
|
587
|
+
end
|
559
588
|
|
560
|
-
|
561
|
-
|
562
|
-
|
589
|
+
def inspection_filter
|
590
|
+
@inspection_filter ||= begin
|
591
|
+
mask = DelegateClass(::String).new(ActiveSupport::ParameterFilter::FILTERED)
|
592
|
+
def mask.pretty_print(pp)
|
593
|
+
pp.text __getobj__
|
594
|
+
end
|
595
|
+
ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
|
596
|
+
end
|
563
597
|
end
|
564
|
-
end
|
565
598
|
end
|
566
599
|
end
|