activerecord 5.0.7.2 → 6.0.6.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 +4 -4
- data/CHANGELOG.md +844 -1944
- data/MIT-LICENSE +3 -1
- data/README.rdoc +9 -7
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +18 -14
- data/lib/active_record/associations/alias_tracker.rb +24 -34
- data/lib/active_record/associations/association.rb +113 -55
- data/lib/active_record/associations/association_scope.rb +102 -96
- data/lib/active_record/associations/belongs_to_association.rb +58 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +18 -25
- data/lib/active_record/associations/builder/belongs_to.rb +43 -54
- data/lib/active_record/associations/builder/collection_association.rb +7 -18
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
- data/lib/active_record/associations/builder/has_many.rb +4 -0
- data/lib/active_record/associations/builder/has_one.rb +37 -1
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +93 -254
- data/lib/active_record/associations/collection_proxy.rb +159 -122
- data/lib/active_record/associations/foreign_association.rb +9 -0
- data/lib/active_record/associations/has_many_association.rb +23 -30
- data/lib/active_record/associations/has_many_through_association.rb +58 -44
- data/lib/active_record/associations/has_one_association.rb +59 -54
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +43 -85
- 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 +152 -177
- data/lib/active_record/associations/preloader/association.rb +101 -97
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/preloader.rb +94 -103
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +27 -15
- data/lib/active_record/associations.rb +1603 -1592
- data/lib/active_record/attribute_assignment.rb +54 -61
- data/lib/active_record/attribute_decorators.rb +38 -17
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
- data/lib/active_record/attribute_methods/dirty.rb +179 -109
- data/lib/active_record/attribute_methods/primary_key.rb +85 -92
- data/lib/active_record/attribute_methods/query.rb +4 -3
- data/lib/active_record/attribute_methods/read.rb +20 -49
- data/lib/active_record/attribute_methods/serialization.rb +29 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
- data/lib/active_record/attribute_methods/write.rb +34 -33
- data/lib/active_record/attribute_methods.rb +66 -106
- data/lib/active_record/attributes.rb +38 -25
- data/lib/active_record/autosave_association.rb +58 -39
- data/lib/active_record/base.rb +27 -24
- data/lib/active_record/callbacks.rb +64 -35
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +34 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +558 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +128 -75
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +233 -147
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
- data/lib/active_record/connection_adapters/abstract_adapter.rb +373 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -562
- data/lib/active_record/connection_adapters/column.rb +41 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
- data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +12 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
- data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +261 -267
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +143 -40
- data/lib/active_record/core.rb +207 -160
- data/lib/active_record/counter_cache.rb +60 -28
- 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 -87
- data/lib/active_record/enum.rb +67 -23
- data/lib/active_record/errors.rb +114 -18
- data/lib/active_record/explain.rb +4 -4
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +13 -8
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +194 -504
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +150 -99
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +116 -25
- data/lib/active_record/internal_metadata.rb +16 -19
- data/lib/active_record/legacy_yaml_adapter.rb +4 -2
- data/lib/active_record/locking/optimistic.rb +85 -86
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +48 -29
- data/lib/active_record/middleware/database_selector/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 +134 -100
- data/lib/active_record/migration/compatibility.rb +174 -56
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +369 -302
- data/lib/active_record/model_schema.rb +160 -127
- data/lib/active_record/nested_attributes.rb +213 -202
- data/lib/active_record/no_touching.rb +12 -3
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +446 -77
- data/lib/active_record/query_cache.rb +13 -12
- data/lib/active_record/querying.rb +37 -24
- data/lib/active_record/railtie.rb +128 -36
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +312 -177
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +214 -254
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/batches.rb +98 -52
- data/lib/active_record/relation/calculations.rb +212 -173
- data/lib/active_record/relation/delegation.rb +73 -69
- data/lib/active_record/relation/finder_methods.rb +207 -247
- data/lib/active_record/relation/from_clause.rb +6 -8
- data/lib/active_record/relation/merger.rb +82 -61
- data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +83 -105
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +488 -332
- data/lib/active_record/relation/record_fetch_warning.rb +5 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +111 -96
- data/lib/active_record/relation/where_clause_factory.rb +6 -11
- data/lib/active_record/relation.rb +443 -318
- data/lib/active_record/result.rb +69 -40
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +83 -99
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +71 -69
- data/lib/active_record/schema_migration.rb +16 -6
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +51 -26
- data/lib/active_record/scoping.rb +20 -20
- data/lib/active_record/secure_token.rb +4 -2
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +63 -28
- data/lib/active_record/store.rb +121 -41
- data/lib/active_record/suppressor.rb +6 -3
- data/lib/active_record/table_metadata.rb +39 -18
- data/lib/active_record/tasks/database_tasks.rb +271 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
- data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +243 -0
- data/lib/active_record/timestamp.rb +70 -36
- data/lib/active_record/touch_later.rb +8 -6
- data/lib/active_record/transactions.rb +141 -157
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +44 -48
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +16 -9
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +12 -1
- data/lib/active_record/type/type_map.rb +14 -17
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type.rb +23 -18
- data/lib/active_record/type_caster/connection.rb +17 -12
- data/lib/active_record/type_caster/map.rb +5 -4
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +3 -2
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +29 -42
- data/lib/active_record/validations.rb +7 -5
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +37 -22
- 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/migration/migration_generator.rb +37 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
- data/lib/rails/generators/active_record/migration.rb +17 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +138 -52
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set/builder.rb +0 -132
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
- /data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/filters"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Integration
|
@@ -7,17 +9,32 @@ module ActiveRecord
|
|
7
9
|
included do
|
8
10
|
##
|
9
11
|
# :singleton-method:
|
10
|
-
# Indicates the format used to generate the timestamp in the cache key
|
11
|
-
# Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
|
12
|
+
# Indicates the format used to generate the timestamp in the cache key, if
|
13
|
+
# versioning is off. Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
|
12
14
|
#
|
13
15
|
# This is +:usec+, by default.
|
14
|
-
class_attribute :cache_timestamp_format, :
|
15
|
-
|
16
|
+
class_attribute :cache_timestamp_format, instance_writer: false, default: :usec
|
17
|
+
|
18
|
+
##
|
19
|
+
# :singleton-method:
|
20
|
+
# Indicates whether to use a stable #cache_key method that is accompanied
|
21
|
+
# by a changing version in the #cache_version method.
|
22
|
+
#
|
23
|
+
# This is +true+, by default on Rails 5.2 and above.
|
24
|
+
class_attribute :cache_versioning, instance_writer: false, default: false
|
25
|
+
|
26
|
+
##
|
27
|
+
# :singleton-method:
|
28
|
+
# Indicates whether to use a stable #cache_key method that is accompanied
|
29
|
+
# by a changing version in the #cache_version method on collections.
|
30
|
+
#
|
31
|
+
# This is +false+, by default until Rails 6.1.
|
32
|
+
class_attribute :collection_cache_versioning, instance_writer: false, default: false
|
16
33
|
end
|
17
34
|
|
18
|
-
# Returns a String
|
19
|
-
# object. The default implementation returns this record's id as a String
|
20
|
-
# or nil if this record's unsaved.
|
35
|
+
# Returns a +String+, which Action Pack uses for constructing a URL to this
|
36
|
+
# object. The default implementation returns this record's id as a +String+,
|
37
|
+
# or +nil+ if this record's unsaved.
|
21
38
|
#
|
22
39
|
# For example, suppose that you have a User model, and that you have a
|
23
40
|
# <tt>resources :users</tt> route. Normally, +user_path+ will
|
@@ -42,32 +59,64 @@ module ActiveRecord
|
|
42
59
|
id && id.to_s # Be sure to stringify the id for routes
|
43
60
|
end
|
44
61
|
|
45
|
-
# Returns a cache key that can be used to identify this record.
|
62
|
+
# Returns a stable cache key that can be used to identify this record.
|
46
63
|
#
|
47
64
|
# Product.new.cache_key # => "products/new"
|
48
|
-
# Product.find(5).cache_key # => "products/5"
|
49
|
-
# Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
|
65
|
+
# Product.find(5).cache_key # => "products/5"
|
50
66
|
#
|
51
|
-
#
|
52
|
-
#
|
67
|
+
# If ActiveRecord::Base.cache_versioning is turned off, as it was in Rails 5.1 and earlier,
|
68
|
+
# the cache key will also include a version.
|
53
69
|
#
|
54
|
-
#
|
55
|
-
|
70
|
+
# Product.cache_versioning = false
|
71
|
+
# Product.find(5).cache_key # => "products/5-20071224150000" (updated_at available)
|
72
|
+
def cache_key
|
56
73
|
if new_record?
|
57
74
|
"#{model_name.cache_key}/new"
|
58
75
|
else
|
59
|
-
|
60
|
-
|
76
|
+
if cache_version
|
77
|
+
"#{model_name.cache_key}/#{id}"
|
61
78
|
else
|
62
|
-
max_updated_column_timestamp
|
79
|
+
timestamp = max_updated_column_timestamp
|
80
|
+
|
81
|
+
if timestamp
|
82
|
+
timestamp = timestamp.utc.to_s(cache_timestamp_format)
|
83
|
+
"#{model_name.cache_key}/#{id}-#{timestamp}"
|
84
|
+
else
|
85
|
+
"#{model_name.cache_key}/#{id}"
|
86
|
+
end
|
63
87
|
end
|
88
|
+
end
|
89
|
+
end
|
64
90
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
91
|
+
# Returns a cache version that can be used together with the cache key to form
|
92
|
+
# a recyclable caching scheme. By default, the #updated_at column is used for the
|
93
|
+
# cache_version, but this method can be overwritten to return something else.
|
94
|
+
#
|
95
|
+
# Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to
|
96
|
+
# +false+ (which it is by default until Rails 6.0).
|
97
|
+
def cache_version
|
98
|
+
return unless cache_versioning
|
99
|
+
|
100
|
+
if has_attribute?("updated_at")
|
101
|
+
timestamp = updated_at_before_type_cast
|
102
|
+
if can_use_fast_cache_version?(timestamp)
|
103
|
+
raw_timestamp_to_cache_version(timestamp)
|
104
|
+
elsif timestamp = updated_at
|
105
|
+
timestamp.utc.to_s(cache_timestamp_format)
|
70
106
|
end
|
107
|
+
else
|
108
|
+
if self.class.has_attribute?("updated_at")
|
109
|
+
raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns a cache key along with the version.
|
115
|
+
def cache_key_with_version
|
116
|
+
if version = cache_version
|
117
|
+
"#{cache_key}-#{version}"
|
118
|
+
else
|
119
|
+
cache_key
|
71
120
|
end
|
72
121
|
end
|
73
122
|
|
@@ -89,7 +138,7 @@ module ActiveRecord
|
|
89
138
|
#
|
90
139
|
# user = User.find_by(name: 'David Heinemeier Hansson')
|
91
140
|
# user.id # => 125
|
92
|
-
# user_path(user) # => "/users/125-david"
|
141
|
+
# user_path(user) # => "/users/125-david-heinemeier"
|
93
142
|
#
|
94
143
|
# Because the generated param begins with the record's +id+, it is
|
95
144
|
# suitable for passing to +find+. In a controller, for example:
|
@@ -103,7 +152,7 @@ module ActiveRecord
|
|
103
152
|
define_method :to_param do
|
104
153
|
if (default = super()) &&
|
105
154
|
(result = send(method_name).to_s).present? &&
|
106
|
-
(param = result.squish.truncate(20, separator:
|
155
|
+
(param = result.squish.parameterize.truncate(20, separator: /-/, omission: "")).present?
|
107
156
|
"#{default}-#{param}"
|
108
157
|
else
|
109
158
|
default
|
@@ -111,6 +160,48 @@ module ActiveRecord
|
|
111
160
|
end
|
112
161
|
end
|
113
162
|
end
|
163
|
+
|
164
|
+
def collection_cache_key(collection = all, timestamp_column = :updated_at) # :nodoc:
|
165
|
+
collection.send(:compute_cache_key, timestamp_column)
|
166
|
+
end
|
114
167
|
end
|
168
|
+
|
169
|
+
private
|
170
|
+
# Detects if the value before type cast
|
171
|
+
# can be used to generate a cache_version.
|
172
|
+
#
|
173
|
+
# The fast cache version only works with a
|
174
|
+
# string value directly from the database.
|
175
|
+
#
|
176
|
+
# We also must check if the timestamp format has been changed
|
177
|
+
# or if the timezone is not set to UTC then
|
178
|
+
# we cannot apply our transformations correctly.
|
179
|
+
def can_use_fast_cache_version?(timestamp)
|
180
|
+
timestamp.is_a?(String) &&
|
181
|
+
cache_timestamp_format == :usec &&
|
182
|
+
default_timezone == :utc &&
|
183
|
+
!updated_at_came_from_user?
|
184
|
+
end
|
185
|
+
|
186
|
+
# Converts a raw database string to `:usec`
|
187
|
+
# format.
|
188
|
+
#
|
189
|
+
# Example:
|
190
|
+
#
|
191
|
+
# timestamp = "2018-10-15 20:02:15.266505"
|
192
|
+
# raw_timestamp_to_cache_version(timestamp)
|
193
|
+
# # => "20181015200215266505"
|
194
|
+
#
|
195
|
+
# PostgreSQL truncates trailing zeros,
|
196
|
+
# https://github.com/postgres/postgres/commit/3e1beda2cde3495f41290e1ece5d544525810214
|
197
|
+
# to account for this we pad the output with zeros
|
198
|
+
def raw_timestamp_to_cache_version(timestamp)
|
199
|
+
key = timestamp.delete("- :.")
|
200
|
+
if key.length < 20
|
201
|
+
key.ljust(20, "0")
|
202
|
+
else
|
203
|
+
key
|
204
|
+
end
|
205
|
+
end
|
115
206
|
end
|
116
207
|
end
|
@@ -1,25 +1,27 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/scoping/default"
|
4
|
+
require "active_record/scoping/named"
|
3
5
|
|
4
6
|
module ActiveRecord
|
5
7
|
# This class is used to create a table that keeps track of values and keys such
|
6
8
|
# as which environment migrations were run in.
|
7
9
|
class InternalMetadata < ActiveRecord::Base # :nodoc:
|
8
10
|
class << self
|
11
|
+
def _internal?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
9
15
|
def primary_key
|
10
16
|
"key"
|
11
17
|
end
|
12
18
|
|
13
19
|
def table_name
|
14
|
-
"#{table_name_prefix}#{
|
15
|
-
end
|
16
|
-
|
17
|
-
def original_table_name
|
18
|
-
"#{table_name_prefix}active_record_internal_metadatas#{table_name_suffix}"
|
20
|
+
"#{table_name_prefix}#{internal_metadata_table_name}#{table_name_suffix}"
|
19
21
|
end
|
20
22
|
|
21
23
|
def []=(key, value)
|
22
|
-
find_or_initialize_by(key: key).
|
24
|
+
find_or_initialize_by(key: key).update!(value: value)
|
23
25
|
end
|
24
26
|
|
25
27
|
def [](key)
|
@@ -27,30 +29,25 @@ module ActiveRecord
|
|
27
29
|
end
|
28
30
|
|
29
31
|
def table_exists?
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
def original_table_exists?
|
34
|
-
# This method will be removed in Rails 5.1
|
35
|
-
# Since it is only necessary when `active_record_internal_metadatas` could exist
|
36
|
-
ActiveSupport::Deprecation.silence { connection.table_exists?(original_table_name) }
|
32
|
+
connection.table_exists?(table_name)
|
37
33
|
end
|
38
34
|
|
39
35
|
# Creates an internal metadata table with columns +key+ and +value+
|
40
36
|
def create_table
|
41
|
-
if original_table_exists?
|
42
|
-
connection.rename_table(original_table_name, table_name)
|
43
|
-
end
|
44
37
|
unless table_exists?
|
45
38
|
key_options = connection.internal_string_options_for_primary_key
|
46
39
|
|
47
40
|
connection.create_table(table_name, id: false) do |t|
|
48
|
-
t.string :key, key_options
|
41
|
+
t.string :key, **key_options
|
49
42
|
t.string :value
|
50
43
|
t.timestamps
|
51
44
|
end
|
52
45
|
end
|
53
46
|
end
|
47
|
+
|
48
|
+
def drop_table
|
49
|
+
connection.drop_table table_name, if_exists: true
|
50
|
+
end
|
54
51
|
end
|
55
52
|
end
|
56
53
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module LegacyYamlAdapter
|
3
5
|
def self.convert(klass, coder)
|
4
6
|
return coder unless coder.is_a?(Psych::Coder)
|
5
7
|
|
6
8
|
case coder["active_record_yaml_version"]
|
7
|
-
when 1 then coder
|
9
|
+
when 1, 2 then coder
|
8
10
|
else
|
9
|
-
if coder["attributes"].is_a?(AttributeSet)
|
11
|
+
if coder["attributes"].is_a?(ActiveModel::AttributeSet)
|
10
12
|
Rails420.convert(klass, coder)
|
11
13
|
else
|
12
14
|
Rails41.convert(klass, coder)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Locking
|
3
5
|
# == What is Optimistic Locking
|
@@ -51,22 +53,24 @@ module ActiveRecord
|
|
51
53
|
extend ActiveSupport::Concern
|
52
54
|
|
53
55
|
included do
|
54
|
-
class_attribute :lock_optimistically, instance_writer: false
|
55
|
-
self.lock_optimistically = true
|
56
|
+
class_attribute :lock_optimistically, instance_writer: false, default: true
|
56
57
|
end
|
57
58
|
|
58
59
|
def locking_enabled? #:nodoc:
|
59
60
|
self.class.locking_enabled?
|
60
61
|
end
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
def increment!(*, **) #:nodoc:
|
64
|
+
super.tap do
|
65
|
+
if locking_enabled?
|
66
|
+
self[self.class.locking_column] += 1
|
67
|
+
clear_attribute_change(self.class.locking_column)
|
68
|
+
end
|
67
69
|
end
|
70
|
+
end
|
68
71
|
|
69
|
-
|
72
|
+
private
|
73
|
+
def _create_record(attribute_names = self.attribute_names)
|
70
74
|
if locking_enabled?
|
71
75
|
# We always want to persist the locking version, even if we don't detect
|
72
76
|
# a change from the default, since the database might have no default
|
@@ -75,118 +79,113 @@ module ActiveRecord
|
|
75
79
|
super
|
76
80
|
end
|
77
81
|
|
78
|
-
def
|
82
|
+
def _touch_row(attribute_names, time)
|
83
|
+
@_touch_attr_names << self.class.locking_column if locking_enabled?
|
84
|
+
super
|
85
|
+
end
|
86
|
+
|
87
|
+
def _update_row(attribute_names, attempted_action = "update")
|
79
88
|
return super unless locking_enabled?
|
80
|
-
return 0 if attribute_names.empty?
|
81
89
|
|
82
|
-
|
83
|
-
|
84
|
-
|
90
|
+
begin
|
91
|
+
locking_column = self.class.locking_column
|
92
|
+
previous_lock_value = read_attribute_before_type_cast(locking_column)
|
93
|
+
attribute_names << locking_column
|
85
94
|
|
86
|
-
|
87
|
-
attribute_names.uniq!
|
95
|
+
self[locking_column] += 1
|
88
96
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
self.class.primary_key => id,
|
94
|
-
lock_col => previous_lock_value,
|
95
|
-
).update_all(
|
96
|
-
attributes_for_update(attribute_names).map do |name|
|
97
|
-
[name, _read_attribute(name)]
|
98
|
-
end.to_h
|
97
|
+
affected_rows = self.class._update_record(
|
98
|
+
attributes_with_values(attribute_names),
|
99
|
+
@primary_key => id_in_database,
|
100
|
+
locking_column => previous_lock_value
|
99
101
|
)
|
100
102
|
|
101
|
-
|
102
|
-
raise ActiveRecord::StaleObjectError.new(self,
|
103
|
+
if affected_rows != 1
|
104
|
+
raise ActiveRecord::StaleObjectError.new(self, attempted_action)
|
103
105
|
end
|
104
106
|
|
105
107
|
affected_rows
|
106
108
|
|
107
|
-
# If something went wrong, revert the
|
109
|
+
# If something went wrong, revert the locking_column value.
|
108
110
|
rescue Exception
|
109
|
-
|
111
|
+
self[locking_column] = previous_lock_value.to_i
|
110
112
|
raise
|
111
113
|
end
|
112
114
|
end
|
113
115
|
|
114
116
|
def destroy_row
|
115
|
-
|
117
|
+
return super unless locking_enabled?
|
116
118
|
|
117
|
-
|
119
|
+
locking_column = self.class.locking_column
|
120
|
+
|
121
|
+
affected_rows = self.class._delete_record(
|
122
|
+
@primary_key => id_in_database,
|
123
|
+
locking_column => read_attribute_before_type_cast(locking_column)
|
124
|
+
)
|
125
|
+
|
126
|
+
if affected_rows != 1
|
118
127
|
raise ActiveRecord::StaleObjectError.new(self, "destroy")
|
119
128
|
end
|
120
129
|
|
121
130
|
affected_rows
|
122
131
|
end
|
123
132
|
|
124
|
-
|
125
|
-
|
133
|
+
module ClassMethods
|
134
|
+
DEFAULT_LOCKING_COLUMN = "lock_version"
|
126
135
|
|
127
|
-
if
|
128
|
-
|
129
|
-
|
136
|
+
# Returns true if the +lock_optimistically+ flag is set to true
|
137
|
+
# (which it is, by default) and the table includes the
|
138
|
+
# +locking_column+ column (defaults to +lock_version+).
|
139
|
+
def locking_enabled?
|
140
|
+
lock_optimistically && columns_hash[locking_column]
|
130
141
|
end
|
131
142
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
# Returns true if the +lock_optimistically+ flag is set to true
|
139
|
-
# (which it is, by default) and the table includes the
|
140
|
-
# +locking_column+ column (defaults to +lock_version+).
|
141
|
-
def locking_enabled?
|
142
|
-
lock_optimistically && columns_hash[locking_column]
|
143
|
-
end
|
144
|
-
|
145
|
-
# Set the column to use for optimistic locking. Defaults to +lock_version+.
|
146
|
-
def locking_column=(value)
|
147
|
-
reload_schema_from_cache
|
148
|
-
@locking_column = value.to_s
|
149
|
-
end
|
143
|
+
# Set the column to use for optimistic locking. Defaults to +lock_version+.
|
144
|
+
def locking_column=(value)
|
145
|
+
reload_schema_from_cache
|
146
|
+
@locking_column = value.to_s
|
147
|
+
end
|
150
148
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
149
|
+
# The version column used for optimistic locking. Defaults to +lock_version+.
|
150
|
+
def locking_column
|
151
|
+
@locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
|
152
|
+
@locking_column
|
153
|
+
end
|
156
154
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
155
|
+
# Reset the column used for optimistic locking back to the +lock_version+ default.
|
156
|
+
def reset_locking_column
|
157
|
+
self.locking_column = DEFAULT_LOCKING_COLUMN
|
158
|
+
end
|
161
159
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
160
|
+
# Make sure the lock version column gets updated when counters are
|
161
|
+
# updated.
|
162
|
+
def update_counters(id, counters)
|
163
|
+
counters = counters.merge(locking_column => 1) if locking_enabled?
|
164
|
+
super
|
165
|
+
end
|
168
166
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
167
|
+
private
|
168
|
+
# We need to apply this decorator here, rather than on module inclusion. The closure
|
169
|
+
# created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the
|
170
|
+
# sub class being decorated. As such, changes to `lock_optimistically`, or
|
171
|
+
# `locking_column` would not be picked up.
|
172
|
+
def inherited(subclass)
|
173
|
+
subclass.class_eval do
|
174
|
+
is_lock_column = ->(name, _) { lock_optimistically && name == locking_column }
|
175
|
+
decorate_matching_attribute_types(is_lock_column, "_optimistic_locking") do |type|
|
176
|
+
LockingType.new(type)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
super
|
180
180
|
end
|
181
|
-
end
|
182
|
-
super
|
183
181
|
end
|
184
|
-
end
|
185
182
|
end
|
186
183
|
|
184
|
+
# In de/serialize we change `nil` to 0, so that we can allow passing
|
185
|
+
# `nil` values to `lock_version`, and not result in `ActiveRecord::StaleObjectError`
|
186
|
+
# during update record.
|
187
187
|
class LockingType < DelegateClass(Type::Value) # :nodoc:
|
188
188
|
def deserialize(value)
|
189
|
-
# `nil` *should* be changed to 0
|
190
189
|
super.to_i
|
191
190
|
end
|
192
191
|
|
@@ -195,11 +194,11 @@ module ActiveRecord
|
|
195
194
|
end
|
196
195
|
|
197
196
|
def init_with(coder)
|
198
|
-
__setobj__(coder[
|
197
|
+
__setobj__(coder["subtype"])
|
199
198
|
end
|
200
199
|
|
201
200
|
def encode_with(coder)
|
202
|
-
coder[
|
201
|
+
coder["subtype"] = __getobj__
|
203
202
|
end
|
204
203
|
end
|
205
204
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Locking
|
3
5
|
# Locking::Pessimistic provides support for row-level locking using
|
@@ -12,9 +14,9 @@ module ActiveRecord
|
|
12
14
|
# of your own such as 'LOCK IN SHARE MODE' or 'FOR UPDATE NOWAIT'. Example:
|
13
15
|
#
|
14
16
|
# Account.transaction do
|
15
|
-
# # select * from accounts where name = 'shugo' limit 1 for update
|
16
|
-
# shugo = Account.
|
17
|
-
# yuko = Account.
|
17
|
+
# # select * from accounts where name = 'shugo' limit 1 for update nowait
|
18
|
+
# shugo = Account.lock("FOR UPDATE NOWAIT").find_by(name: "shugo")
|
19
|
+
# yuko = Account.lock("FOR UPDATE NOWAIT").find_by(name: "yuko")
|
18
20
|
# shugo.balance -= 100
|
19
21
|
# shugo.save!
|
20
22
|
# yuko.balance += 100
|
@@ -51,15 +53,25 @@ module ActiveRecord
|
|
51
53
|
# end
|
52
54
|
#
|
53
55
|
# Database-specific information on row locking:
|
54
|
-
# MySQL:
|
55
|
-
# PostgreSQL:
|
56
|
+
# MySQL: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
|
57
|
+
# PostgreSQL: https://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
|
56
58
|
module Pessimistic
|
57
59
|
# Obtain a row lock on this record. Reloads the record to obtain the requested
|
58
60
|
# lock. Pass an SQL locking clause to append the end of the SELECT statement
|
59
61
|
# or pass true for "FOR UPDATE" (the default, an exclusive row lock). Returns
|
60
62
|
# the locked record.
|
61
63
|
def lock!(lock = true)
|
62
|
-
|
64
|
+
if persisted?
|
65
|
+
if has_changes_to_save?
|
66
|
+
raise(<<-MSG.squish)
|
67
|
+
Locking a record with unpersisted changes is not supported. Use
|
68
|
+
`save` to persist the changes, or `reload` to discard them
|
69
|
+
explicitly.
|
70
|
+
MSG
|
71
|
+
end
|
72
|
+
|
73
|
+
reload(lock: lock)
|
74
|
+
end
|
63
75
|
self
|
64
76
|
end
|
65
77
|
|