activerecord 5.0.6 → 6.0.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 +638 -2023
- data/MIT-LICENSE +3 -1
- data/README.rdoc +8 -6
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record/aggregations.rb +249 -246
- data/lib/active_record/association_relation.rb +24 -13
- data/lib/active_record/associations/alias_tracker.rb +24 -33
- data/lib/active_record/associations/association.rb +119 -56
- data/lib/active_record/associations/association_scope.rb +94 -94
- data/lib/active_record/associations/belongs_to_association.rb +58 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +18 -25
- data/lib/active_record/associations/builder/belongs_to.rb +43 -54
- data/lib/active_record/associations/builder/collection_association.rb +7 -18
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -61
- 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 +80 -252
- data/lib/active_record/associations/collection_proxy.rb +158 -121
- data/lib/active_record/associations/foreign_association.rb +9 -0
- data/lib/active_record/associations/has_many_association.rb +23 -29
- 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 +38 -90
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/join_dependency.rb +134 -176
- data/lib/active_record/associations/preloader/association.rb +84 -125
- data/lib/active_record/associations/preloader/through_association.rb +82 -75
- data/lib/active_record/associations/preloader.rb +90 -102
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +26 -14
- data/lib/active_record/associations.rb +1603 -1592
- data/lib/active_record/attribute_assignment.rb +54 -60
- data/lib/active_record/attribute_decorators.rb +38 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -7
- data/lib/active_record/attribute_methods/dirty.rb +179 -109
- data/lib/active_record/attribute_methods/primary_key.rb +86 -91
- data/lib/active_record/attribute_methods/query.rb +4 -3
- data/lib/active_record/attribute_methods/read.rb +21 -49
- data/lib/active_record/attribute_methods/serialization.rb +30 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -64
- data/lib/active_record/attribute_methods/write.rb +35 -33
- data/lib/active_record/attribute_methods.rb +66 -106
- data/lib/active_record/attributes.rb +38 -24
- data/lib/active_record/autosave_association.rb +53 -32
- data/lib/active_record/base.rb +27 -24
- data/lib/active_record/callbacks.rb +63 -33
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +11 -11
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +553 -321
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +213 -94
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -28
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -27
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -126
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +369 -199
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +363 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -551
- data/lib/active_record/connection_adapters/column.rb +41 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +172 -138
- 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 +143 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +50 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +49 -30
- data/lib/active_record/connection_adapters/postgresql/column.rb +22 -7
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +60 -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 -10
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -17
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -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 +31 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -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 +9 -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 +19 -25
- 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 +35 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +380 -300
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
- data/lib/active_record/connection_adapters/postgresql/utils.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +382 -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 +120 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +74 -19
- 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 +254 -262
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -7
- data/lib/active_record/connection_handling.rb +159 -40
- data/lib/active_record/core.rb +202 -162
- data/lib/active_record/counter_cache.rb +57 -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 +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -86
- data/lib/active_record/enum.rb +60 -23
- data/lib/active_record/errors.rb +114 -18
- data/lib/active_record/explain.rb +4 -3
- 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 +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +195 -502
- data/lib/active_record/gem_version.rb +4 -2
- data/lib/active_record/inheritance.rb +151 -97
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +116 -25
- data/lib/active_record/internal_metadata.rb +15 -18
- data/lib/active_record/legacy_yaml_adapter.rb +4 -2
- data/lib/active_record/locking/optimistic.rb +78 -87
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +48 -29
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +143 -97
- data/lib/active_record/migration/compatibility.rb +174 -56
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +367 -300
- data/lib/active_record/model_schema.rb +145 -139
- data/lib/active_record/nested_attributes.rb +214 -201
- data/lib/active_record/no_touching.rb +10 -1
- data/lib/active_record/null_relation.rb +13 -34
- data/lib/active_record/persistence.rb +442 -72
- data/lib/active_record/query_cache.rb +15 -14
- data/lib/active_record/querying.rb +36 -23
- 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 +309 -177
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +211 -249
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/batches.rb +99 -52
- data/lib/active_record/relation/calculations.rb +211 -172
- data/lib/active_record/relation/delegation.rb +67 -65
- data/lib/active_record/relation/finder_methods.rb +208 -247
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +78 -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 +86 -104
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +458 -329
- data/lib/active_record/relation/record_fetch_warning.rb +5 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -7
- data/lib/active_record/relation/where_clause.rb +111 -95
- data/lib/active_record/relation/where_clause_factory.rb +6 -11
- data/lib/active_record/relation.rb +429 -318
- data/lib/active_record/result.rb +69 -39
- 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 +15 -5
- data/lib/active_record/scoping/default.rb +93 -95
- data/lib/active_record/scoping/named.rb +45 -25
- data/lib/active_record/scoping.rb +20 -19
- 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 +4 -1
- data/lib/active_record/table_metadata.rb +26 -20
- data/lib/active_record/tasks/database_tasks.rb +276 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +54 -90
- data/lib/active_record/tasks/postgresql_database_tasks.rb +78 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +34 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +70 -35
- data/lib/active_record/touch_later.rb +7 -4
- data/lib/active_record/transactions.rb +133 -149
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +44 -45
- 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 -3
- 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 -8
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +2 -1
- data/lib/active_record/type/type_map.rb +13 -15
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +23 -17
- 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 -1
- 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 -4
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +36 -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 +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +58 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/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 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -29
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +133 -50
- 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 -130
- 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
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require 'concurrent/map'
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "mutex_m"
|
5
4
|
|
6
5
|
module ActiveRecord
|
7
6
|
# = Active Record Attribute Methods
|
@@ -23,18 +22,11 @@ module ActiveRecord
|
|
23
22
|
delegate :column_for_attribute, to: :class
|
24
23
|
end
|
25
24
|
|
26
|
-
|
27
|
-
def self.set_name_cache(name, value)
|
28
|
-
const_name = "ATTR_#{name}"
|
29
|
-
unless const_defined? const_name
|
30
|
-
const_set const_name, value.dup.freeze
|
31
|
-
end
|
32
|
-
end
|
33
|
-
}
|
25
|
+
RESTRICTED_CLASS_METHODS = %w(private public protected allocate new name parent superclass)
|
34
26
|
|
35
|
-
|
36
|
-
|
37
|
-
|
27
|
+
class GeneratedAttributeMethods < Module #:nodoc:
|
28
|
+
include Mutex_m
|
29
|
+
end
|
38
30
|
|
39
31
|
module ClassMethods
|
40
32
|
def inherited(child_class) #:nodoc:
|
@@ -43,7 +35,8 @@ module ActiveRecord
|
|
43
35
|
end
|
44
36
|
|
45
37
|
def initialize_generated_modules # :nodoc:
|
46
|
-
@generated_attribute_methods = GeneratedAttributeMethods.new
|
38
|
+
@generated_attribute_methods = const_set(:GeneratedAttributeMethods, GeneratedAttributeMethods.new)
|
39
|
+
private_constant :GeneratedAttributeMethods
|
47
40
|
@attribute_methods_generated = false
|
48
41
|
include @generated_attribute_methods
|
49
42
|
|
@@ -58,11 +51,10 @@ module ActiveRecord
|
|
58
51
|
# attribute methods.
|
59
52
|
generated_attribute_methods.synchronize do
|
60
53
|
return false if @attribute_methods_generated
|
61
|
-
superclass.define_attribute_methods unless
|
54
|
+
superclass.define_attribute_methods unless base_class?
|
62
55
|
super(attribute_names)
|
63
56
|
@attribute_methods_generated = true
|
64
57
|
end
|
65
|
-
true
|
66
58
|
end
|
67
59
|
|
68
60
|
def undefine_attribute_methods # :nodoc:
|
@@ -123,7 +115,7 @@ module ActiveRecord
|
|
123
115
|
# A class method is 'dangerous' if it is already (re)defined by Active Record, but
|
124
116
|
# not by any ancestors. (So 'puts' is not dangerous but 'new' is.)
|
125
117
|
def dangerous_class_method?(method_name)
|
126
|
-
|
118
|
+
RESTRICTED_CLASS_METHODS.include?(method_name.to_s) || class_method_defined_within?(method_name, Base)
|
127
119
|
end
|
128
120
|
|
129
121
|
def class_method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc:
|
@@ -148,7 +140,7 @@ module ActiveRecord
|
|
148
140
|
# Person.attribute_method?(:age=) # => true
|
149
141
|
# Person.attribute_method?(:nothing) # => false
|
150
142
|
def attribute_method?(attribute)
|
151
|
-
super || (table_exists? && column_names.include?(attribute.to_s.sub(/=$/,
|
143
|
+
super || (table_exists? && column_names.include?(attribute.to_s.sub(/=$/, "")))
|
152
144
|
end
|
153
145
|
|
154
146
|
# Returns an array of column names as strings if it's not an abstract class and
|
@@ -161,10 +153,10 @@ module ActiveRecord
|
|
161
153
|
# # => ["id", "created_at", "updated_at", "name", "age"]
|
162
154
|
def attribute_names
|
163
155
|
@attribute_names ||= if !abstract_class? && table_exists?
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
156
|
+
attribute_types.keys
|
157
|
+
else
|
158
|
+
[]
|
159
|
+
end
|
168
160
|
end
|
169
161
|
|
170
162
|
# Returns true if the given attribute exists, otherwise false.
|
@@ -209,34 +201,27 @@ module ActiveRecord
|
|
209
201
|
# end
|
210
202
|
#
|
211
203
|
# person = Person.new
|
212
|
-
# person.respond_to(:name) # => true
|
213
|
-
# person.respond_to(:name=) # => true
|
214
|
-
# person.respond_to(:name?) # => true
|
215
|
-
# person.respond_to('age') # => true
|
216
|
-
# person.respond_to('age=') # => true
|
217
|
-
# person.respond_to('age?') # => true
|
218
|
-
# person.respond_to(:nothing) # => false
|
204
|
+
# person.respond_to?(:name) # => true
|
205
|
+
# person.respond_to?(:name=) # => true
|
206
|
+
# person.respond_to?(:name?) # => true
|
207
|
+
# person.respond_to?('age') # => true
|
208
|
+
# person.respond_to?('age=') # => true
|
209
|
+
# person.respond_to?('age?') # => true
|
210
|
+
# person.respond_to?(:nothing) # => false
|
219
211
|
def respond_to?(name, include_private = false)
|
220
212
|
return false unless super
|
221
213
|
|
222
|
-
case name
|
223
|
-
when :to_partial_path
|
224
|
-
name = "to_partial_path".freeze
|
225
|
-
when :to_model
|
226
|
-
name = "to_model".freeze
|
227
|
-
else
|
228
|
-
name = name.to_s
|
229
|
-
end
|
230
|
-
|
231
214
|
# If the result is true then check for the select case.
|
232
215
|
# For queries selecting a subset of columns, return false for unselected columns.
|
233
216
|
# We check defined?(@attributes) not to issue warnings if called on objects that
|
234
217
|
# have been allocated but not yet initialized.
|
235
|
-
if defined?(@attributes)
|
236
|
-
|
218
|
+
if defined?(@attributes)
|
219
|
+
if name = self.class.symbol_column_to_string(name.to_sym)
|
220
|
+
return has_attribute?(name)
|
221
|
+
end
|
237
222
|
end
|
238
223
|
|
239
|
-
|
224
|
+
true
|
240
225
|
end
|
241
226
|
|
242
227
|
# Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
|
@@ -293,15 +278,8 @@ module ActiveRecord
|
|
293
278
|
# person.attribute_for_inspect(:tag_ids)
|
294
279
|
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
|
295
280
|
def attribute_for_inspect(attr_name)
|
296
|
-
value =
|
297
|
-
|
298
|
-
if value.is_a?(String) && value.length > 50
|
299
|
-
"#{value[0, 50]}...".inspect
|
300
|
-
elsif value.is_a?(Date) || value.is_a?(Time)
|
301
|
-
%("#{value.to_s(:db)}")
|
302
|
-
else
|
303
|
-
value.inspect
|
304
|
-
end
|
281
|
+
value = _read_attribute(attr_name)
|
282
|
+
format_for_inspect(value)
|
305
283
|
end
|
306
284
|
|
307
285
|
# Returns +true+ if the specified +attribute+ has been set by the user or by a
|
@@ -330,8 +308,6 @@ module ActiveRecord
|
|
330
308
|
#
|
331
309
|
# Note: +:id+ is always present.
|
332
310
|
#
|
333
|
-
# Alias for the #read_attribute method.
|
334
|
-
#
|
335
311
|
# class Person < ActiveRecord::Base
|
336
312
|
# belongs_to :organization
|
337
313
|
# end
|
@@ -394,67 +370,51 @@ module ActiveRecord
|
|
394
370
|
@attributes.accessed
|
395
371
|
end
|
396
372
|
|
397
|
-
protected
|
398
|
-
|
399
|
-
def clone_attribute_value(reader_method, attribute_name) # :nodoc:
|
400
|
-
value = send(reader_method, attribute_name)
|
401
|
-
value.duplicable? ? value.clone : value
|
402
|
-
rescue TypeError, NoMethodError
|
403
|
-
value
|
404
|
-
end
|
405
|
-
|
406
|
-
def arel_attributes_with_values_for_create(attribute_names) # :nodoc:
|
407
|
-
arel_attributes_with_values(attributes_for_create(attribute_names))
|
408
|
-
end
|
409
|
-
|
410
|
-
def arel_attributes_with_values_for_update(attribute_names) # :nodoc:
|
411
|
-
arel_attributes_with_values(attributes_for_update(attribute_names))
|
412
|
-
end
|
413
|
-
|
414
|
-
def attribute_method?(attr_name) # :nodoc:
|
415
|
-
# We check defined? because Syck calls respond_to? before actually calling initialize.
|
416
|
-
defined?(@attributes) && @attributes.key?(attr_name)
|
417
|
-
end
|
418
|
-
|
419
373
|
private
|
374
|
+
def attribute_method?(attr_name)
|
375
|
+
# We check defined? because Syck calls respond_to? before actually calling initialize.
|
376
|
+
defined?(@attributes) && @attributes.key?(attr_name)
|
377
|
+
end
|
420
378
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
arel_table = self.class.arel_table
|
426
|
-
|
427
|
-
attribute_names.each do |name|
|
428
|
-
attrs[arel_table[name]] = typecasted_attribute_value(name)
|
379
|
+
def attributes_with_values(attribute_names)
|
380
|
+
attribute_names.each_with_object({}) do |name, attrs|
|
381
|
+
attrs[name] = _read_attribute(name)
|
382
|
+
end
|
429
383
|
end
|
430
|
-
attrs
|
431
|
-
end
|
432
384
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
385
|
+
# Filters the primary keys and readonly attributes from the attribute names.
|
386
|
+
def attributes_for_update(attribute_names)
|
387
|
+
attribute_names &= self.class.column_names
|
388
|
+
attribute_names.delete_if do |name|
|
389
|
+
readonly_attribute?(name)
|
390
|
+
end
|
437
391
|
end
|
438
|
-
end
|
439
392
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
393
|
+
# Filters out the primary keys, from the attribute names, when the primary
|
394
|
+
# key is to be generated (e.g. the id attribute has no value).
|
395
|
+
def attributes_for_create(attribute_names)
|
396
|
+
attribute_names &= self.class.column_names
|
397
|
+
attribute_names.delete_if do |name|
|
398
|
+
pk_attribute?(name) && id.nil?
|
399
|
+
end
|
445
400
|
end
|
446
|
-
end
|
447
401
|
|
448
|
-
|
449
|
-
|
450
|
-
|
402
|
+
def format_for_inspect(value)
|
403
|
+
if value.is_a?(String) && value.length > 50
|
404
|
+
"#{value[0, 50]}...".inspect
|
405
|
+
elsif value.is_a?(Date) || value.is_a?(Time)
|
406
|
+
%("#{value.to_s(:db)}")
|
407
|
+
else
|
408
|
+
value.inspect
|
409
|
+
end
|
410
|
+
end
|
451
411
|
|
452
|
-
|
453
|
-
|
454
|
-
|
412
|
+
def readonly_attribute?(name)
|
413
|
+
self.class.readonly_attributes.include?(name)
|
414
|
+
end
|
455
415
|
|
456
|
-
|
457
|
-
|
458
|
-
|
416
|
+
def pk_attribute?(name)
|
417
|
+
name == @primary_key
|
418
|
+
end
|
459
419
|
end
|
460
420
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model/attribute/user_provided_default"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
# See ActiveRecord::Attributes::ClassMethods for documentation
|
@@ -6,8 +8,7 @@ module ActiveRecord
|
|
6
8
|
extend ActiveSupport::Concern
|
7
9
|
|
8
10
|
included do
|
9
|
-
class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false # :internal:
|
10
|
-
self.attributes_to_define_after_schema_loads = {}
|
11
|
+
class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false, default: {} # :internal:
|
11
12
|
end
|
12
13
|
|
13
14
|
module ClassMethods
|
@@ -40,6 +41,9 @@ module ActiveRecord
|
|
40
41
|
# +range+ (PostgreSQL only) specifies that the type should be a range (see the
|
41
42
|
# examples below).
|
42
43
|
#
|
44
|
+
# When using a symbol for +cast_type+, extra options are forwarded to the
|
45
|
+
# constructor of the type object.
|
46
|
+
#
|
43
47
|
# ==== Examples
|
44
48
|
#
|
45
49
|
# The type detected by Active Record can be overridden.
|
@@ -56,7 +60,7 @@ module ActiveRecord
|
|
56
60
|
# store_listing = StoreListing.new(price_in_cents: '10.1')
|
57
61
|
#
|
58
62
|
# # before
|
59
|
-
# store_listing.price_in_cents # => BigDecimal
|
63
|
+
# store_listing.price_in_cents # => BigDecimal(10.1)
|
60
64
|
#
|
61
65
|
# class StoreListing < ActiveRecord::Base
|
62
66
|
# attribute :price_in_cents, :integer
|
@@ -111,12 +115,22 @@ module ActiveRecord
|
|
111
115
|
# my_float_range: 1.0..3.5
|
112
116
|
# }
|
113
117
|
#
|
118
|
+
# Passing options to the type constructor
|
119
|
+
#
|
120
|
+
# # app/models/my_model.rb
|
121
|
+
# class MyModel < ActiveRecord::Base
|
122
|
+
# attribute :small_int, :integer, limit: 2
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
# MyModel.create(small_int: 65537)
|
126
|
+
# # => Error: 65537 is out of range for the limit of two bytes
|
127
|
+
#
|
114
128
|
# ==== Creating Custom Types
|
115
129
|
#
|
116
130
|
# Users may also define their own custom types, as long as they respond
|
117
131
|
# to the methods defined on the value type. The method +deserialize+ or
|
118
132
|
# +cast+ will be called on your type object, with raw input from the
|
119
|
-
# database or from your controllers. See
|
133
|
+
# database or from your controllers. See ActiveModel::Type::Value for the
|
120
134
|
# expected API. It is recommended that your type objects inherit from an
|
121
135
|
# existing type, or from ActiveRecord::Type::Value
|
122
136
|
#
|
@@ -143,7 +157,7 @@ module ActiveRecord
|
|
143
157
|
# store_listing.price_in_cents # => 1000
|
144
158
|
#
|
145
159
|
# For more details on creating custom types, see the documentation for
|
146
|
-
#
|
160
|
+
# ActiveModel::Type::Value. For more details on registering your types
|
147
161
|
# to be referenced by a symbol, see ActiveRecord::Type.register. You can
|
148
162
|
# also pass a type object directly, in place of a symbol.
|
149
163
|
#
|
@@ -190,8 +204,8 @@ module ActiveRecord
|
|
190
204
|
# The type of an attribute is given the opportunity to change how dirty
|
191
205
|
# tracking is performed. The methods +changed?+ and +changed_in_place?+
|
192
206
|
# will be called from ActiveModel::Dirty. See the documentation for those
|
193
|
-
# methods in
|
194
|
-
def attribute(name, cast_type, **options)
|
207
|
+
# methods in ActiveModel::Type::Value for more details.
|
208
|
+
def attribute(name, cast_type = Type::Value.new, **options)
|
195
209
|
name = name.to_s
|
196
210
|
reload_schema_from_cache
|
197
211
|
|
@@ -242,24 +256,24 @@ module ActiveRecord
|
|
242
256
|
|
243
257
|
private
|
244
258
|
|
245
|
-
|
246
|
-
|
259
|
+
NO_DEFAULT_PROVIDED = Object.new # :nodoc:
|
260
|
+
private_constant :NO_DEFAULT_PROVIDED
|
247
261
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
262
|
+
def define_default_attribute(name, value, type, from_user:)
|
263
|
+
if value == NO_DEFAULT_PROVIDED
|
264
|
+
default_attribute = _default_attributes[name].with_type(type)
|
265
|
+
elsif from_user
|
266
|
+
default_attribute = ActiveModel::Attribute::UserProvidedDefault.new(
|
267
|
+
name,
|
268
|
+
value,
|
269
|
+
type,
|
270
|
+
_default_attributes.fetch(name.to_s) { nil },
|
271
|
+
)
|
272
|
+
else
|
273
|
+
default_attribute = ActiveModel::Attribute.from_database(name, value, type)
|
274
|
+
end
|
275
|
+
_default_attributes[name] = default_attribute
|
260
276
|
end
|
261
|
-
_default_attributes[name] = default_attribute
|
262
|
-
end
|
263
277
|
end
|
264
278
|
end
|
265
279
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record Autosave Association
|
3
5
|
#
|
@@ -140,24 +142,23 @@ module ActiveRecord
|
|
140
142
|
|
141
143
|
included do
|
142
144
|
Associations::Builder::Association.extensions << AssociationBuilderExtension
|
143
|
-
mattr_accessor :index_nested_attribute_errors, instance_writer: false
|
144
|
-
self.index_nested_attribute_errors = false
|
145
|
+
mattr_accessor :index_nested_attribute_errors, instance_writer: false, default: false
|
145
146
|
end
|
146
147
|
|
147
148
|
module ClassMethods # :nodoc:
|
148
149
|
private
|
149
150
|
|
150
151
|
def define_non_cyclic_method(name, &block)
|
151
|
-
return if
|
152
|
+
return if instance_methods(false).include?(name)
|
152
153
|
define_method(name) do |*args|
|
153
154
|
result = true; @_already_called ||= {}
|
154
155
|
# Loop prevention for validation of associations
|
155
156
|
unless @_already_called[name]
|
156
157
|
begin
|
157
|
-
@_already_called[name]=true
|
158
|
+
@_already_called[name] = true
|
158
159
|
result = instance_eval(&block)
|
159
160
|
ensure
|
160
|
-
@_already_called[name]=false
|
161
|
+
@_already_called[name] = false
|
161
162
|
end
|
162
163
|
end
|
163
164
|
|
@@ -181,6 +182,7 @@ module ActiveRecord
|
|
181
182
|
|
182
183
|
if reflection.collection?
|
183
184
|
before_save :before_save_collection_association
|
185
|
+
after_save :after_save_collection_association
|
184
186
|
|
185
187
|
define_non_cyclic_method(save_method) { save_collection_association(reflection) }
|
186
188
|
# Doesn't use after_save as that would save associations added in after_create/after_update twice
|
@@ -215,13 +217,7 @@ module ActiveRecord
|
|
215
217
|
method = :validate_single_association
|
216
218
|
end
|
217
219
|
|
218
|
-
define_non_cyclic_method(validation_method)
|
219
|
-
send(method, reflection)
|
220
|
-
# TODO: remove the following line as soon as the return value of
|
221
|
-
# callbacks is ignored, that is, returning `false` does not
|
222
|
-
# display a deprecation warning or halts the callback chain.
|
223
|
-
true
|
224
|
-
end
|
220
|
+
define_non_cyclic_method(validation_method) { send(method, reflection) }
|
225
221
|
validate validation_method
|
226
222
|
after_validation :_ensure_no_duplicate_errors
|
227
223
|
end
|
@@ -267,7 +263,7 @@ module ActiveRecord
|
|
267
263
|
# Returns whether or not this record has been changed in any way (including whether
|
268
264
|
# any of its nested autosave associations are likewise changed)
|
269
265
|
def changed_for_autosave?
|
270
|
-
new_record? ||
|
266
|
+
new_record? || has_changes_to_save? || marked_for_destruction? || nested_records_changed_for_autosave?
|
271
267
|
end
|
272
268
|
|
273
269
|
private
|
@@ -276,7 +272,7 @@ module ActiveRecord
|
|
276
272
|
# or saved. If +autosave+ is +false+ only new records will be returned,
|
277
273
|
# unless the parent is/was a new record itself.
|
278
274
|
def associated_records_to_validate_or_save(association, new_record, autosave)
|
279
|
-
if new_record
|
275
|
+
if new_record || custom_validation_context?
|
280
276
|
association && association.target
|
281
277
|
elsif autosave
|
282
278
|
association.target.find_all(&:changed_for_autosave?)
|
@@ -308,7 +304,7 @@ module ActiveRecord
|
|
308
304
|
def validate_single_association(reflection)
|
309
305
|
association = association_instance_get(reflection.name)
|
310
306
|
record = association && association.reader
|
311
|
-
association_valid?(reflection, record) if record
|
307
|
+
association_valid?(reflection, record) if record && (record.changed_for_autosave? || custom_validation_context?)
|
312
308
|
end
|
313
309
|
|
314
310
|
# Validate the associated records if <tt>:validate</tt> or
|
@@ -325,12 +321,12 @@ module ActiveRecord
|
|
325
321
|
# Returns whether or not the association is valid and applies any errors to
|
326
322
|
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
|
327
323
|
# enabled records if they're marked_for_destruction? or destroyed.
|
328
|
-
def association_valid?(reflection, record, index=nil)
|
324
|
+
def association_valid?(reflection, record, index = nil)
|
329
325
|
return true if record.destroyed? || (reflection.options[:autosave] && record.marked_for_destruction?)
|
330
326
|
|
331
|
-
|
327
|
+
context = validation_context if custom_validation_context?
|
332
328
|
|
333
|
-
unless valid = record.valid?(
|
329
|
+
unless valid = record.valid?(context)
|
334
330
|
if reflection.options[:autosave]
|
335
331
|
indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
|
336
332
|
|
@@ -368,7 +364,10 @@ module ActiveRecord
|
|
368
364
|
# association whether or not the parent was a new record before saving.
|
369
365
|
def before_save_collection_association
|
370
366
|
@new_record_before_save = new_record?
|
371
|
-
|
367
|
+
end
|
368
|
+
|
369
|
+
def after_save_collection_association
|
370
|
+
@new_record_before_save = false
|
372
371
|
end
|
373
372
|
|
374
373
|
# Saves any new associated records, or all loaded autosave associations if
|
@@ -383,7 +382,14 @@ module ActiveRecord
|
|
383
382
|
if association = association_instance_get(reflection.name)
|
384
383
|
autosave = reflection.options[:autosave]
|
385
384
|
|
386
|
-
|
385
|
+
# By saving the instance variable in a local variable,
|
386
|
+
# we make the whole callback re-entrant.
|
387
|
+
new_record_before_save = @new_record_before_save
|
388
|
+
|
389
|
+
# reconstruct the scope now that we know the owner's id
|
390
|
+
association.reset_scope
|
391
|
+
|
392
|
+
if records = associated_records_to_validate_or_save(association, new_record_before_save, autosave)
|
387
393
|
if autosave
|
388
394
|
records_to_destroy = records.select(&:marked_for_destruction?)
|
389
395
|
records_to_destroy.each { |record| association.destroy(record) }
|
@@ -395,22 +401,24 @@ module ActiveRecord
|
|
395
401
|
|
396
402
|
saved = true
|
397
403
|
|
398
|
-
if autosave != false && (
|
404
|
+
if autosave != false && (new_record_before_save || record.new_record?)
|
399
405
|
if autosave
|
400
406
|
saved = association.insert_record(record, false)
|
401
|
-
|
402
|
-
association.insert_record(record)
|
407
|
+
elsif !reflection.nested?
|
408
|
+
association_saved = association.insert_record(record)
|
409
|
+
|
410
|
+
if reflection.validate?
|
411
|
+
errors.add(reflection.name) unless association_saved
|
412
|
+
saved = association_saved
|
413
|
+
end
|
403
414
|
end
|
404
415
|
elsif autosave
|
405
|
-
saved = record.save(:
|
416
|
+
saved = record.save(validate: false)
|
406
417
|
end
|
407
418
|
|
408
|
-
raise
|
419
|
+
raise(RecordInvalid.new(association.owner)) unless saved
|
409
420
|
end
|
410
421
|
end
|
411
|
-
|
412
|
-
# reconstruct the scope now that we know the owner's id
|
413
|
-
association.reset_scope if association.respond_to?(:reset_scope)
|
414
422
|
end
|
415
423
|
end
|
416
424
|
|
@@ -437,9 +445,12 @@ module ActiveRecord
|
|
437
445
|
if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
|
438
446
|
unless reflection.through_reflection
|
439
447
|
record[reflection.foreign_key] = key
|
448
|
+
if inverse_reflection = reflection.inverse_of
|
449
|
+
record.association(inverse_reflection.name).loaded!
|
450
|
+
end
|
440
451
|
end
|
441
452
|
|
442
|
-
saved = record.save(:
|
453
|
+
saved = record.save(validate: !autosave)
|
443
454
|
raise ActiveRecord::Rollback if !saved && autosave
|
444
455
|
saved
|
445
456
|
end
|
@@ -450,8 +461,14 @@ module ActiveRecord
|
|
450
461
|
# If the record is new or it has changed, returns true.
|
451
462
|
def record_changed?(reflection, record, key)
|
452
463
|
record.new_record? ||
|
453
|
-
|
454
|
-
record.
|
464
|
+
association_foreign_key_changed?(reflection, record, key) ||
|
465
|
+
record.will_save_change_to_attribute?(reflection.foreign_key)
|
466
|
+
end
|
467
|
+
|
468
|
+
def association_foreign_key_changed?(reflection, record, key)
|
469
|
+
return false if reflection.through_reflection?
|
470
|
+
|
471
|
+
record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key
|
455
472
|
end
|
456
473
|
|
457
474
|
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
|
@@ -469,7 +486,7 @@ module ActiveRecord
|
|
469
486
|
self[reflection.foreign_key] = nil
|
470
487
|
record.destroy
|
471
488
|
elsif autosave != false
|
472
|
-
saved = record.save(:
|
489
|
+
saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
|
473
490
|
|
474
491
|
if association.updated?
|
475
492
|
association_id = record.send(reflection.options[:primary_key] || :id)
|
@@ -482,6 +499,10 @@ module ActiveRecord
|
|
482
499
|
end
|
483
500
|
end
|
484
501
|
|
502
|
+
def custom_validation_context?
|
503
|
+
validation_context && [:create, :update].exclude?(validation_context)
|
504
|
+
end
|
505
|
+
|
485
506
|
def _ensure_no_duplicate_errors
|
486
507
|
errors.messages.each_key do |attribute|
|
487
508
|
errors[attribute].uniq!
|
data/lib/active_record/base.rb
CHANGED
@@ -1,25 +1,28 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "active_support/benchmarkable"
|
5
|
+
require "active_support/dependencies"
|
6
|
+
require "active_support/descendants_tracker"
|
7
|
+
require "active_support/time"
|
8
|
+
require "active_support/core_ext/module/attribute_accessors"
|
9
|
+
require "active_support/core_ext/array/extract_options"
|
10
|
+
require "active_support/core_ext/hash/deep_merge"
|
11
|
+
require "active_support/core_ext/hash/slice"
|
12
|
+
require "active_support/core_ext/string/behavior"
|
13
|
+
require "active_support/core_ext/kernel/singleton_class"
|
14
|
+
require "active_support/core_ext/module/introspection"
|
15
|
+
require "active_support/core_ext/object/duplicable"
|
16
|
+
require "active_support/core_ext/class/subclasses"
|
17
|
+
require "active_record/attribute_decorators"
|
18
|
+
require "active_record/define_callbacks"
|
19
|
+
require "active_record/errors"
|
20
|
+
require "active_record/log_subscriber"
|
21
|
+
require "active_record/explain_subscriber"
|
22
|
+
require "active_record/relation/delegation"
|
23
|
+
require "active_record/attributes"
|
24
|
+
require "active_record/type_caster"
|
25
|
+
require "active_record/database_configurations"
|
23
26
|
|
24
27
|
module ActiveRecord #:nodoc:
|
25
28
|
# = Active Record
|
@@ -285,7 +288,7 @@ module ActiveRecord #:nodoc:
|
|
285
288
|
extend Explain
|
286
289
|
extend Enum
|
287
290
|
extend Delegation::DelegateCache
|
288
|
-
extend
|
291
|
+
extend Aggregations::ClassMethods
|
289
292
|
|
290
293
|
include Core
|
291
294
|
include Persistence
|
@@ -303,6 +306,7 @@ module ActiveRecord #:nodoc:
|
|
303
306
|
include AttributeDecorators
|
304
307
|
include Locking::Optimistic
|
305
308
|
include Locking::Pessimistic
|
309
|
+
include DefineCallbacks
|
306
310
|
include AttributeMethods
|
307
311
|
include Callbacks
|
308
312
|
include Timestamp
|
@@ -310,7 +314,6 @@ module ActiveRecord #:nodoc:
|
|
310
314
|
include ActiveModel::SecurePassword
|
311
315
|
include AutosaveAssociation
|
312
316
|
include NestedAttributes
|
313
|
-
include Aggregations
|
314
317
|
include Transactions
|
315
318
|
include TouchLater
|
316
319
|
include NoTouching
|