activerecord 5.0.7.2 → 6.0.6.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +844 -1944
- data/MIT-LICENSE +3 -1
- data/README.rdoc +9 -7
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +18 -14
- data/lib/active_record/associations/alias_tracker.rb +24 -34
- data/lib/active_record/associations/association.rb +113 -55
- data/lib/active_record/associations/association_scope.rb +102 -96
- data/lib/active_record/associations/belongs_to_association.rb +58 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +18 -25
- data/lib/active_record/associations/builder/belongs_to.rb +43 -54
- data/lib/active_record/associations/builder/collection_association.rb +7 -18
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
- data/lib/active_record/associations/builder/has_many.rb +4 -0
- data/lib/active_record/associations/builder/has_one.rb +37 -1
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +93 -254
- data/lib/active_record/associations/collection_proxy.rb +159 -122
- data/lib/active_record/associations/foreign_association.rb +9 -0
- data/lib/active_record/associations/has_many_association.rb +23 -30
- data/lib/active_record/associations/has_many_through_association.rb +58 -44
- data/lib/active_record/associations/has_one_association.rb +59 -54
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +43 -85
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/join_dependency.rb +152 -177
- data/lib/active_record/associations/preloader/association.rb +101 -97
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/preloader.rb +94 -103
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +27 -15
- data/lib/active_record/associations.rb +1603 -1592
- data/lib/active_record/attribute_assignment.rb +54 -61
- data/lib/active_record/attribute_decorators.rb +38 -17
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
- data/lib/active_record/attribute_methods/dirty.rb +179 -109
- data/lib/active_record/attribute_methods/primary_key.rb +85 -92
- data/lib/active_record/attribute_methods/query.rb +4 -3
- data/lib/active_record/attribute_methods/read.rb +20 -49
- data/lib/active_record/attribute_methods/serialization.rb +29 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
- data/lib/active_record/attribute_methods/write.rb +34 -33
- data/lib/active_record/attribute_methods.rb +66 -106
- data/lib/active_record/attributes.rb +38 -25
- data/lib/active_record/autosave_association.rb +58 -39
- data/lib/active_record/base.rb +27 -24
- data/lib/active_record/callbacks.rb +64 -35
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +34 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +558 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +128 -75
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +233 -147
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
- data/lib/active_record/connection_adapters/abstract_adapter.rb +373 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -562
- data/lib/active_record/connection_adapters/column.rb +41 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
- data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +12 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
- data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +261 -267
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +143 -40
- data/lib/active_record/core.rb +207 -160
- data/lib/active_record/counter_cache.rb +60 -28
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +78 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -87
- data/lib/active_record/enum.rb +67 -23
- data/lib/active_record/errors.rb +114 -18
- data/lib/active_record/explain.rb +4 -4
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +13 -8
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +194 -504
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +150 -99
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +116 -25
- data/lib/active_record/internal_metadata.rb +16 -19
- data/lib/active_record/legacy_yaml_adapter.rb +4 -2
- data/lib/active_record/locking/optimistic.rb +85 -86
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +48 -29
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
- data/lib/active_record/middleware/database_selector.rb +74 -0
- data/lib/active_record/migration/command_recorder.rb +134 -100
- data/lib/active_record/migration/compatibility.rb +174 -56
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +369 -302
- data/lib/active_record/model_schema.rb +160 -127
- data/lib/active_record/nested_attributes.rb +213 -202
- data/lib/active_record/no_touching.rb +12 -3
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +446 -77
- data/lib/active_record/query_cache.rb +13 -12
- data/lib/active_record/querying.rb +37 -24
- data/lib/active_record/railtie.rb +128 -36
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +312 -177
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +214 -254
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/batches.rb +98 -52
- data/lib/active_record/relation/calculations.rb +212 -173
- data/lib/active_record/relation/delegation.rb +73 -69
- data/lib/active_record/relation/finder_methods.rb +207 -247
- data/lib/active_record/relation/from_clause.rb +6 -8
- data/lib/active_record/relation/merger.rb +82 -61
- data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +83 -105
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +488 -332
- data/lib/active_record/relation/record_fetch_warning.rb +5 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +111 -96
- data/lib/active_record/relation/where_clause_factory.rb +6 -11
- data/lib/active_record/relation.rb +443 -318
- data/lib/active_record/result.rb +69 -40
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +83 -99
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +71 -69
- data/lib/active_record/schema_migration.rb +16 -6
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +51 -26
- data/lib/active_record/scoping.rb +20 -20
- data/lib/active_record/secure_token.rb +4 -2
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +63 -28
- data/lib/active_record/store.rb +121 -41
- data/lib/active_record/suppressor.rb +6 -3
- data/lib/active_record/table_metadata.rb +39 -18
- data/lib/active_record/tasks/database_tasks.rb +271 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
- data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +243 -0
- data/lib/active_record/timestamp.rb +70 -36
- data/lib/active_record/touch_later.rb +8 -6
- data/lib/active_record/transactions.rb +141 -157
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +44 -48
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +16 -9
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +12 -1
- data/lib/active_record/type/type_map.rb +14 -17
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type.rb +23 -18
- data/lib/active_record/type_caster/connection.rb +17 -12
- data/lib/active_record/type_caster/map.rb +5 -4
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +3 -2
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +29 -42
- data/lib/active_record/validations.rb +7 -5
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +37 -22
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +256 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +203 -0
- data/lib/arel/visitors/dot.rb +296 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +156 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +158 -0
- data/lib/arel/visitors/oracle12.rb +65 -0
- data/lib/arel/visitors/postgresql.rb +109 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +888 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors/where_sql.rb +22 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +62 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
- data/lib/rails/generators/active_record/migration.rb +17 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +138 -52
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set/builder.rb +0 -132
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
- /data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,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
|
|
@@ -241,25 +255,24 @@ module ActiveRecord
|
|
241
255
|
end
|
242
256
|
|
243
257
|
private
|
258
|
+
NO_DEFAULT_PROVIDED = Object.new # :nodoc:
|
259
|
+
private_constant :NO_DEFAULT_PROVIDED
|
244
260
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
default_attribute = Attribute.from_database(name, value, type)
|
261
|
+
def define_default_attribute(name, value, type, from_user:)
|
262
|
+
if value == NO_DEFAULT_PROVIDED
|
263
|
+
default_attribute = _default_attributes[name].with_type(type)
|
264
|
+
elsif from_user
|
265
|
+
default_attribute = ActiveModel::Attribute::UserProvidedDefault.new(
|
266
|
+
name,
|
267
|
+
value,
|
268
|
+
type,
|
269
|
+
_default_attributes.fetch(name.to_s) { nil },
|
270
|
+
)
|
271
|
+
else
|
272
|
+
default_attribute = ActiveModel::Attribute.from_database(name, value, type)
|
273
|
+
end
|
274
|
+
_default_attributes[name] = default_attribute
|
260
275
|
end
|
261
|
-
_default_attributes[name] = default_attribute
|
262
|
-
end
|
263
276
|
end
|
264
277
|
end
|
265
278
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record Autosave Association
|
3
5
|
#
|
@@ -27,7 +29,7 @@ module ActiveRecord
|
|
27
29
|
# == Callbacks
|
28
30
|
#
|
29
31
|
# Association with autosave option defines several callbacks on your
|
30
|
-
# model (before_save, after_create, after_update). Please note that
|
32
|
+
# model (around_save, before_save, after_create, after_update). Please note that
|
31
33
|
# callbacks are executed in the order they were defined in
|
32
34
|
# model. You should avoid modifying the association content, before
|
33
35
|
# autosave callbacks are executed. Placing your callbacks after
|
@@ -140,24 +142,22 @@ 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
|
def define_non_cyclic_method(name, &block)
|
151
|
-
return if
|
151
|
+
return if instance_methods(false).include?(name)
|
152
152
|
define_method(name) do |*args|
|
153
153
|
result = true; @_already_called ||= {}
|
154
154
|
# Loop prevention for validation of associations
|
155
155
|
unless @_already_called[name]
|
156
156
|
begin
|
157
|
-
@_already_called[name]=true
|
157
|
+
@_already_called[name] = true
|
158
158
|
result = instance_eval(&block)
|
159
159
|
ensure
|
160
|
-
@_already_called[name]=false
|
160
|
+
@_already_called[name] = false
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
@@ -180,7 +180,7 @@ module ActiveRecord
|
|
180
180
|
save_method = :"autosave_associated_records_for_#{reflection.name}"
|
181
181
|
|
182
182
|
if reflection.collection?
|
183
|
-
|
183
|
+
around_save :around_save_collection_association
|
184
184
|
|
185
185
|
define_non_cyclic_method(save_method) { save_collection_association(reflection) }
|
186
186
|
# Doesn't use after_save as that would save associations added in after_create/after_update twice
|
@@ -215,13 +215,7 @@ module ActiveRecord
|
|
215
215
|
method = :validate_single_association
|
216
216
|
end
|
217
217
|
|
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
|
218
|
+
define_non_cyclic_method(validation_method) { send(method, reflection) }
|
225
219
|
validate validation_method
|
226
220
|
after_validation :_ensure_no_duplicate_errors
|
227
221
|
end
|
@@ -267,16 +261,15 @@ module ActiveRecord
|
|
267
261
|
# Returns whether or not this record has been changed in any way (including whether
|
268
262
|
# any of its nested autosave associations are likewise changed)
|
269
263
|
def changed_for_autosave?
|
270
|
-
new_record? ||
|
264
|
+
new_record? || has_changes_to_save? || marked_for_destruction? || nested_records_changed_for_autosave?
|
271
265
|
end
|
272
266
|
|
273
267
|
private
|
274
|
-
|
275
268
|
# Returns the record for an association collection that should be validated
|
276
269
|
# or saved. If +autosave+ is +false+ only new records will be returned,
|
277
270
|
# unless the parent is/was a new record itself.
|
278
271
|
def associated_records_to_validate_or_save(association, new_record, autosave)
|
279
|
-
if new_record
|
272
|
+
if new_record || custom_validation_context?
|
280
273
|
association && association.target
|
281
274
|
elsif autosave
|
282
275
|
association.target.find_all(&:changed_for_autosave?)
|
@@ -308,7 +301,7 @@ module ActiveRecord
|
|
308
301
|
def validate_single_association(reflection)
|
309
302
|
association = association_instance_get(reflection.name)
|
310
303
|
record = association && association.reader
|
311
|
-
association_valid?(reflection, record) if record
|
304
|
+
association_valid?(reflection, record) if record && (record.changed_for_autosave? || custom_validation_context?)
|
312
305
|
end
|
313
306
|
|
314
307
|
# Validate the associated records if <tt>:validate</tt> or
|
@@ -325,12 +318,12 @@ module ActiveRecord
|
|
325
318
|
# Returns whether or not the association is valid and applies any errors to
|
326
319
|
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
|
327
320
|
# enabled records if they're marked_for_destruction? or destroyed.
|
328
|
-
def association_valid?(reflection, record, index=nil)
|
321
|
+
def association_valid?(reflection, record, index = nil)
|
329
322
|
return true if record.destroyed? || (reflection.options[:autosave] && record.marked_for_destruction?)
|
330
323
|
|
331
|
-
|
324
|
+
context = validation_context if custom_validation_context?
|
332
325
|
|
333
|
-
unless valid = record.valid?(
|
326
|
+
unless valid = record.valid?(context)
|
334
327
|
if reflection.options[:autosave]
|
335
328
|
indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
|
336
329
|
|
@@ -364,11 +357,15 @@ module ActiveRecord
|
|
364
357
|
end
|
365
358
|
end
|
366
359
|
|
367
|
-
# Is used as
|
360
|
+
# Is used as an around_save callback to check while saving a collection
|
368
361
|
# association whether or not the parent was a new record before saving.
|
369
|
-
def
|
370
|
-
@new_record_before_save
|
371
|
-
|
362
|
+
def around_save_collection_association
|
363
|
+
previously_new_record_before_save = (@new_record_before_save ||= false)
|
364
|
+
@new_record_before_save = !previously_new_record_before_save && new_record?
|
365
|
+
|
366
|
+
yield
|
367
|
+
ensure
|
368
|
+
@new_record_before_save = previously_new_record_before_save
|
372
369
|
end
|
373
370
|
|
374
371
|
# Saves any new associated records, or all loaded autosave associations if
|
@@ -383,7 +380,14 @@ module ActiveRecord
|
|
383
380
|
if association = association_instance_get(reflection.name)
|
384
381
|
autosave = reflection.options[:autosave]
|
385
382
|
|
386
|
-
|
383
|
+
# By saving the instance variable in a local variable,
|
384
|
+
# we make the whole callback re-entrant.
|
385
|
+
new_record_before_save = @new_record_before_save
|
386
|
+
|
387
|
+
# reconstruct the scope now that we know the owner's id
|
388
|
+
association.reset_scope
|
389
|
+
|
390
|
+
if records = associated_records_to_validate_or_save(association, new_record_before_save, autosave)
|
387
391
|
if autosave
|
388
392
|
records_to_destroy = records.select(&:marked_for_destruction?)
|
389
393
|
records_to_destroy.each { |record| association.destroy(record) }
|
@@ -395,22 +399,24 @@ module ActiveRecord
|
|
395
399
|
|
396
400
|
saved = true
|
397
401
|
|
398
|
-
if autosave != false && (
|
402
|
+
if autosave != false && (new_record_before_save || record.new_record?)
|
399
403
|
if autosave
|
400
404
|
saved = association.insert_record(record, false)
|
401
|
-
|
402
|
-
association.insert_record(record)
|
405
|
+
elsif !reflection.nested?
|
406
|
+
association_saved = association.insert_record(record)
|
407
|
+
|
408
|
+
if reflection.validate?
|
409
|
+
errors.add(reflection.name) unless association_saved
|
410
|
+
saved = association_saved
|
411
|
+
end
|
403
412
|
end
|
404
413
|
elsif autosave
|
405
|
-
saved = record.save(:
|
414
|
+
saved = record.save(validate: false)
|
406
415
|
end
|
407
416
|
|
408
|
-
raise
|
417
|
+
raise(RecordInvalid.new(association.owner)) unless saved
|
409
418
|
end
|
410
419
|
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
420
|
end
|
415
421
|
end
|
416
422
|
|
@@ -437,9 +443,12 @@ module ActiveRecord
|
|
437
443
|
if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
|
438
444
|
unless reflection.through_reflection
|
439
445
|
record[reflection.foreign_key] = key
|
446
|
+
if inverse_reflection = reflection.inverse_of
|
447
|
+
record.association(inverse_reflection.name).inversed_from(self)
|
448
|
+
end
|
440
449
|
end
|
441
450
|
|
442
|
-
saved = record.save(:
|
451
|
+
saved = record.save(validate: !autosave)
|
443
452
|
raise ActiveRecord::Rollback if !saved && autosave
|
444
453
|
saved
|
445
454
|
end
|
@@ -450,8 +459,14 @@ module ActiveRecord
|
|
450
459
|
# If the record is new or it has changed, returns true.
|
451
460
|
def record_changed?(reflection, record, key)
|
452
461
|
record.new_record? ||
|
453
|
-
|
454
|
-
record.
|
462
|
+
association_foreign_key_changed?(reflection, record, key) ||
|
463
|
+
record.will_save_change_to_attribute?(reflection.foreign_key)
|
464
|
+
end
|
465
|
+
|
466
|
+
def association_foreign_key_changed?(reflection, record, key)
|
467
|
+
return false if reflection.through_reflection?
|
468
|
+
|
469
|
+
record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key
|
455
470
|
end
|
456
471
|
|
457
472
|
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
|
@@ -469,7 +484,7 @@ module ActiveRecord
|
|
469
484
|
self[reflection.foreign_key] = nil
|
470
485
|
record.destroy
|
471
486
|
elsif autosave != false
|
472
|
-
saved = record.save(:
|
487
|
+
saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
|
473
488
|
|
474
489
|
if association.updated?
|
475
490
|
association_id = record.send(reflection.options[:primary_key] || :id)
|
@@ -482,6 +497,10 @@ module ActiveRecord
|
|
482
497
|
end
|
483
498
|
end
|
484
499
|
|
500
|
+
def custom_validation_context?
|
501
|
+
validation_context && [:create, :update].exclude?(validation_context)
|
502
|
+
end
|
503
|
+
|
485
504
|
def _ensure_no_duplicate_errors
|
486
505
|
errors.messages.each_key do |attribute|
|
487
506
|
errors[attribute].uniq!
|