activerecord 4.2.0 → 6.1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1221 -796
- data/MIT-LICENSE +4 -2
- data/README.rdoc +15 -14
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +267 -249
- data/lib/active_record/association_relation.rb +45 -7
- data/lib/active_record/associations/alias_tracker.rb +40 -43
- data/lib/active_record/associations/association.rb +172 -67
- data/lib/active_record/associations/association_scope.rb +105 -129
- data/lib/active_record/associations/belongs_to_association.rb +85 -59
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +57 -43
- data/lib/active_record/associations/builder/belongs_to.rb +74 -57
- data/lib/active_record/associations/builder/collection_association.rb +15 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
- data/lib/active_record/associations/builder/has_many.rb +13 -5
- data/lib/active_record/associations/builder/has_one.rb +44 -6
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +168 -279
- data/lib/active_record/associations/collection_proxy.rb +263 -155
- data/lib/active_record/associations/foreign_association.rb +33 -0
- data/lib/active_record/associations/has_many_association.rb +57 -84
- data/lib/active_record/associations/has_many_through_association.rb +70 -82
- data/lib/active_record/associations/has_one_association.rb +74 -47
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
- 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 +175 -164
- data/lib/active_record/associations/preloader/association.rb +107 -112
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +99 -96
- data/lib/active_record/associations/singular_association.rb +18 -45
- data/lib/active_record/associations/through_association.rb +49 -24
- data/lib/active_record/associations.rb +1845 -1597
- data/lib/active_record/attribute_assignment.rb +59 -185
- data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
- data/lib/active_record/attribute_methods/dirty.rb +168 -138
- data/lib/active_record/attribute_methods/primary_key.rb +93 -83
- data/lib/active_record/attribute_methods/query.rb +8 -10
- data/lib/active_record/attribute_methods/read.rb +19 -79
- data/lib/active_record/attribute_methods/serialization.rb +49 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
- data/lib/active_record/attribute_methods/write.rb +25 -56
- data/lib/active_record/attribute_methods.rb +153 -162
- data/lib/active_record/attributes.rb +234 -70
- data/lib/active_record/autosave_association.rb +157 -69
- data/lib/active_record/base.rb +49 -50
- data/lib/active_record/callbacks.rb +234 -79
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +46 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
- data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
- data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
- data/lib/active_record/connection_adapters/column.rb +67 -40
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
- data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +314 -41
- data/lib/active_record/core.rb +488 -243
- data/lib/active_record/counter_cache.rb +71 -50
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +273 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -106
- data/lib/active_record/enum.rb +212 -94
- data/lib/active_record/errors.rb +225 -54
- data/lib/active_record/explain.rb +27 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +33 -14
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +273 -496
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +175 -110
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +121 -29
- data/lib/active_record/internal_metadata.rb +64 -0
- data/lib/active_record/legacy_yaml_adapter.rb +52 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +103 -95
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +93 -31
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +185 -90
- data/lib/active_record/migration/compatibility.rb +298 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +685 -309
- data/lib/active_record/model_schema.rb +420 -113
- data/lib/active_record/nested_attributes.rb +265 -216
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +574 -135
- data/lib/active_record/query_cache.rb +29 -23
- data/lib/active_record/querying.rb +50 -31
- data/lib/active_record/railtie.rb +175 -54
- data/lib/active_record/railties/console_sandbox.rb +3 -3
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +533 -216
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +485 -310
- data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
- data/lib/active_record/relation/batches.rb +217 -59
- data/lib/active_record/relation/calculations.rb +326 -244
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +318 -256
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +99 -84
- data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +139 -96
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +757 -409
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +23 -21
- data/lib/active_record/relation/where_clause.rb +239 -0
- data/lib/active_record/relation.rb +554 -342
- data/lib/active_record/result.rb +91 -47
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +134 -122
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +141 -92
- data/lib/active_record/schema_migration.rb +24 -26
- data/lib/active_record/scoping/default.rb +96 -82
- data/lib/active_record/scoping/named.rb +78 -36
- data/lib/active_record/scoping.rb +45 -27
- data/lib/active_record/secure_token.rb +48 -0
- data/lib/active_record/serialization.rb +8 -6
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +89 -36
- data/lib/active_record/store.rb +133 -43
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +81 -0
- data/lib/active_record/tasks/database_tasks.rb +366 -129
- data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
- data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +291 -0
- data/lib/active_record/timestamp.rb +86 -43
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +181 -152
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +126 -0
- data/lib/active_record/type/date.rb +4 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +33 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +21 -16
- data/lib/active_record/type/type_map.rb +16 -19
- data/lib/active_record/type/unsigned_integer.rb +9 -8
- data/lib/active_record/type.rb +84 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +12 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +65 -48
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +44 -28
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
- data/lib/rails/generators/active_record/migration.rb +35 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +175 -65
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -149
- data/lib/active_record/attribute_decorators.rb +0 -66
- data/lib/active_record/attribute_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -30
- data/lib/active_record/type/decimal.rb +0 -40
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -55
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord::Associations
|
4
|
+
module ForeignAssociation # :nodoc:
|
5
|
+
def foreign_key_present?
|
6
|
+
if reflection.klass.primary_key
|
7
|
+
owner.attribute_present?(reflection.active_record_primary_key)
|
8
|
+
else
|
9
|
+
false
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def nullified_owner_attributes
|
14
|
+
Hash.new.tap do |attrs|
|
15
|
+
attrs[reflection.foreign_key] = nil
|
16
|
+
attrs[reflection.type] = nil if reflection.type.present?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
# Sets the owner attributes on the given record
|
22
|
+
def set_owner_attributes(record)
|
23
|
+
return if options[:through]
|
24
|
+
|
25
|
+
key = owner._read_attribute(reflection.join_foreign_key)
|
26
|
+
record._write_attribute(reflection.join_primary_key, key)
|
27
|
+
|
28
|
+
if reflection.type
|
29
|
+
record._write_attribute(reflection.type, owner.class.polymorphic_name)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Has Many Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Has Many Association
|
4
6
|
# This is the proxy that handles a has many association.
|
5
7
|
#
|
6
8
|
# If the association has a <tt>:through</tt> option further specialization
|
7
9
|
# is provided by its child HasManyThroughAssociation.
|
8
10
|
class HasManyAssociation < CollectionAssociation #:nodoc:
|
11
|
+
include ForeignAssociation
|
9
12
|
|
10
13
|
def handle_dependency
|
11
14
|
case options[:dependent]
|
@@ -14,43 +17,48 @@ module ActiveRecord
|
|
14
17
|
|
15
18
|
when :restrict_with_error
|
16
19
|
unless empty?
|
17
|
-
record =
|
18
|
-
owner.errors.add(:base, :
|
19
|
-
|
20
|
+
record = owner.class.human_attribute_name(reflection.name).downcase
|
21
|
+
owner.errors.add(:base, :'restrict_dependent_destroy.has_many', record: record)
|
22
|
+
throw(:abort)
|
20
23
|
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
when :destroy
|
26
|
+
# No point in executing the counter update since we're going to destroy the parent anyway
|
27
|
+
load_target.each { |t| t.destroyed_by_association = reflection }
|
28
|
+
destroy_all
|
29
|
+
when :destroy_async
|
30
|
+
load_target.each do |t|
|
31
|
+
t.destroyed_by_association = reflection
|
29
32
|
end
|
30
|
-
end
|
31
|
-
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
unless target.empty?
|
35
|
+
association_class = target.first.class
|
36
|
+
primary_key_column = association_class.primary_key.to_sym
|
37
|
+
|
38
|
+
ids = target.collect do |assoc|
|
39
|
+
assoc.public_send(primary_key_column)
|
40
|
+
end
|
41
|
+
|
42
|
+
enqueue_destroy_association(
|
43
|
+
owner_model_name: owner.class.to_s,
|
44
|
+
owner_id: owner.id,
|
45
|
+
association_class: reflection.klass.to_s,
|
46
|
+
association_ids: ids,
|
47
|
+
association_primary_key_column: primary_key_column,
|
48
|
+
ensuring_owner_was_method: options.fetch(:ensuring_owner_was, nil)
|
49
|
+
)
|
50
|
+
end
|
39
51
|
else
|
40
|
-
|
52
|
+
delete_all
|
41
53
|
end
|
42
54
|
end
|
43
55
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
else
|
48
|
-
super
|
49
|
-
end
|
56
|
+
def insert_record(record, validate = true, raise = false)
|
57
|
+
set_owner_attributes(record)
|
58
|
+
super
|
50
59
|
end
|
51
60
|
|
52
61
|
private
|
53
|
-
|
54
62
|
# Returns the number of records in this collection.
|
55
63
|
#
|
56
64
|
# If the association has a counter cache it gets that value. Otherwise
|
@@ -65,102 +73,59 @@ module ActiveRecord
|
|
65
73
|
# If the collection is empty the target is set to an empty array and
|
66
74
|
# the loaded flag is set to true as well.
|
67
75
|
def count_records
|
68
|
-
count = if has_cached_counter?
|
69
|
-
owner.
|
76
|
+
count = if reflection.has_cached_counter?
|
77
|
+
owner.read_attribute(reflection.counter_cache_column).to_i
|
70
78
|
else
|
71
|
-
scope.count
|
79
|
+
scope.count(:all)
|
72
80
|
end
|
73
81
|
|
74
82
|
# If there's nothing in the database and @target has no new records
|
75
83
|
# we are certain the current target is an empty array. This is a
|
76
84
|
# documented side-effect of the method that may avoid an extra SELECT.
|
77
|
-
|
85
|
+
loaded! if count == 0
|
78
86
|
|
79
87
|
[association_scope.limit_value, count].compact.min
|
80
88
|
end
|
81
89
|
|
82
|
-
def has_cached_counter?(reflection = reflection())
|
83
|
-
owner.attribute_present?(cached_counter_attribute_name(reflection))
|
84
|
-
end
|
85
|
-
|
86
|
-
def cached_counter_attribute_name(reflection = reflection())
|
87
|
-
options[:counter_cache] || "#{reflection.name}_count"
|
88
|
-
end
|
89
|
-
|
90
90
|
def update_counter(difference, reflection = reflection())
|
91
|
-
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
def update_counter_in_database(difference, reflection = reflection())
|
96
|
-
if has_cached_counter?(reflection)
|
97
|
-
counter = cached_counter_attribute_name(reflection)
|
98
|
-
owner.class.update_counters(owner.id, counter => difference)
|
91
|
+
if reflection.has_cached_counter?
|
92
|
+
owner.increment!(reflection.counter_cache_column, difference)
|
99
93
|
end
|
100
94
|
end
|
101
95
|
|
102
96
|
def update_counter_in_memory(difference, reflection = reflection())
|
103
|
-
if
|
104
|
-
counter =
|
105
|
-
owner
|
106
|
-
owner.send(:
|
97
|
+
if reflection.counter_must_be_updated_by_has_many?
|
98
|
+
counter = reflection.counter_cache_column
|
99
|
+
owner.increment(counter, difference)
|
100
|
+
owner.send(:"clear_#{counter}_change")
|
107
101
|
end
|
108
102
|
end
|
109
103
|
|
110
|
-
# This shit is nasty. We need to avoid the following situation:
|
111
|
-
#
|
112
|
-
# * An associated record is deleted via record.destroy
|
113
|
-
# * Hence the callbacks run, and they find a belongs_to on the record with a
|
114
|
-
# :counter_cache options which points back at our owner. So they update the
|
115
|
-
# counter cache.
|
116
|
-
# * In which case, we must make sure to *not* update the counter cache, or else
|
117
|
-
# it will be decremented twice.
|
118
|
-
#
|
119
|
-
# Hence this method.
|
120
|
-
def inverse_updates_counter_cache?(reflection = reflection())
|
121
|
-
counter_name = cached_counter_attribute_name(reflection)
|
122
|
-
inverse_updates_counter_named?(counter_name, reflection)
|
123
|
-
end
|
124
|
-
|
125
|
-
def inverse_updates_counter_named?(counter_name, reflection = reflection())
|
126
|
-
reflection.klass._reflections.values.any? { |inverse_reflection|
|
127
|
-
inverse_reflection.belongs_to? &&
|
128
|
-
inverse_reflection.counter_cache_column == counter_name
|
129
|
-
}
|
130
|
-
end
|
131
|
-
|
132
104
|
def delete_count(method, scope)
|
133
105
|
if method == :delete_all
|
134
106
|
scope.delete_all
|
135
107
|
else
|
136
|
-
scope.update_all(
|
108
|
+
scope.update_all(nullified_owner_attributes)
|
137
109
|
end
|
138
110
|
end
|
139
111
|
|
140
112
|
def delete_or_nullify_all_records(method)
|
141
|
-
count = delete_count(method,
|
113
|
+
count = delete_count(method, scope)
|
142
114
|
update_counter(-count)
|
115
|
+
count
|
143
116
|
end
|
144
117
|
|
145
118
|
# Deletes the records according to the <tt>:dependent</tt> option.
|
146
119
|
def delete_records(records, method)
|
147
120
|
if method == :destroy
|
148
121
|
records.each(&:destroy!)
|
149
|
-
update_counter(-records.length) unless inverse_updates_counter_cache?
|
122
|
+
update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
|
150
123
|
else
|
151
124
|
scope = self.scope.where(reflection.klass.primary_key => records)
|
152
125
|
update_counter(-delete_count(method, scope))
|
153
126
|
end
|
154
127
|
end
|
155
128
|
|
156
|
-
def foreign_key_present?
|
157
|
-
if reflection.klass.primary_key
|
158
|
-
owner.attribute_present?(reflection.association_primary_key)
|
159
|
-
else
|
160
|
-
false
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
129
|
def concat_records(records, *)
|
165
130
|
update_counter_if_success(super, records.length)
|
166
131
|
end
|
@@ -179,6 +144,14 @@ module ActiveRecord
|
|
179
144
|
end
|
180
145
|
saved_successfully
|
181
146
|
end
|
147
|
+
|
148
|
+
def difference(a, b)
|
149
|
+
a - b
|
150
|
+
end
|
151
|
+
|
152
|
+
def intersection(a, b)
|
153
|
+
a & b
|
154
|
+
end
|
182
155
|
end
|
183
156
|
end
|
184
157
|
end
|
@@ -1,31 +1,14 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
-
# = Active Record Has Many Through Association
|
5
4
|
module Associations
|
5
|
+
# = Active Record Has Many Through Association
|
6
6
|
class HasManyThroughAssociation < HasManyAssociation #:nodoc:
|
7
7
|
include ThroughAssociation
|
8
8
|
|
9
9
|
def initialize(owner, reflection)
|
10
10
|
super
|
11
|
-
|
12
|
-
@through_records = {}
|
13
|
-
@through_association = nil
|
14
|
-
end
|
15
|
-
|
16
|
-
# Returns the size of the collection by executing a SELECT COUNT(*) query
|
17
|
-
# if the collection hasn't been loaded, and by calling collection.size if
|
18
|
-
# it has. If the collection will likely have a size greater than zero,
|
19
|
-
# and if fetching the collection will be needed afterwards, one less
|
20
|
-
# SELECT query will be generated by using #length instead.
|
21
|
-
def size
|
22
|
-
if has_cached_counter?
|
23
|
-
owner._read_attribute cached_counter_attribute_name(reflection)
|
24
|
-
elsif loaded?
|
25
|
-
target.size
|
26
|
-
else
|
27
|
-
super
|
28
|
-
end
|
11
|
+
@through_records = {}.compare_by_identity
|
29
12
|
end
|
30
13
|
|
31
14
|
def concat(*records)
|
@@ -38,49 +21,31 @@ module ActiveRecord
|
|
38
21
|
super
|
39
22
|
end
|
40
23
|
|
41
|
-
def concat_records(records)
|
42
|
-
ensure_not_nested
|
43
|
-
|
44
|
-
records = super(records, true)
|
45
|
-
|
46
|
-
if owner.new_record? && records
|
47
|
-
records.flatten.each do |record|
|
48
|
-
build_through_record(record)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
records
|
53
|
-
end
|
54
|
-
|
55
24
|
def insert_record(record, validate = true, raise = false)
|
56
25
|
ensure_not_nested
|
57
26
|
|
58
|
-
if record.new_record?
|
59
|
-
|
60
|
-
record.save!(:validate => validate)
|
61
|
-
else
|
62
|
-
return unless record.save(:validate => validate)
|
63
|
-
end
|
27
|
+
if record.new_record? || record.has_changes_to_save?
|
28
|
+
return unless super
|
64
29
|
end
|
65
30
|
|
66
31
|
save_through_record(record)
|
67
|
-
if has_cached_counter? && !through_reflection_updates_counter_cache?
|
68
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
69
|
-
Automatic updating of counter caches on through associations has been
|
70
|
-
deprecated, and will be removed in Rails 5. Instead, please set the
|
71
|
-
appropriate `counter_cache` options on the `has_many` and `belongs_to`
|
72
|
-
for your associations to #{through_reflection.name}.
|
73
|
-
MSG
|
74
32
|
|
75
|
-
update_counter_in_database(1)
|
76
|
-
end
|
77
33
|
record
|
78
34
|
end
|
79
35
|
|
80
36
|
private
|
37
|
+
def concat_records(records)
|
38
|
+
ensure_not_nested
|
39
|
+
|
40
|
+
records = super(records, true)
|
81
41
|
|
82
|
-
|
83
|
-
|
42
|
+
if owner.new_record? && records
|
43
|
+
records.flatten.each do |record|
|
44
|
+
build_through_record(record)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
records
|
84
49
|
end
|
85
50
|
|
86
51
|
# The through record (built with build_record) is temporarily cached
|
@@ -89,35 +54,40 @@ module ActiveRecord
|
|
89
54
|
# However, after insert_record has been called, the cache is cleared in
|
90
55
|
# order to allow multiple instances of the same record in an association.
|
91
56
|
def build_through_record(record)
|
92
|
-
@through_records[record
|
57
|
+
@through_records[record] ||= begin
|
93
58
|
ensure_mutable
|
94
59
|
|
95
|
-
|
96
|
-
|
97
|
-
|
60
|
+
attributes = through_scope_attributes
|
61
|
+
attributes[source_reflection.name] = record
|
62
|
+
attributes[source_reflection.foreign_type] = options[:source_type] if options[:source_type]
|
63
|
+
|
64
|
+
through_association.build(attributes)
|
98
65
|
end
|
99
66
|
end
|
100
67
|
|
101
|
-
|
102
|
-
[through_scope_attributes]
|
103
|
-
end
|
68
|
+
attr_reader :through_scope
|
104
69
|
|
105
70
|
def through_scope_attributes
|
71
|
+
scope = through_scope || self.scope
|
106
72
|
scope.where_values_hash(through_association.reflection.name.to_s).
|
107
73
|
except!(through_association.reflection.foreign_key,
|
108
74
|
through_association.reflection.klass.inheritance_column)
|
109
75
|
end
|
110
76
|
|
111
77
|
def save_through_record(record)
|
112
|
-
build_through_record(record)
|
78
|
+
association = build_through_record(record)
|
79
|
+
if association.changed?
|
80
|
+
association.save!
|
81
|
+
end
|
113
82
|
ensure
|
114
|
-
@through_records.delete(record
|
83
|
+
@through_records.delete(record)
|
115
84
|
end
|
116
85
|
|
117
86
|
def build_record(attributes)
|
118
87
|
ensure_not_nested
|
119
88
|
|
120
|
-
|
89
|
+
@through_scope = scope
|
90
|
+
record = super
|
121
91
|
|
122
92
|
inverse = source_reflection.inverse_of
|
123
93
|
if inverse
|
@@ -129,6 +99,13 @@ module ActiveRecord
|
|
129
99
|
end
|
130
100
|
|
131
101
|
record
|
102
|
+
ensure
|
103
|
+
@through_scope = nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def remove_records(existing_records, records, method)
|
107
|
+
super
|
108
|
+
delete_through_records(records)
|
132
109
|
end
|
133
110
|
|
134
111
|
def target_reflection_has_associated_record?
|
@@ -138,7 +115,7 @@ module ActiveRecord
|
|
138
115
|
def update_through_counter?(method)
|
139
116
|
case method
|
140
117
|
when :destroy
|
141
|
-
!inverse_updates_counter_cache?
|
118
|
+
!through_reflection.inverse_updates_counter_cache?
|
142
119
|
when :nullify
|
143
120
|
false
|
144
121
|
else
|
@@ -155,23 +132,15 @@ module ActiveRecord
|
|
155
132
|
|
156
133
|
scope = through_association.scope
|
157
134
|
scope.where! construct_join_attributes(*records)
|
135
|
+
scope = scope.where(through_scope_attributes)
|
158
136
|
|
159
137
|
case method
|
160
138
|
when :destroy
|
161
139
|
if scope.klass.primary_key
|
162
|
-
count = scope.destroy_all.
|
140
|
+
count = scope.destroy_all.count(&:destroyed?)
|
163
141
|
else
|
164
|
-
scope.each
|
165
|
-
|
166
|
-
end
|
167
|
-
|
168
|
-
arel = scope.arel
|
169
|
-
|
170
|
-
stmt = Arel::DeleteManager.new arel.engine
|
171
|
-
stmt.from scope.klass.arel_table
|
172
|
-
stmt.wheres = arel.constraints
|
173
|
-
|
174
|
-
count = scope.klass.connection.delete(stmt, 'SQL', scope.bind_values)
|
142
|
+
scope.each(&:_run_destroy_callbacks)
|
143
|
+
count = scope.delete_all
|
175
144
|
end
|
176
145
|
when :nullify
|
177
146
|
count = scope.update_all(source_reflection.foreign_key => nil)
|
@@ -188,9 +157,33 @@ module ActiveRecord
|
|
188
157
|
|
189
158
|
if through_reflection.collection? && update_through_counter?(method)
|
190
159
|
update_counter(-count, through_reflection)
|
160
|
+
else
|
161
|
+
update_counter(-count)
|
191
162
|
end
|
192
163
|
|
193
|
-
|
164
|
+
count
|
165
|
+
end
|
166
|
+
|
167
|
+
def difference(a, b)
|
168
|
+
distribution = distribution(b)
|
169
|
+
|
170
|
+
a.reject { |record| mark_occurrence(distribution, record) }
|
171
|
+
end
|
172
|
+
|
173
|
+
def intersection(a, b)
|
174
|
+
distribution = distribution(b)
|
175
|
+
|
176
|
+
a.select { |record| mark_occurrence(distribution, record) }
|
177
|
+
end
|
178
|
+
|
179
|
+
def mark_occurrence(distribution, record)
|
180
|
+
distribution[record] > 0 && distribution[record] -= 1
|
181
|
+
end
|
182
|
+
|
183
|
+
def distribution(array)
|
184
|
+
array.each_with_object(Hash.new(0)) do |record, distribution|
|
185
|
+
distribution[record] += 1
|
186
|
+
end
|
194
187
|
end
|
195
188
|
|
196
189
|
def through_records_for(record)
|
@@ -215,24 +208,19 @@ module ActiveRecord
|
|
215
208
|
end
|
216
209
|
end
|
217
210
|
|
218
|
-
@through_records.delete(record
|
211
|
+
@through_records.delete(record)
|
219
212
|
end
|
220
213
|
end
|
221
214
|
|
222
215
|
def find_target
|
223
216
|
return [] unless target_reflection_has_associated_record?
|
224
|
-
|
217
|
+
super
|
225
218
|
end
|
226
219
|
|
227
220
|
# NOTE - not sure that we can actually cope with inverses here
|
228
221
|
def invertible_for?(record)
|
229
222
|
false
|
230
223
|
end
|
231
|
-
|
232
|
-
def through_reflection_updates_counter_cache?
|
233
|
-
counter_name = cached_counter_attribute_name
|
234
|
-
inverse_updates_counter_named?(counter_name, through_reflection)
|
235
|
-
end
|
236
224
|
end
|
237
225
|
end
|
238
226
|
end
|
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Belongs To Has One Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Has One Association
|
4
6
|
class HasOneAssociation < SingularAssociation #:nodoc:
|
7
|
+
include ForeignAssociation
|
5
8
|
|
6
9
|
def handle_dependency
|
7
10
|
case options[:dependent]
|
@@ -10,9 +13,9 @@ module ActiveRecord
|
|
10
13
|
|
11
14
|
when :restrict_with_error
|
12
15
|
if load_target
|
13
|
-
record =
|
14
|
-
owner.errors.add(:base, :
|
15
|
-
|
16
|
+
record = owner.class.human_attribute_name(reflection.name).downcase
|
17
|
+
owner.errors.add(:base, :'restrict_dependent_destroy.has_one', record: record)
|
18
|
+
throw(:abort)
|
16
19
|
end
|
17
20
|
|
18
21
|
else
|
@@ -20,49 +23,61 @@ module ActiveRecord
|
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
+
def delete(method = options[:dependent])
|
27
|
+
if load_target
|
28
|
+
case method
|
29
|
+
when :delete
|
30
|
+
target.delete
|
31
|
+
when :destroy
|
32
|
+
target.destroyed_by_association = reflection
|
33
|
+
target.destroy
|
34
|
+
throw(:abort) unless target.destroyed?
|
35
|
+
when :destroy_async
|
36
|
+
primary_key_column = target.class.primary_key.to_sym
|
37
|
+
id = target.public_send(primary_key_column)
|
38
|
+
|
39
|
+
enqueue_destroy_association(
|
40
|
+
owner_model_name: owner.class.to_s,
|
41
|
+
owner_id: owner.id,
|
42
|
+
association_class: reflection.klass.to_s,
|
43
|
+
association_ids: [id],
|
44
|
+
association_primary_key_column: primary_key_column,
|
45
|
+
ensuring_owner_was_method: options.fetch(:ensuring_owner_was, nil)
|
46
|
+
)
|
47
|
+
when :nullify
|
48
|
+
target.update_columns(nullified_owner_attributes) if target.persisted?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def replace(record, save = true)
|
55
|
+
raise_on_type_mismatch!(record) if record
|
26
56
|
|
27
|
-
|
57
|
+
return target unless load_target || record
|
28
58
|
|
29
|
-
|
30
|
-
|
31
|
-
|
59
|
+
assigning_another_record = target != record
|
60
|
+
if assigning_another_record || record.has_changes_to_save?
|
61
|
+
save &&= owner.persisted?
|
32
62
|
|
33
|
-
|
34
|
-
|
63
|
+
transaction_if(save) do
|
64
|
+
remove_target!(options[:dependent]) if target && !target.destroyed? && assigning_another_record
|
35
65
|
|
36
|
-
|
37
|
-
|
38
|
-
|
66
|
+
if record
|
67
|
+
set_owner_attributes(record)
|
68
|
+
set_inverse_instance(record)
|
39
69
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
70
|
+
if save && !record.save
|
71
|
+
nullify_owner_attributes(record)
|
72
|
+
set_owner_attributes(target) if target
|
73
|
+
raise RecordNotSaved, "Failed to save the new associated #{reflection.name}."
|
74
|
+
end
|
44
75
|
end
|
45
76
|
end
|
46
77
|
end
|
47
|
-
end
|
48
78
|
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
def delete(method = options[:dependent])
|
53
|
-
if load_target
|
54
|
-
case method
|
55
|
-
when :delete
|
56
|
-
target.delete
|
57
|
-
when :destroy
|
58
|
-
target.destroy
|
59
|
-
when :nullify
|
60
|
-
target.update_columns(reflection.foreign_key => nil)
|
61
|
-
end
|
79
|
+
self.target = record
|
62
80
|
end
|
63
|
-
end
|
64
|
-
|
65
|
-
private
|
66
81
|
|
67
82
|
# The reason that the save param for replace is false, if for create (not just build),
|
68
83
|
# is because the setting of the foreign keys is actually handled by the scoping when
|
@@ -74,18 +89,22 @@ module ActiveRecord
|
|
74
89
|
|
75
90
|
def remove_target!(method)
|
76
91
|
case method
|
77
|
-
|
78
|
-
|
79
|
-
|
92
|
+
when :delete
|
93
|
+
target.delete
|
94
|
+
when :destroy
|
95
|
+
target.destroyed_by_association = reflection
|
96
|
+
if target.persisted?
|
80
97
|
target.destroy
|
81
|
-
|
82
|
-
|
98
|
+
end
|
99
|
+
else
|
100
|
+
nullify_owner_attributes(target)
|
101
|
+
remove_inverse_instance(target)
|
83
102
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
103
|
+
if target.persisted? && owner.persisted? && !target.save
|
104
|
+
set_owner_attributes(target)
|
105
|
+
raise RecordNotSaved, "Failed to remove the existing associated #{reflection.name}. " \
|
106
|
+
"The record failed to save after its foreign key was set to nil."
|
107
|
+
end
|
89
108
|
end
|
90
109
|
end
|
91
110
|
|
@@ -100,6 +119,14 @@ module ActiveRecord
|
|
100
119
|
yield
|
101
120
|
end
|
102
121
|
end
|
122
|
+
|
123
|
+
def _create_record(attributes, raise_error = false, &block)
|
124
|
+
unless owner.persisted?
|
125
|
+
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
|
126
|
+
end
|
127
|
+
|
128
|
+
super
|
129
|
+
end
|
103
130
|
end
|
104
131
|
end
|
105
132
|
end
|