activerecord 4.2.9 → 6.1.4.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 +964 -1382
- data/MIT-LICENSE +4 -2
- data/README.rdoc +15 -14
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +266 -251
- data/lib/active_record/association_relation.rb +40 -15
- data/lib/active_record/associations/alias_tracker.rb +40 -43
- data/lib/active_record/associations/association.rb +162 -69
- data/lib/active_record/associations/association_scope.rb +105 -130
- data/lib/active_record/associations/belongs_to_association.rb +83 -65
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +57 -43
- data/lib/active_record/associations/builder/belongs_to.rb +74 -57
- data/lib/active_record/associations/builder/collection_association.rb +15 -37
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
- data/lib/active_record/associations/builder/has_many.rb +13 -5
- data/lib/active_record/associations/builder/has_one.rb +44 -6
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +148 -287
- data/lib/active_record/associations/collection_proxy.rb +252 -150
- data/lib/active_record/associations/foreign_association.rb +23 -1
- data/lib/active_record/associations/has_many_association.rb +56 -98
- data/lib/active_record/associations/has_many_through_association.rb +68 -89
- data/lib/active_record/associations/has_one_association.rb +73 -47
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -81
- 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 +174 -169
- data/lib/active_record/associations/preloader/association.rb +108 -115
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +97 -94
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +39 -19
- data/lib/active_record/associations.rb +1845 -1598
- data/lib/active_record/attribute_assignment.rb +59 -185
- data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
- data/lib/active_record/attribute_methods/dirty.rb +168 -148
- data/lib/active_record/attribute_methods/primary_key.rb +93 -83
- data/lib/active_record/attribute_methods/query.rb +8 -10
- data/lib/active_record/attribute_methods/read.rb +19 -79
- data/lib/active_record/attribute_methods/serialization.rb +49 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +55 -36
- data/lib/active_record/attribute_methods/write.rb +24 -55
- data/lib/active_record/attribute_methods.rb +149 -154
- data/lib/active_record/attributes.rb +234 -78
- data/lib/active_record/autosave_association.rb +133 -60
- data/lib/active_record/base.rb +46 -46
- data/lib/active_record/callbacks.rb +234 -79
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +34 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
- data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
- data/lib/active_record/connection_adapters/column.rb +67 -40
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +194 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -160
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -58
- 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 +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -19
- 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 +31 -20
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +145 -48
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +496 -298
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +588 -375
- data/lib/active_record/connection_adapters/schema_cache.rb +167 -29
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -373
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +314 -41
- data/lib/active_record/core.rb +458 -241
- data/lib/active_record/counter_cache.rb +70 -49
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -106
- data/lib/active_record/enum.rb +211 -92
- data/lib/active_record/errors.rb +224 -54
- data/lib/active_record/explain.rb +27 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +33 -14
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +275 -500
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +175 -110
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +121 -29
- data/lib/active_record/internal_metadata.rb +62 -0
- data/lib/active_record/legacy_yaml_adapter.rb +27 -5
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +98 -92
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +93 -31
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +185 -90
- data/lib/active_record/migration/compatibility.rb +295 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +673 -325
- data/lib/active_record/model_schema.rb +418 -113
- data/lib/active_record/nested_attributes.rb +263 -224
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +572 -136
- data/lib/active_record/query_cache.rb +29 -23
- data/lib/active_record/querying.rb +50 -31
- data/lib/active_record/railtie.rb +170 -51
- data/lib/active_record/railties/console_sandbox.rb +3 -3
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +523 -199
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +454 -291
- data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
- data/lib/active_record/relation/batches.rb +217 -59
- data/lib/active_record/relation/calculations.rb +324 -249
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +316 -242
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +95 -103
- data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +136 -122
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +757 -413
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -20
- data/lib/active_record/relation/where_clause.rb +239 -0
- data/lib/active_record/relation.rb +554 -343
- data/lib/active_record/result.rb +91 -47
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +134 -122
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +141 -92
- data/lib/active_record/schema_migration.rb +24 -23
- data/lib/active_record/scoping/default.rb +96 -83
- data/lib/active_record/scoping/named.rb +78 -36
- data/lib/active_record/scoping.rb +45 -27
- data/lib/active_record/secure_token.rb +48 -0
- data/lib/active_record/serialization.rb +8 -6
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +89 -36
- data/lib/active_record/store.rb +128 -43
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +81 -0
- data/lib/active_record/tasks/database_tasks.rb +364 -130
- data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
- data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +86 -43
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +182 -163
- 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 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- 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 +27 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +21 -16
- data/lib/active_record/type/type_map.rb +16 -19
- data/lib/active_record/type/unsigned_integer.rb +9 -8
- data/lib/active_record/type.rb +84 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +12 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +63 -56
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +42 -29
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -4
- data/lib/rails/generators/active_record/migration.rb +35 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +172 -65
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_decorators.rb +0 -66
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- 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 -59
- 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 -40
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,35 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# See ActiveRecord::Transactions::ClassMethods for documentation.
|
3
5
|
module Transactions
|
4
6
|
extend ActiveSupport::Concern
|
5
7
|
#:nodoc:
|
6
8
|
ACTIONS = [:create, :destroy, :update]
|
7
|
-
#:nodoc:
|
8
|
-
CALLBACK_WARN_MESSAGE = "Currently, Active Record suppresses errors raised " \
|
9
|
-
"within `after_rollback`/`after_commit` callbacks and only print them to " \
|
10
|
-
"the logs. In the next version, these errors will no longer be suppressed. " \
|
11
|
-
"Instead, the errors will propagate normally just like in other Active " \
|
12
|
-
"Record callbacks.\n" \
|
13
|
-
"\n" \
|
14
|
-
"You can opt into the new behavior and remove this warning by setting:\n" \
|
15
|
-
"\n" \
|
16
|
-
" config.active_record.raise_in_transactional_callbacks = true\n\n"
|
17
9
|
|
18
10
|
included do
|
19
11
|
define_callbacks :commit, :rollback,
|
20
|
-
|
12
|
+
:before_commit,
|
21
13
|
scope: [:kind, :name]
|
22
|
-
|
23
|
-
mattr_accessor :raise_in_transactional_callbacks, instance_writer: false
|
24
|
-
self.raise_in_transactional_callbacks = false
|
25
14
|
end
|
26
15
|
|
27
16
|
# = Active Record Transactions
|
28
17
|
#
|
29
|
-
# Transactions are protective blocks where SQL statements are only permanent
|
18
|
+
# \Transactions are protective blocks where SQL statements are only permanent
|
30
19
|
# if they can all succeed as one atomic action. The classic example is a
|
31
20
|
# transfer between two accounts where you can only have a deposit if the
|
32
|
-
# withdrawal succeeded and vice versa. Transactions enforce the integrity of
|
21
|
+
# withdrawal succeeded and vice versa. \Transactions enforce the integrity of
|
33
22
|
# the database and guard the data against program errors or database
|
34
23
|
# break-downs. So basically you should use transaction blocks whenever you
|
35
24
|
# have a number of statements that must be executed together or not at all.
|
@@ -49,20 +38,20 @@ module ActiveRecord
|
|
49
38
|
#
|
50
39
|
# == Different Active Record classes in a single transaction
|
51
40
|
#
|
52
|
-
# Though the transaction class method is called on some Active Record class,
|
41
|
+
# Though the #transaction class method is called on some Active Record class,
|
53
42
|
# the objects within the transaction block need not all be instances of
|
54
43
|
# that class. This is because transactions are per-database connection, not
|
55
44
|
# per-model.
|
56
45
|
#
|
57
46
|
# In this example a +balance+ record is transactionally saved even
|
58
|
-
# though
|
47
|
+
# though #transaction is called on the +Account+ class:
|
59
48
|
#
|
60
49
|
# Account.transaction do
|
61
50
|
# balance.save!
|
62
51
|
# account.save!
|
63
52
|
# end
|
64
53
|
#
|
65
|
-
# The
|
54
|
+
# The #transaction method is also available as a model instance method.
|
66
55
|
# For example, you can also do this:
|
67
56
|
#
|
68
57
|
# balance.transaction do
|
@@ -89,7 +78,8 @@ module ActiveRecord
|
|
89
78
|
#
|
90
79
|
# == +save+ and +destroy+ are automatically wrapped in a transaction
|
91
80
|
#
|
92
|
-
# Both
|
81
|
+
# Both {#save}[rdoc-ref:Persistence#save] and
|
82
|
+
# {#destroy}[rdoc-ref:Persistence#destroy] come wrapped in a transaction that ensures
|
93
83
|
# that whatever you do in validations or callbacks will happen under its
|
94
84
|
# protected cover. So you can use validations to check for values that
|
95
85
|
# the transaction depends on or you can raise exceptions in the callbacks
|
@@ -98,7 +88,7 @@ module ActiveRecord
|
|
98
88
|
# As a consequence changes to the database are not seen outside your connection
|
99
89
|
# until the operation is complete. For example, if you try to update the index
|
100
90
|
# of a search engine in +after_save+ the indexer won't see the updated record.
|
101
|
-
# The
|
91
|
+
# The #after_commit callback is the only one that is triggered once the update
|
102
92
|
# is committed. See below.
|
103
93
|
#
|
104
94
|
# == Exception handling and rolling back
|
@@ -107,11 +97,11 @@ module ActiveRecord
|
|
107
97
|
# be propagated (after triggering the ROLLBACK), so you should be ready to
|
108
98
|
# catch those in your application code.
|
109
99
|
#
|
110
|
-
# One exception is the
|
100
|
+
# One exception is the ActiveRecord::Rollback exception, which will trigger
|
111
101
|
# a ROLLBACK when raised, but not be re-raised by the transaction block.
|
112
102
|
#
|
113
|
-
# *Warning*: one should not catch
|
114
|
-
# inside a transaction block.
|
103
|
+
# *Warning*: one should not catch ActiveRecord::StatementInvalid exceptions
|
104
|
+
# inside a transaction block. ActiveRecord::StatementInvalid exceptions indicate that an
|
115
105
|
# error occurred at the database level, for example when a unique constraint
|
116
106
|
# is violated. On some database systems, such as PostgreSQL, database errors
|
117
107
|
# inside a transaction cause the entire transaction to become unusable
|
@@ -132,16 +122,16 @@ module ActiveRecord
|
|
132
122
|
# # statement will cause a PostgreSQL error, even though the unique
|
133
123
|
# # constraint is no longer violated:
|
134
124
|
# Number.create(i: 1)
|
135
|
-
# # => "
|
125
|
+
# # => "PG::Error: ERROR: current transaction is aborted, commands
|
136
126
|
# # ignored until end of transaction block"
|
137
127
|
# end
|
138
128
|
#
|
139
129
|
# One should restart the entire transaction if an
|
140
|
-
#
|
130
|
+
# ActiveRecord::StatementInvalid occurred.
|
141
131
|
#
|
142
132
|
# == Nested transactions
|
143
133
|
#
|
144
|
-
#
|
134
|
+
# #transaction calls can be nested. By default, this makes all database
|
145
135
|
# statements in the nested transaction block become part of the parent
|
146
136
|
# transaction. For example, the following behavior may be surprising:
|
147
137
|
#
|
@@ -153,7 +143,7 @@ module ActiveRecord
|
|
153
143
|
# end
|
154
144
|
# end
|
155
145
|
#
|
156
|
-
# creates both "Kotori" and "Nemu". Reason is the
|
146
|
+
# creates both "Kotori" and "Nemu". Reason is the ActiveRecord::Rollback
|
157
147
|
# exception in the nested block does not issue a ROLLBACK. Since these exceptions
|
158
148
|
# are captured in transaction blocks, the parent block does not see it and the
|
159
149
|
# real transaction is committed.
|
@@ -171,34 +161,34 @@ module ActiveRecord
|
|
171
161
|
# end
|
172
162
|
# end
|
173
163
|
#
|
174
|
-
# only "Kotori" is created.
|
164
|
+
# only "Kotori" is created.
|
175
165
|
#
|
176
166
|
# Most databases don't support true nested transactions. At the time of
|
177
167
|
# writing, the only database that we're aware of that supports true nested
|
178
168
|
# transactions, is MS-SQL. Because of this, Active Record emulates nested
|
179
|
-
# transactions by using savepoints
|
180
|
-
#
|
169
|
+
# transactions by using savepoints. See
|
170
|
+
# https://dev.mysql.com/doc/refman/en/savepoint.html
|
181
171
|
# for more information about savepoints.
|
182
172
|
#
|
183
|
-
# === Callbacks
|
173
|
+
# === \Callbacks
|
184
174
|
#
|
185
175
|
# There are two types of callbacks associated with committing and rolling back transactions:
|
186
|
-
#
|
176
|
+
# #after_commit and #after_rollback.
|
187
177
|
#
|
188
|
-
#
|
189
|
-
# transaction immediately after the transaction is committed.
|
178
|
+
# #after_commit callbacks are called on every record saved or destroyed within a
|
179
|
+
# transaction immediately after the transaction is committed. #after_rollback callbacks
|
190
180
|
# are called on every record saved or destroyed within a transaction immediately after the
|
191
181
|
# transaction or savepoint is rolled back.
|
192
182
|
#
|
193
183
|
# These callbacks are useful for interacting with other systems since you will be guaranteed
|
194
184
|
# that the callback is only executed when the database is in a permanent state. For example,
|
195
|
-
#
|
185
|
+
# #after_commit is a good spot to put in a hook to clearing a cache since clearing it from
|
196
186
|
# within a transaction could trigger the cache to be regenerated before the database is updated.
|
197
187
|
#
|
198
188
|
# === Caveats
|
199
189
|
#
|
200
|
-
# If you're on MySQL, then do not use DDL operations in nested
|
201
|
-
# blocks that are emulated with savepoints. That is, do not execute statements
|
190
|
+
# If you're on MySQL, then do not use Data Definition Language (DDL) operations in nested
|
191
|
+
# transactions blocks that are emulated with savepoints. That is, do not execute statements
|
202
192
|
# like 'CREATE TABLE' inside such blocks. This is because MySQL automatically
|
203
193
|
# releases all savepoints upon executing a DDL operation. When +transaction+
|
204
194
|
# is finished and tries to release the savepoint it created earlier, a
|
@@ -206,18 +196,22 @@ module ActiveRecord
|
|
206
196
|
# automatically released. The following example demonstrates the problem:
|
207
197
|
#
|
208
198
|
# Model.connection.transaction do # BEGIN
|
209
|
-
# Model.connection.transaction(requires_new: true) do
|
199
|
+
# Model.connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
|
210
200
|
# Model.connection.create_table(...) # active_record_1 now automatically released
|
211
|
-
# end # RELEASE
|
201
|
+
# end # RELEASE SAVEPOINT active_record_1
|
212
202
|
# # ^^^^ BOOM! database error!
|
213
203
|
# end
|
214
204
|
#
|
215
205
|
# Note that "TRUNCATE" is also a MySQL DDL statement!
|
216
206
|
module ClassMethods
|
217
|
-
# See
|
218
|
-
def transaction(options
|
219
|
-
|
220
|
-
|
207
|
+
# See the ConnectionAdapters::DatabaseStatements#transaction API docs.
|
208
|
+
def transaction(**options, &block)
|
209
|
+
connection.transaction(**options, &block)
|
210
|
+
end
|
211
|
+
|
212
|
+
def before_commit(*args, &block) # :nodoc:
|
213
|
+
set_options_for_callbacks!(args)
|
214
|
+
set_callback(:before_commit, :before, *args, &block)
|
221
215
|
end
|
222
216
|
|
223
217
|
# This callback is called after a record has been created, updated, or destroyed.
|
@@ -232,109 +226,114 @@ module ActiveRecord
|
|
232
226
|
# after_commit :do_foo_bar, on: [:create, :update]
|
233
227
|
# after_commit :do_bar_baz, on: [:update, :destroy]
|
234
228
|
#
|
235
|
-
# Note that transactional fixtures do not play well with this feature. Please
|
236
|
-
# use the +test_after_commit+ gem to have these hooks fired in tests.
|
237
229
|
def after_commit(*args, &block)
|
238
230
|
set_options_for_callbacks!(args)
|
239
231
|
set_callback(:commit, :after, *args, &block)
|
240
|
-
|
241
|
-
|
242
|
-
|
232
|
+
end
|
233
|
+
|
234
|
+
# Shortcut for <tt>after_commit :hook, on: [ :create, :update ]</tt>.
|
235
|
+
def after_save_commit(*args, &block)
|
236
|
+
set_options_for_callbacks!(args, on: [ :create, :update ])
|
237
|
+
set_callback(:commit, :after, *args, &block)
|
238
|
+
end
|
239
|
+
|
240
|
+
# Shortcut for <tt>after_commit :hook, on: :create</tt>.
|
241
|
+
def after_create_commit(*args, &block)
|
242
|
+
set_options_for_callbacks!(args, on: :create)
|
243
|
+
set_callback(:commit, :after, *args, &block)
|
244
|
+
end
|
245
|
+
|
246
|
+
# Shortcut for <tt>after_commit :hook, on: :update</tt>.
|
247
|
+
def after_update_commit(*args, &block)
|
248
|
+
set_options_for_callbacks!(args, on: :update)
|
249
|
+
set_callback(:commit, :after, *args, &block)
|
250
|
+
end
|
251
|
+
|
252
|
+
# Shortcut for <tt>after_commit :hook, on: :destroy</tt>.
|
253
|
+
def after_destroy_commit(*args, &block)
|
254
|
+
set_options_for_callbacks!(args, on: :destroy)
|
255
|
+
set_callback(:commit, :after, *args, &block)
|
243
256
|
end
|
244
257
|
|
245
258
|
# This callback is called after a create, update, or destroy are rolled back.
|
246
259
|
#
|
247
|
-
# Please check the documentation of
|
260
|
+
# Please check the documentation of #after_commit for options.
|
248
261
|
def after_rollback(*args, &block)
|
249
262
|
set_options_for_callbacks!(args)
|
250
263
|
set_callback(:rollback, :after, *args, &block)
|
251
|
-
unless ActiveRecord::Base.raise_in_transactional_callbacks
|
252
|
-
ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
|
253
|
-
end
|
254
264
|
end
|
255
265
|
|
256
266
|
private
|
267
|
+
def set_options_for_callbacks!(args, enforced_options = {})
|
268
|
+
options = args.extract_options!.merge!(enforced_options)
|
269
|
+
args << options
|
257
270
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
271
|
+
if options[:on]
|
272
|
+
fire_on = Array(options[:on])
|
273
|
+
assert_valid_transaction_action(fire_on)
|
274
|
+
options[:if] = [
|
275
|
+
-> { transaction_include_any_action?(fire_on) },
|
276
|
+
*options[:if]
|
277
|
+
]
|
278
|
+
end
|
265
279
|
end
|
266
|
-
end
|
267
280
|
|
268
|
-
|
269
|
-
|
270
|
-
|
281
|
+
def assert_valid_transaction_action(actions)
|
282
|
+
if (actions - ACTIONS).any?
|
283
|
+
raise ArgumentError, ":on conditions for after_commit and after_rollback callbacks have to be one of #{ACTIONS}"
|
284
|
+
end
|
271
285
|
end
|
272
|
-
end
|
273
286
|
end
|
274
287
|
|
275
288
|
# See ActiveRecord::Transactions::ClassMethods for detailed documentation.
|
276
|
-
def transaction(options
|
277
|
-
self.class.transaction(options, &block)
|
289
|
+
def transaction(**options, &block)
|
290
|
+
self.class.transaction(**options, &block)
|
278
291
|
end
|
279
292
|
|
280
293
|
def destroy #:nodoc:
|
281
294
|
with_transaction_returning_status { super }
|
282
295
|
end
|
283
296
|
|
284
|
-
def save(
|
285
|
-
|
286
|
-
with_transaction_returning_status { super }
|
287
|
-
end
|
297
|
+
def save(**) #:nodoc:
|
298
|
+
with_transaction_returning_status { super }
|
288
299
|
end
|
289
300
|
|
290
|
-
def save!(
|
301
|
+
def save!(**) #:nodoc:
|
291
302
|
with_transaction_returning_status { super }
|
292
303
|
end
|
293
304
|
|
294
|
-
def touch(
|
305
|
+
def touch(*, **) #:nodoc:
|
295
306
|
with_transaction_returning_status { super }
|
296
307
|
end
|
297
308
|
|
298
|
-
|
299
|
-
|
300
|
-
remember_transaction_record_state
|
301
|
-
yield
|
302
|
-
rescue Exception
|
303
|
-
restore_transaction_record_state
|
304
|
-
raise
|
305
|
-
ensure
|
306
|
-
clear_transaction_record_state
|
309
|
+
def before_committed! # :nodoc:
|
310
|
+
_run_before_commit_callbacks
|
307
311
|
end
|
308
312
|
|
309
|
-
# Call the
|
313
|
+
# Call the #after_commit callbacks.
|
310
314
|
#
|
311
315
|
# Ensure that it is not called if the object was never persisted (failed create),
|
312
316
|
# but call it after the commit of a destroyed object.
|
313
|
-
def committed!(should_run_callbacks
|
314
|
-
_run_commit_callbacks if should_run_callbacks && destroyed? || persisted?
|
315
|
-
ensure
|
317
|
+
def committed!(should_run_callbacks: true) #:nodoc:
|
316
318
|
force_clear_transaction_record_state
|
319
|
+
if should_run_callbacks
|
320
|
+
@_committed_already_called = true
|
321
|
+
_run_commit_callbacks
|
322
|
+
end
|
323
|
+
ensure
|
324
|
+
@_committed_already_called = @_trigger_update_callback = @_trigger_destroy_callback = false
|
317
325
|
end
|
318
326
|
|
319
|
-
# Call the
|
327
|
+
# Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
|
320
328
|
# state should be rolled back to the beginning or just to the last savepoint.
|
321
|
-
def rolledback!(force_restore_state
|
322
|
-
|
329
|
+
def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
|
330
|
+
if should_run_callbacks
|
331
|
+
_run_rollback_callbacks
|
332
|
+
end
|
323
333
|
ensure
|
324
334
|
restore_transaction_record_state(force_restore_state)
|
325
335
|
clear_transaction_record_state
|
326
|
-
|
327
|
-
|
328
|
-
# Add the record to the current transaction so that the +after_rollback+ and +after_commit+ callbacks
|
329
|
-
# can be called.
|
330
|
-
def add_to_transaction
|
331
|
-
if has_transactional_callbacks?
|
332
|
-
self.class.connection.add_transaction_record(self)
|
333
|
-
else
|
334
|
-
sync_with_transaction_state
|
335
|
-
set_transaction_state(self.class.connection.transaction_state)
|
336
|
-
end
|
337
|
-
remember_transaction_record_state
|
336
|
+
@_trigger_update_callback = @_trigger_destroy_callback = false if force_restore_state
|
338
337
|
end
|
339
338
|
|
340
339
|
# Executes +method+ within a transaction and captures its return value as a
|
@@ -345,83 +344,103 @@ module ActiveRecord
|
|
345
344
|
# instance.
|
346
345
|
def with_transaction_returning_status
|
347
346
|
status = nil
|
348
|
-
self.class.
|
349
|
-
|
350
|
-
begin
|
351
|
-
status = yield
|
352
|
-
rescue ActiveRecord::Rollback
|
353
|
-
clear_transaction_record_state
|
354
|
-
status = nil
|
355
|
-
end
|
347
|
+
connection = self.class.connection
|
348
|
+
ensure_finalize = !connection.transaction_open?
|
356
349
|
|
350
|
+
connection.transaction do
|
351
|
+
add_to_transaction(ensure_finalize || has_transactional_callbacks?)
|
352
|
+
remember_transaction_record_state
|
353
|
+
|
354
|
+
status = yield
|
357
355
|
raise ActiveRecord::Rollback unless status
|
358
356
|
end
|
359
357
|
status
|
360
|
-
ensure
|
361
|
-
if @transaction_state && @transaction_state.committed?
|
362
|
-
clear_transaction_record_state
|
363
|
-
end
|
364
358
|
end
|
365
359
|
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
def remember_transaction_record_state #:nodoc:
|
370
|
-
@_start_transaction_state[:id] = id
|
371
|
-
@_start_transaction_state.reverse_merge!(
|
372
|
-
new_record: @new_record,
|
373
|
-
destroyed: @destroyed,
|
374
|
-
frozen?: frozen?,
|
375
|
-
)
|
376
|
-
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
|
360
|
+
def trigger_transactional_callbacks? # :nodoc:
|
361
|
+
(@_new_record_before_last_commit || _trigger_update_callback) && persisted? ||
|
362
|
+
_trigger_destroy_callback && destroyed?
|
377
363
|
end
|
378
364
|
|
379
|
-
|
380
|
-
|
381
|
-
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
|
382
|
-
force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
|
383
|
-
end
|
365
|
+
private
|
366
|
+
attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
|
384
367
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
368
|
+
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
369
|
+
def remember_transaction_record_state
|
370
|
+
@_start_transaction_state ||= {
|
371
|
+
id: id,
|
372
|
+
new_record: @new_record,
|
373
|
+
previously_new_record: @previously_new_record,
|
374
|
+
destroyed: @destroyed,
|
375
|
+
attributes: @attributes,
|
376
|
+
frozen?: frozen?,
|
377
|
+
level: 0
|
378
|
+
}
|
379
|
+
@_start_transaction_state[:level] += 1
|
389
380
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
if transaction_level < 1 || force
|
395
|
-
restore_state = @_start_transaction_state
|
396
|
-
thaw
|
397
|
-
@new_record = restore_state[:new_record]
|
398
|
-
@destroyed = restore_state[:destroyed]
|
399
|
-
pk = self.class.primary_key
|
400
|
-
if pk && read_attribute(pk) != restore_state[:id]
|
401
|
-
write_attribute(pk, restore_state[:id])
|
402
|
-
end
|
403
|
-
freeze if restore_state[:frozen?]
|
381
|
+
if _committed_already_called
|
382
|
+
@_new_record_before_last_commit = false
|
383
|
+
else
|
384
|
+
@_new_record_before_last_commit = @_start_transaction_state[:new_record]
|
404
385
|
end
|
405
386
|
end
|
406
|
-
end
|
407
387
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
388
|
+
# Clear the new record state and id of a record.
|
389
|
+
def clear_transaction_record_state
|
390
|
+
return unless @_start_transaction_state
|
391
|
+
@_start_transaction_state[:level] -= 1
|
392
|
+
force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
|
393
|
+
end
|
394
|
+
|
395
|
+
# Force to clear the transaction record state.
|
396
|
+
def force_clear_transaction_record_state
|
397
|
+
@_start_transaction_state = nil
|
398
|
+
end
|
412
399
|
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
400
|
+
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
401
|
+
def restore_transaction_record_state(force_restore_state = false)
|
402
|
+
if restore_state = @_start_transaction_state
|
403
|
+
if force_restore_state || restore_state[:level] <= 1
|
404
|
+
@new_record = restore_state[:new_record]
|
405
|
+
@previously_new_record = restore_state[:previously_new_record]
|
406
|
+
@destroyed = restore_state[:destroyed]
|
407
|
+
@attributes = restore_state[:attributes].map do |attr|
|
408
|
+
value = @attributes.fetch_value(attr.name)
|
409
|
+
attr = attr.with_value_from_user(value) if attr.value != value
|
410
|
+
attr
|
411
|
+
end
|
412
|
+
@mutations_from_database = nil
|
413
|
+
@mutations_before_last_save = nil
|
414
|
+
if @attributes.fetch_value(@primary_key) != restore_state[:id]
|
415
|
+
@attributes.write_from_user(@primary_key, restore_state[:id])
|
416
|
+
end
|
417
|
+
freeze if restore_state[:frozen?]
|
418
|
+
end
|
423
419
|
end
|
424
420
|
end
|
425
|
-
|
421
|
+
|
422
|
+
# Determine if a transaction included an action for :create, :update, or :destroy. Used in filtering callbacks.
|
423
|
+
def transaction_include_any_action?(actions)
|
424
|
+
actions.any? do |action|
|
425
|
+
case action
|
426
|
+
when :create
|
427
|
+
persisted? && @_new_record_before_last_commit
|
428
|
+
when :update
|
429
|
+
!(@_new_record_before_last_commit || destroyed?) && _trigger_update_callback
|
430
|
+
when :destroy
|
431
|
+
_trigger_destroy_callback
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
# Add the record to the current transaction so that the #after_rollback and #after_commit
|
437
|
+
# callbacks can be called.
|
438
|
+
def add_to_transaction(ensure_finalize = true)
|
439
|
+
self.class.connection.add_transaction_record(self, ensure_finalize)
|
440
|
+
end
|
441
|
+
|
442
|
+
def has_transactional_callbacks?
|
443
|
+
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
|
444
|
+
end
|
426
445
|
end
|
427
446
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Translation
|
3
5
|
include ActiveModel::Translation
|
@@ -8,7 +10,7 @@ module ActiveRecord
|
|
8
10
|
classes = [klass]
|
9
11
|
return classes if klass == ActiveRecord::Base
|
10
12
|
|
11
|
-
while klass
|
13
|
+
while !klass.base_class?
|
12
14
|
classes << klass = klass.superclass
|
13
15
|
end
|
14
16
|
classes
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model/type/registry"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
# :stopdoc:
|
7
|
+
module Type
|
8
|
+
class AdapterSpecificRegistry < ActiveModel::Type::Registry
|
9
|
+
def add_modifier(options, klass, **args)
|
10
|
+
registrations << DecorationRegistration.new(options, klass, **args)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def registration_klass
|
15
|
+
Registration
|
16
|
+
end
|
17
|
+
|
18
|
+
def find_registration(symbol, *args, **kwargs)
|
19
|
+
registrations
|
20
|
+
.select { |registration| registration.matches?(symbol, *args, **kwargs) }
|
21
|
+
.max
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Registration
|
26
|
+
def initialize(name, block, adapter: nil, override: nil)
|
27
|
+
@name = name
|
28
|
+
@block = block
|
29
|
+
@adapter = adapter
|
30
|
+
@override = override
|
31
|
+
end
|
32
|
+
|
33
|
+
def call(_registry, *args, adapter: nil, **kwargs)
|
34
|
+
if kwargs.any? # https://bugs.ruby-lang.org/issues/10856
|
35
|
+
block.call(*args, **kwargs)
|
36
|
+
else
|
37
|
+
block.call(*args)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def matches?(type_name, *args, **kwargs)
|
42
|
+
type_name == name && matches_adapter?(**kwargs)
|
43
|
+
end
|
44
|
+
|
45
|
+
def <=>(other)
|
46
|
+
if conflicts_with?(other)
|
47
|
+
raise TypeConflictError.new("Type #{name} was registered for all
|
48
|
+
adapters, but shadows a native type with
|
49
|
+
the same name for #{other.adapter}".squish)
|
50
|
+
end
|
51
|
+
priority <=> other.priority
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
attr_reader :name, :block, :adapter, :override
|
56
|
+
|
57
|
+
def priority
|
58
|
+
result = 0
|
59
|
+
if adapter
|
60
|
+
result |= 1
|
61
|
+
end
|
62
|
+
if override
|
63
|
+
result |= 2
|
64
|
+
end
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
def priority_except_adapter
|
69
|
+
priority & 0b111111100
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def matches_adapter?(adapter: nil, **)
|
74
|
+
(self.adapter.nil? || adapter == self.adapter)
|
75
|
+
end
|
76
|
+
|
77
|
+
def conflicts_with?(other)
|
78
|
+
same_priority_except_adapter?(other) &&
|
79
|
+
has_adapter_conflict?(other)
|
80
|
+
end
|
81
|
+
|
82
|
+
def same_priority_except_adapter?(other)
|
83
|
+
priority_except_adapter == other.priority_except_adapter
|
84
|
+
end
|
85
|
+
|
86
|
+
def has_adapter_conflict?(other)
|
87
|
+
(override.nil? && other.adapter) ||
|
88
|
+
(adapter && other.override.nil?)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class DecorationRegistration < Registration
|
93
|
+
def initialize(options, klass, adapter: nil)
|
94
|
+
@options = options
|
95
|
+
@klass = klass
|
96
|
+
@adapter = adapter
|
97
|
+
end
|
98
|
+
|
99
|
+
def call(registry, *args, **kwargs)
|
100
|
+
subtype = registry.lookup(*args, **kwargs.except(*options.keys))
|
101
|
+
klass.new(subtype)
|
102
|
+
end
|
103
|
+
|
104
|
+
def matches?(*args, **kwargs)
|
105
|
+
matches_adapter?(**kwargs) && matches_options?(**kwargs)
|
106
|
+
end
|
107
|
+
|
108
|
+
def priority
|
109
|
+
super | 4
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
attr_reader :options, :klass
|
114
|
+
|
115
|
+
def matches_options?(**kwargs)
|
116
|
+
options.all? do |key, value|
|
117
|
+
kwargs[key] == value
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class TypeConflictError < StandardError
|
124
|
+
end
|
125
|
+
# :startdoc:
|
126
|
+
end
|