activerecord 4.2.0 → 6.0.5.1
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 +852 -801
- data/MIT-LICENSE +4 -2
- data/README.rdoc +14 -13
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +267 -249
- data/lib/active_record/association_relation.rb +26 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -36
- data/lib/active_record/associations/association.rb +137 -55
- data/lib/active_record/associations/association_scope.rb +110 -132
- 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 +58 -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 +150 -275
- data/lib/active_record/associations/collection_proxy.rb +253 -152
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +35 -84
- 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 +43 -78
- 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 +159 -162
- data/lib/active_record/associations/preloader/association.rb +102 -113
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +96 -95
- data/lib/active_record/associations/singular_association.rb +18 -45
- data/lib/active_record/associations/through_association.rb +49 -24
- data/lib/active_record/associations.rb +1737 -1596
- data/lib/active_record/attribute_assignment.rb +57 -185
- data/lib/active_record/attribute_decorators.rb +39 -17
- data/lib/active_record/attribute_methods/before_type_cast.rb +14 -5
- data/lib/active_record/attribute_methods/dirty.rb +174 -134
- data/lib/active_record/attribute_methods/primary_key.rb +90 -84
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -77
- data/lib/active_record/attribute_methods/serialization.rb +40 -21
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -37
- data/lib/active_record/attribute_methods/write.rb +33 -56
- data/lib/active_record/attribute_methods.rb +124 -143
- data/lib/active_record/attributes.rb +213 -74
- data/lib/active_record/autosave_association.rb +125 -54
- data/lib/active_record/base.rb +60 -49
- data/lib/active_record/callbacks.rb +101 -76
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +36 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +810 -291
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +253 -108
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +83 -24
- 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 -47
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +383 -239
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +736 -235
- data/lib/active_record/connection_adapters/abstract/transaction.rb +190 -87
- data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -192
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +536 -600
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -153
- 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 +196 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +71 -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 +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -196
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +71 -115
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +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 +17 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/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 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -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 +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +465 -291
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +565 -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 +119 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +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 +299 -364
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_handling.rb +167 -41
- data/lib/active_record/core.rb +277 -233
- data/lib/active_record/counter_cache.rb +71 -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 +78 -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 -106
- data/lib/active_record/enum.rb +172 -89
- data/lib/active_record/errors.rb +189 -53
- data/lib/active_record/explain.rb +22 -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 +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +225 -497
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +158 -115
- 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 +99 -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 +87 -0
- data/lib/active_record/middleware/database_selector.rb +74 -0
- data/lib/active_record/migration/command_recorder.rb +166 -91
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +636 -290
- data/lib/active_record/model_schema.rb +344 -112
- data/lib/active_record/nested_attributes.rb +265 -215
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +559 -125
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +44 -30
- data/lib/active_record/railtie.rb +166 -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 +341 -202
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +461 -302
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +206 -55
- data/lib/active_record/relation/calculations.rb +270 -249
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +287 -255
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +86 -68
- 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 +112 -92
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +612 -392
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -17
- data/lib/active_record/relation/where_clause.rb +189 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/relation.rb +533 -340
- data/lib/active_record/result.rb +79 -43
- 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 +98 -82
- data/lib/active_record/scoping/named.rb +91 -33
- data/lib/active_record/scoping.rb +45 -27
- 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 +90 -0
- data/lib/active_record/tasks/database_tasks.rb +309 -99
- data/lib/active_record/tasks/mysql_database_tasks.rb +58 -89
- data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -31
- data/lib/active_record/tasks/sqlite_database_tasks.rb +37 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +243 -0
- data/lib/active_record/timestamp.rb +86 -41
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +222 -146
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +126 -0
- data/lib/active_record/type/date.rb +4 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +29 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +21 -16
- data/lib/active_record/type/type_map.rb +16 -19
- data/lib/active_record/type/unsigned_integer.rb +9 -8
- data/lib/active_record/type.rb +77 -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 +12 -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 +38 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +44 -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 +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/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/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +62 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +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 +30 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +174 -63
- 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/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -30
- data/lib/active_record/type/decimal.rb +0 -40
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -55
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
data/lib/active_record/core.rb
CHANGED
@@ -1,7 +1,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,184 @@ 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
|
130
|
+
|
131
|
+
##
|
132
|
+
# :singleton-method:
|
133
|
+
# Application configurable boolean that instructs the YAML Coder to use
|
134
|
+
# an unsafe load if set to true.
|
135
|
+
mattr_accessor :use_yaml_unsafe_load, instance_writer: false, default: false
|
136
|
+
|
137
|
+
# Application configurable array that provides additional permitted classes
|
138
|
+
# to Psych safe_load in the YAML Coder
|
139
|
+
mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: []
|
96
140
|
|
97
141
|
class_attribute :default_connection_handler, instance_writer: false
|
98
|
-
|
142
|
+
|
143
|
+
self.filter_attributes = []
|
99
144
|
|
100
145
|
def self.connection_handler
|
101
|
-
|
146
|
+
Thread.current.thread_variable_get("ar_connection_handler") || default_connection_handler
|
102
147
|
end
|
103
148
|
|
104
149
|
def self.connection_handler=(handler)
|
105
|
-
|
150
|
+
Thread.current.thread_variable_set("ar_connection_handler", handler)
|
106
151
|
end
|
107
152
|
|
108
153
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
109
154
|
end
|
110
155
|
|
111
156
|
module ClassMethods
|
112
|
-
def
|
113
|
-
|
114
|
-
super
|
157
|
+
def initialize_find_by_cache # :nodoc:
|
158
|
+
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
115
159
|
end
|
116
160
|
|
117
|
-
def
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
def inherited(child_class)
|
161
|
+
def inherited(child_class) # :nodoc:
|
162
|
+
# initialize cache at class definition for thread safety
|
122
163
|
child_class.initialize_find_by_cache
|
123
164
|
super
|
124
165
|
end
|
125
166
|
|
126
|
-
def find(*ids)
|
167
|
+
def find(*ids) # :nodoc:
|
127
168
|
# We don't have cache keys for this stuff yet
|
128
169
|
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
170
|
return super if block_given? ||
|
132
171
|
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
|
172
|
+
scope_attributes? ||
|
173
|
+
columns_hash.key?(inheritance_column) && !base_class?
|
174
|
+
|
175
|
+
id = ids.first
|
176
|
+
|
177
|
+
return super if StatementCache.unsupported_value?(id)
|
178
|
+
|
145
179
|
key = primary_key
|
146
180
|
|
147
|
-
|
148
|
-
|
149
|
-
where(key => params.bind).limit(1)
|
150
|
-
}
|
181
|
+
statement = cached_find_by_statement(key) { |params|
|
182
|
+
where(key => params.bind).limit(1)
|
151
183
|
}
|
152
|
-
|
184
|
+
|
185
|
+
record = statement.execute([id], connection)&.first
|
153
186
|
unless record
|
154
|
-
raise RecordNotFound
|
187
|
+
raise RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id)
|
155
188
|
end
|
156
189
|
record
|
157
|
-
rescue RangeError
|
158
|
-
raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
|
159
190
|
end
|
160
191
|
|
161
|
-
def find_by(*args)
|
162
|
-
return super if
|
163
|
-
|
192
|
+
def find_by(*args) # :nodoc:
|
193
|
+
return super if scope_attributes? || reflect_on_all_aggregations.any? ||
|
194
|
+
columns_hash.key?(inheritance_column) && !base_class?
|
164
195
|
|
165
196
|
hash = args.first
|
166
197
|
|
167
|
-
return super if hash.values.any? { |v|
|
168
|
-
|
198
|
+
return super if !(Hash === hash) || hash.values.any? { |v|
|
199
|
+
StatementCache.unsupported_value?(v)
|
169
200
|
}
|
170
201
|
|
171
202
|
# We can't cache Post.find_by(author: david) ...yet
|
172
203
|
return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
|
173
204
|
|
174
|
-
|
205
|
+
keys = hash.keys
|
175
206
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
wheres = key.each_with_object({}) { |param,o|
|
180
|
-
o[param] = params.bind
|
181
|
-
}
|
182
|
-
klass.where(wheres).limit(1)
|
207
|
+
statement = cached_find_by_statement(keys) { |params|
|
208
|
+
wheres = keys.each_with_object({}) { |param, o|
|
209
|
+
o[param] = params.bind
|
183
210
|
}
|
211
|
+
where(wheres).limit(1)
|
184
212
|
}
|
185
213
|
begin
|
186
|
-
|
187
|
-
rescue TypeError
|
188
|
-
raise ActiveRecord::StatementInvalid
|
189
|
-
rescue RangeError
|
190
|
-
nil
|
214
|
+
statement.execute(hash.values, connection)&.first
|
215
|
+
rescue TypeError
|
216
|
+
raise ActiveRecord::StatementInvalid
|
191
217
|
end
|
192
218
|
end
|
193
219
|
|
194
|
-
def find_by!(*args)
|
195
|
-
find_by(*args)
|
220
|
+
def find_by!(*args) # :nodoc:
|
221
|
+
find_by(*args) || raise(RecordNotFound.new("Couldn't find #{name}", name))
|
196
222
|
end
|
197
223
|
|
198
|
-
def initialize_generated_modules
|
224
|
+
def initialize_generated_modules # :nodoc:
|
199
225
|
generated_association_methods
|
200
226
|
end
|
201
227
|
|
202
|
-
def generated_association_methods
|
228
|
+
def generated_association_methods # :nodoc:
|
203
229
|
@generated_association_methods ||= begin
|
204
230
|
mod = const_set(:GeneratedAssociationMethods, Module.new)
|
231
|
+
private_constant :GeneratedAssociationMethods
|
205
232
|
include mod
|
233
|
+
|
206
234
|
mod
|
207
235
|
end
|
208
236
|
end
|
209
237
|
|
238
|
+
# Returns columns which shouldn't be exposed while calling +#inspect+.
|
239
|
+
def filter_attributes
|
240
|
+
if defined?(@filter_attributes)
|
241
|
+
@filter_attributes
|
242
|
+
else
|
243
|
+
superclass.filter_attributes
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# Specifies columns which shouldn't be exposed while calling +#inspect+.
|
248
|
+
attr_writer :filter_attributes
|
249
|
+
|
210
250
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
211
|
-
def inspect
|
251
|
+
def inspect # :nodoc:
|
212
252
|
if self == Base
|
213
253
|
super
|
214
254
|
elsif abstract_class?
|
@@ -216,48 +256,64 @@ module ActiveRecord
|
|
216
256
|
elsif !connected?
|
217
257
|
"#{super} (call '#{super}.connection' to establish a connection)"
|
218
258
|
elsif table_exists?
|
219
|
-
attr_list =
|
259
|
+
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
|
220
260
|
"#{super}(#{attr_list})"
|
221
261
|
else
|
222
262
|
"#{super}(Table doesn't exist)"
|
223
263
|
end
|
224
264
|
end
|
225
265
|
|
226
|
-
# Overwrite the default class equality method to provide support for
|
227
|
-
def ===(object)
|
266
|
+
# Overwrite the default class equality method to provide support for decorated models.
|
267
|
+
def ===(object) # :nodoc:
|
228
268
|
object.is_a?(self)
|
229
269
|
end
|
230
270
|
|
231
271
|
# Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
|
232
272
|
#
|
233
273
|
# class Post < ActiveRecord::Base
|
234
|
-
# scope :published_and_commented, -> { published.and(
|
274
|
+
# scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
|
235
275
|
# end
|
236
276
|
def arel_table # :nodoc:
|
237
|
-
@arel_table ||= Arel::Table.new(table_name,
|
277
|
+
@arel_table ||= Arel::Table.new(table_name, type_caster: type_caster)
|
238
278
|
end
|
239
279
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
280
|
+
def arel_attribute(name, table = arel_table) # :nodoc:
|
281
|
+
name = name.to_s
|
282
|
+
name = attribute_aliases[name] || name
|
283
|
+
table[name]
|
284
|
+
end
|
285
|
+
|
286
|
+
def predicate_builder # :nodoc:
|
287
|
+
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
288
|
+
end
|
289
|
+
|
290
|
+
def type_caster # :nodoc:
|
291
|
+
TypeCaster::Map.new(self)
|
292
|
+
end
|
293
|
+
|
294
|
+
def _internal? # :nodoc:
|
295
|
+
false
|
296
|
+
end
|
297
|
+
|
298
|
+
def cached_find_by_statement(key, &block) # :nodoc:
|
299
|
+
cache = @find_by_statement_cache[connection.prepared_statements]
|
300
|
+
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
248
301
|
end
|
249
302
|
|
250
303
|
private
|
304
|
+
def relation
|
305
|
+
relation = Relation.create(self)
|
251
306
|
|
252
|
-
|
253
|
-
|
307
|
+
if finder_needs_type_condition? && !ignore_default_scope?
|
308
|
+
relation.where!(type_condition)
|
309
|
+
else
|
310
|
+
relation
|
311
|
+
end
|
312
|
+
end
|
254
313
|
|
255
|
-
|
256
|
-
|
257
|
-
else
|
258
|
-
relation
|
314
|
+
def table_metadata
|
315
|
+
TableMetadata.new(self, arel_table)
|
259
316
|
end
|
260
|
-
end
|
261
317
|
end
|
262
318
|
|
263
319
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
@@ -268,39 +324,50 @@ module ActiveRecord
|
|
268
324
|
# ==== Example:
|
269
325
|
# # Instantiates a single new object
|
270
326
|
# User.new(first_name: 'Jamie')
|
271
|
-
def initialize(attributes = nil
|
272
|
-
@
|
327
|
+
def initialize(attributes = nil)
|
328
|
+
@new_record = true
|
329
|
+
@attributes = self.class._default_attributes.deep_dup
|
273
330
|
|
274
331
|
init_internals
|
275
332
|
initialize_internals_callback
|
276
333
|
|
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
|
334
|
+
assign_attributes(attributes) if attributes
|
281
335
|
|
282
336
|
yield self if block_given?
|
283
337
|
_run_initialize_callbacks
|
284
338
|
end
|
285
339
|
|
286
|
-
# Initialize an empty model object from +coder+. +coder+
|
287
|
-
# the
|
288
|
-
#
|
340
|
+
# Initialize an empty model object from +coder+. +coder+ should be
|
341
|
+
# the result of previously encoding an Active Record model, using
|
342
|
+
# #encode_with.
|
289
343
|
#
|
290
344
|
# class Post < ActiveRecord::Base
|
291
345
|
# end
|
292
346
|
#
|
347
|
+
# old_post = Post.new(title: "hello world")
|
348
|
+
# coder = {}
|
349
|
+
# old_post.encode_with(coder)
|
350
|
+
#
|
293
351
|
# post = Post.allocate
|
294
|
-
# post.init_with(
|
352
|
+
# post.init_with(coder)
|
295
353
|
# post.title # => 'hello world'
|
296
|
-
def init_with(coder)
|
297
|
-
|
354
|
+
def init_with(coder, &block)
|
355
|
+
coder = LegacyYamlAdapter.convert(self.class, coder)
|
356
|
+
attributes = self.class.yaml_encoder.decode(coder)
|
357
|
+
init_with_attributes(attributes, coder["new_record"], &block)
|
358
|
+
end
|
298
359
|
|
299
|
-
|
360
|
+
##
|
361
|
+
# Initialize an empty model object from +attributes+.
|
362
|
+
# +attributes+ should be an attributes object, and unlike the
|
363
|
+
# `initialize` method, no assignment calls are made per attribute.
|
364
|
+
def init_with_attributes(attributes, new_record = false) # :nodoc:
|
365
|
+
@new_record = new_record
|
366
|
+
@attributes = attributes
|
300
367
|
|
301
|
-
|
368
|
+
init_internals
|
302
369
|
|
303
|
-
self
|
370
|
+
yield self if block_given?
|
304
371
|
|
305
372
|
_run_find_callbacks
|
306
373
|
_run_initialize_callbacks
|
@@ -336,23 +403,22 @@ module ActiveRecord
|
|
336
403
|
|
337
404
|
##
|
338
405
|
def initialize_dup(other) # :nodoc:
|
339
|
-
@attributes = @attributes.
|
340
|
-
@attributes.reset(
|
406
|
+
@attributes = @attributes.deep_dup
|
407
|
+
@attributes.reset(@primary_key)
|
341
408
|
|
342
409
|
_run_initialize_callbacks
|
343
410
|
|
344
|
-
@
|
345
|
-
@
|
346
|
-
|
347
|
-
@
|
348
|
-
@destroyed = false
|
411
|
+
@new_record = true
|
412
|
+
@destroyed = false
|
413
|
+
@_start_transaction_state = nil
|
414
|
+
@transaction_state = nil
|
349
415
|
|
350
416
|
super
|
351
417
|
end
|
352
418
|
|
353
419
|
# Populate +coder+ with attributes about this record that should be
|
354
420
|
# serialized. The structure of +coder+ defined in this method is
|
355
|
-
# guaranteed to match the structure of +coder+ passed to the
|
421
|
+
# guaranteed to match the structure of +coder+ passed to the #init_with
|
356
422
|
# method.
|
357
423
|
#
|
358
424
|
# Example:
|
@@ -363,10 +429,9 @@ module ActiveRecord
|
|
363
429
|
# Post.new.encode_with(coder)
|
364
430
|
# coder # => {"attributes" => {"id" => nil, ... }}
|
365
431
|
def encode_with(coder)
|
366
|
-
|
367
|
-
coder[
|
368
|
-
coder[
|
369
|
-
coder['new_record'] = new_record?
|
432
|
+
self.class.yaml_encoder.encode(@attributes, coder)
|
433
|
+
coder["new_record"] = new_record?
|
434
|
+
coder["active_record_yaml_version"] = 2
|
370
435
|
end
|
371
436
|
|
372
437
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
@@ -390,7 +455,7 @@ module ActiveRecord
|
|
390
455
|
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
391
456
|
def hash
|
392
457
|
if id
|
393
|
-
id.hash
|
458
|
+
self.class.hash ^ id.hash
|
394
459
|
else
|
395
460
|
super
|
396
461
|
end
|
@@ -406,18 +471,27 @@ module ActiveRecord
|
|
406
471
|
|
407
472
|
# Returns +true+ if the attributes hash has been frozen.
|
408
473
|
def frozen?
|
474
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
409
475
|
@attributes.frozen?
|
410
476
|
end
|
411
477
|
|
412
478
|
# Allows sort on objects
|
413
479
|
def <=>(other_object)
|
414
480
|
if other_object.is_a?(self.class)
|
415
|
-
|
481
|
+
to_key <=> other_object.to_key
|
416
482
|
else
|
417
483
|
super
|
418
484
|
end
|
419
485
|
end
|
420
486
|
|
487
|
+
def present? # :nodoc:
|
488
|
+
true
|
489
|
+
end
|
490
|
+
|
491
|
+
def blank? # :nodoc:
|
492
|
+
false
|
493
|
+
end
|
494
|
+
|
421
495
|
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
|
422
496
|
# attributes will be marked as read only since they cannot be saved.
|
423
497
|
def readonly?
|
@@ -438,129 +512,99 @@ module ActiveRecord
|
|
438
512
|
# We check defined?(@attributes) not to issue warnings if the object is
|
439
513
|
# allocated but not initialized.
|
440
514
|
inspection = if defined?(@attributes) && @attributes
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
515
|
+
self.class.attribute_names.collect do |name|
|
516
|
+
if has_attribute?(name)
|
517
|
+
attr = _read_attribute(name)
|
518
|
+
value = if attr.nil?
|
519
|
+
attr.inspect
|
520
|
+
else
|
521
|
+
attr = format_for_inspect(attr)
|
522
|
+
inspection_filter.filter_param(name, attr)
|
523
|
+
end
|
524
|
+
"#{name}: #{value}"
|
525
|
+
end
|
526
|
+
end.compact.join(", ")
|
527
|
+
else
|
528
|
+
"not initialized"
|
529
|
+
end
|
530
|
+
|
449
531
|
"#<#{self.class} #{inspection}>"
|
450
532
|
end
|
451
533
|
|
452
|
-
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from
|
534
|
+
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
|
453
535
|
# when pp is required.
|
454
536
|
def pretty_print(pp)
|
537
|
+
return super if custom_inspect_method_defined?
|
455
538
|
pp.object_address_group(self) do
|
456
539
|
if defined?(@attributes) && @attributes
|
457
|
-
|
458
|
-
pp.seplist(
|
459
|
-
|
460
|
-
pp.breakable ' '
|
540
|
+
attr_names = self.class.attribute_names.select { |name| has_attribute?(name) }
|
541
|
+
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
542
|
+
pp.breakable " "
|
461
543
|
pp.group(1) do
|
462
|
-
pp.text
|
463
|
-
pp.text
|
544
|
+
pp.text attr_name
|
545
|
+
pp.text ":"
|
464
546
|
pp.breakable
|
465
|
-
|
547
|
+
value = _read_attribute(attr_name)
|
548
|
+
value = inspection_filter.filter_param(attr_name, value) unless value.nil?
|
549
|
+
pp.pp value
|
466
550
|
end
|
467
551
|
end
|
468
552
|
else
|
469
|
-
pp.breakable
|
470
|
-
pp.text
|
553
|
+
pp.breakable " "
|
554
|
+
pp.text "not initialized"
|
471
555
|
end
|
472
556
|
end
|
473
557
|
end
|
474
558
|
|
475
559
|
# Returns a hash of the given methods with their names as keys and returned values as values.
|
476
560
|
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?
|
561
|
+
Hash[methods.flatten.map! { |method| [method, public_send(method)] }].with_indifferent_access
|
486
562
|
end
|
487
563
|
|
488
564
|
private
|
565
|
+
# +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
|
566
|
+
# the array, and then rescues from the possible +NoMethodError+. If those elements are
|
567
|
+
# +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have,
|
568
|
+
# which significantly impacts upon performance.
|
569
|
+
#
|
570
|
+
# So we can avoid the +method_missing+ hit by explicitly defining +#to_ary+ as +nil+ here.
|
571
|
+
#
|
572
|
+
# See also https://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
|
573
|
+
def to_ary
|
574
|
+
nil
|
575
|
+
end
|
489
576
|
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
# TransactionState.
|
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
|
577
|
+
def init_internals
|
578
|
+
@primary_key = self.class.primary_key
|
579
|
+
@readonly = false
|
580
|
+
@destroyed = false
|
581
|
+
@marked_for_destruction = false
|
582
|
+
@destroyed_by_association = nil
|
583
|
+
@_start_transaction_state = nil
|
584
|
+
@transaction_state = nil
|
518
585
|
|
519
|
-
|
520
|
-
update_attributes_from_transaction_state(transaction_state.parent, depth+1)
|
521
|
-
end
|
586
|
+
self.class.define_attribute_methods
|
522
587
|
end
|
523
|
-
end
|
524
|
-
|
525
|
-
# Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
|
526
|
-
# of the array, and then rescues from the possible NoMethodError. If those elements are
|
527
|
-
# ActiveRecord::Base's, then this triggers the various method_missing's that we have,
|
528
|
-
# which significantly impacts upon performance.
|
529
|
-
#
|
530
|
-
# So we can avoid the method_missing hit by explicitly defining #to_ary as nil here.
|
531
|
-
#
|
532
|
-
# See also http://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
|
533
|
-
def to_ary # :nodoc:
|
534
|
-
nil
|
535
|
-
end
|
536
588
|
|
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
|
589
|
+
def initialize_internals_callback
|
590
|
+
end
|
550
591
|
|
551
|
-
|
552
|
-
|
592
|
+
def custom_inspect_method_defined?
|
593
|
+
self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
|
594
|
+
end
|
553
595
|
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
596
|
+
class InspectionMask < DelegateClass(::String)
|
597
|
+
def pretty_print(pp)
|
598
|
+
pp.text __getobj__
|
599
|
+
end
|
600
|
+
end
|
601
|
+
private_constant :InspectionMask
|
559
602
|
|
560
|
-
|
561
|
-
|
562
|
-
|
603
|
+
def inspection_filter
|
604
|
+
@inspection_filter ||= begin
|
605
|
+
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
606
|
+
ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
|
607
|
+
end
|
563
608
|
end
|
564
|
-
end
|
565
609
|
end
|
566
610
|
end
|