activerecord 4.2.0 → 6.0.5.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 +852 -801
- data/MIT-LICENSE +4 -2
- data/README.rdoc +14 -13
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +267 -249
- data/lib/active_record/association_relation.rb +26 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -36
- data/lib/active_record/associations/association.rb +137 -55
- data/lib/active_record/associations/association_scope.rb +110 -132
- data/lib/active_record/associations/belongs_to_association.rb +67 -54
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +27 -40
- data/lib/active_record/associations/builder/belongs_to.rb +69 -55
- data/lib/active_record/associations/builder/collection_association.rb +10 -29
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +58 -70
- data/lib/active_record/associations/builder/has_many.rb +8 -4
- data/lib/active_record/associations/builder/has_one.rb +46 -5
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +150 -275
- data/lib/active_record/associations/collection_proxy.rb +253 -152
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +35 -84
- data/lib/active_record/associations/has_many_through_association.rb +62 -80
- data/lib/active_record/associations/has_one_association.rb +62 -49
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +43 -78
- 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 +159 -162
- data/lib/active_record/associations/preloader/association.rb +102 -113
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +96 -95
- 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 +1737 -1596
- data/lib/active_record/attribute_assignment.rb +57 -185
- data/lib/active_record/attribute_decorators.rb +39 -17
- data/lib/active_record/attribute_methods/before_type_cast.rb +14 -5
- data/lib/active_record/attribute_methods/dirty.rb +174 -134
- data/lib/active_record/attribute_methods/primary_key.rb +90 -84
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -77
- data/lib/active_record/attribute_methods/serialization.rb +40 -21
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -37
- data/lib/active_record/attribute_methods/write.rb +33 -56
- data/lib/active_record/attribute_methods.rb +124 -143
- data/lib/active_record/attributes.rb +213 -74
- data/lib/active_record/autosave_association.rb +125 -54
- data/lib/active_record/base.rb +60 -49
- data/lib/active_record/callbacks.rb +101 -76
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +36 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +810 -291
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +253 -108
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +83 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +171 -53
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -47
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +383 -239
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +736 -235
- data/lib/active_record/connection_adapters/abstract/transaction.rb +190 -87
- data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -192
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +536 -600
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -153
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -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 +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -196
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +71 -115
- 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 +5 -1
- 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/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 -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 +9 -5
- 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 +23 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -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 +465 -291
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +565 -363
- data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -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 +17 -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 +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +299 -364
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_handling.rb +167 -41
- data/lib/active_record/core.rb +277 -233
- data/lib/active_record/counter_cache.rb +71 -50
- 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 -106
- data/lib/active_record/enum.rb +172 -89
- data/lib/active_record/errors.rb +189 -53
- data/lib/active_record/explain.rb +22 -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 +35 -9
- 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 +225 -497
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +158 -115
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +123 -29
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +99 -98
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +76 -33
- 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 +166 -91
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +636 -290
- data/lib/active_record/model_schema.rb +344 -112
- data/lib/active_record/nested_attributes.rb +265 -215
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +559 -125
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +44 -30
- data/lib/active_record/railtie.rb +166 -47
- 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 +341 -202
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +461 -302
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +206 -55
- data/lib/active_record/relation/calculations.rb +270 -249
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +287 -255
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +86 -68
- data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -25
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -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 +53 -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 +112 -92
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +612 -392
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -17
- data/lib/active_record/relation/where_clause.rb +189 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/relation.rb +533 -340
- data/lib/active_record/result.rb +79 -43
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +144 -121
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +112 -93
- data/lib/active_record/schema_migration.rb +24 -20
- data/lib/active_record/scoping/default.rb +98 -82
- data/lib/active_record/scoping/named.rb +91 -33
- data/lib/active_record/scoping.rb +45 -27
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +73 -36
- data/lib/active_record/store.rb +127 -42
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +90 -0
- data/lib/active_record/tasks/database_tasks.rb +309 -99
- data/lib/active_record/tasks/mysql_database_tasks.rb +58 -89
- data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -31
- data/lib/active_record/tasks/sqlite_database_tasks.rb +37 -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 +86 -41
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +222 -146
- 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 +29 -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 +77 -23
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -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/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +43 -46
- data/lib/active_record/validations.rb +38 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +44 -21
- 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/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -8
- data/lib/rails/generators/active_record/migration.rb +30 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +174 -63
- 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_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- 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,20 @@
|
|
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
|
+
end
|
20
|
+
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,26 @@ 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
|
|
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
|
22
29
|
else
|
23
|
-
|
24
|
-
# No point in executing the counter update since we're going to destroy the parent anyway
|
25
|
-
load_target.each { |t| t.destroyed_by_association = reflection }
|
26
|
-
destroy_all
|
27
|
-
else
|
28
|
-
delete_all
|
29
|
-
end
|
30
|
+
delete_all
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
34
|
def insert_record(record, validate = true, raise = false)
|
34
35
|
set_owner_attributes(record)
|
35
|
-
|
36
|
-
|
37
|
-
if raise
|
38
|
-
record.save!(:validate => validate)
|
39
|
-
else
|
40
|
-
record.save(:validate => validate)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def empty?
|
45
|
-
if has_cached_counter?
|
46
|
-
size.zero?
|
47
|
-
else
|
48
|
-
super
|
49
|
-
end
|
36
|
+
super
|
50
37
|
end
|
51
38
|
|
52
39
|
private
|
53
|
-
|
54
40
|
# Returns the number of records in this collection.
|
55
41
|
#
|
56
42
|
# If the association has a counter cache it gets that value. Otherwise
|
@@ -65,102 +51,59 @@ module ActiveRecord
|
|
65
51
|
# If the collection is empty the target is set to an empty array and
|
66
52
|
# the loaded flag is set to true as well.
|
67
53
|
def count_records
|
68
|
-
count = if has_cached_counter?
|
69
|
-
owner._read_attribute
|
54
|
+
count = if reflection.has_cached_counter?
|
55
|
+
owner._read_attribute(reflection.counter_cache_column).to_i
|
70
56
|
else
|
71
|
-
scope.count
|
57
|
+
scope.count(:all)
|
72
58
|
end
|
73
59
|
|
74
60
|
# If there's nothing in the database and @target has no new records
|
75
61
|
# we are certain the current target is an empty array. This is a
|
76
62
|
# documented side-effect of the method that may avoid an extra SELECT.
|
77
|
-
|
63
|
+
loaded! if count == 0
|
78
64
|
|
79
65
|
[association_scope.limit_value, count].compact.min
|
80
66
|
end
|
81
67
|
|
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
68
|
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)
|
69
|
+
if reflection.has_cached_counter?
|
70
|
+
owner.increment!(reflection.counter_cache_column, difference)
|
99
71
|
end
|
100
72
|
end
|
101
73
|
|
102
74
|
def update_counter_in_memory(difference, reflection = reflection())
|
103
|
-
if
|
104
|
-
counter =
|
105
|
-
owner
|
106
|
-
owner.send(:
|
75
|
+
if reflection.counter_must_be_updated_by_has_many?
|
76
|
+
counter = reflection.counter_cache_column
|
77
|
+
owner.increment(counter, difference)
|
78
|
+
owner.send(:clear_attribute_change, counter) # eww
|
107
79
|
end
|
108
80
|
end
|
109
81
|
|
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
82
|
def delete_count(method, scope)
|
133
83
|
if method == :delete_all
|
134
84
|
scope.delete_all
|
135
85
|
else
|
136
|
-
scope.update_all(
|
86
|
+
scope.update_all(nullified_owner_attributes)
|
137
87
|
end
|
138
88
|
end
|
139
89
|
|
140
90
|
def delete_or_nullify_all_records(method)
|
141
|
-
count = delete_count(method,
|
91
|
+
count = delete_count(method, scope)
|
142
92
|
update_counter(-count)
|
93
|
+
count
|
143
94
|
end
|
144
95
|
|
145
96
|
# Deletes the records according to the <tt>:dependent</tt> option.
|
146
97
|
def delete_records(records, method)
|
147
98
|
if method == :destroy
|
148
99
|
records.each(&:destroy!)
|
149
|
-
update_counter(-records.length) unless inverse_updates_counter_cache?
|
100
|
+
update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
|
150
101
|
else
|
151
102
|
scope = self.scope.where(reflection.klass.primary_key => records)
|
152
103
|
update_counter(-delete_count(method, scope))
|
153
104
|
end
|
154
105
|
end
|
155
106
|
|
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
107
|
def concat_records(records, *)
|
165
108
|
update_counter_if_success(super, records.length)
|
166
109
|
end
|
@@ -179,6 +122,14 @@ module ActiveRecord
|
|
179
122
|
end
|
180
123
|
saved_successfully
|
181
124
|
end
|
125
|
+
|
126
|
+
def difference(a, b)
|
127
|
+
a - b
|
128
|
+
end
|
129
|
+
|
130
|
+
def intersection(a, b)
|
131
|
+
a & b
|
132
|
+
end
|
182
133
|
end
|
183
134
|
end
|
184
135
|
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 = {}
|
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
|
@@ -92,14 +57,12 @@ module ActiveRecord
|
|
92
57
|
@through_records[record.object_id] ||= begin
|
93
58
|
ensure_mutable
|
94
59
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end
|
99
|
-
end
|
60
|
+
attributes = through_scope_attributes
|
61
|
+
attributes[source_reflection.name] = record
|
62
|
+
attributes[source_reflection.foreign_type] = options[:source_type] if options[:source_type]
|
100
63
|
|
101
|
-
|
102
|
-
|
64
|
+
through_association.build(attributes)
|
65
|
+
end
|
103
66
|
end
|
104
67
|
|
105
68
|
def through_scope_attributes
|
@@ -109,7 +72,10 @@ module ActiveRecord
|
|
109
72
|
end
|
110
73
|
|
111
74
|
def save_through_record(record)
|
112
|
-
build_through_record(record)
|
75
|
+
association = build_through_record(record)
|
76
|
+
if association.changed?
|
77
|
+
association.save!
|
78
|
+
end
|
113
79
|
ensure
|
114
80
|
@through_records.delete(record.object_id)
|
115
81
|
end
|
@@ -117,7 +83,7 @@ module ActiveRecord
|
|
117
83
|
def build_record(attributes)
|
118
84
|
ensure_not_nested
|
119
85
|
|
120
|
-
record = super
|
86
|
+
record = super
|
121
87
|
|
122
88
|
inverse = source_reflection.inverse_of
|
123
89
|
if inverse
|
@@ -131,6 +97,11 @@ module ActiveRecord
|
|
131
97
|
record
|
132
98
|
end
|
133
99
|
|
100
|
+
def remove_records(existing_records, records, method)
|
101
|
+
super
|
102
|
+
delete_through_records(records)
|
103
|
+
end
|
104
|
+
|
134
105
|
def target_reflection_has_associated_record?
|
135
106
|
!(through_reflection.belongs_to? && owner[through_reflection.foreign_key].blank?)
|
136
107
|
end
|
@@ -138,7 +109,7 @@ module ActiveRecord
|
|
138
109
|
def update_through_counter?(method)
|
139
110
|
case method
|
140
111
|
when :destroy
|
141
|
-
!inverse_updates_counter_cache?
|
112
|
+
!through_reflection.inverse_updates_counter_cache?
|
142
113
|
when :nullify
|
143
114
|
false
|
144
115
|
else
|
@@ -155,23 +126,15 @@ module ActiveRecord
|
|
155
126
|
|
156
127
|
scope = through_association.scope
|
157
128
|
scope.where! construct_join_attributes(*records)
|
129
|
+
scope = scope.where(through_scope_attributes)
|
158
130
|
|
159
131
|
case method
|
160
132
|
when :destroy
|
161
133
|
if scope.klass.primary_key
|
162
|
-
count = scope.destroy_all.
|
134
|
+
count = scope.destroy_all.count(&:destroyed?)
|
163
135
|
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)
|
136
|
+
scope.each(&:_run_destroy_callbacks)
|
137
|
+
count = scope.delete_all
|
175
138
|
end
|
176
139
|
when :nullify
|
177
140
|
count = scope.update_all(source_reflection.foreign_key => nil)
|
@@ -188,9 +151,33 @@ module ActiveRecord
|
|
188
151
|
|
189
152
|
if through_reflection.collection? && update_through_counter?(method)
|
190
153
|
update_counter(-count, through_reflection)
|
154
|
+
else
|
155
|
+
update_counter(-count)
|
191
156
|
end
|
192
157
|
|
193
|
-
|
158
|
+
count
|
159
|
+
end
|
160
|
+
|
161
|
+
def difference(a, b)
|
162
|
+
distribution = distribution(b)
|
163
|
+
|
164
|
+
a.reject { |record| mark_occurrence(distribution, record) }
|
165
|
+
end
|
166
|
+
|
167
|
+
def intersection(a, b)
|
168
|
+
distribution = distribution(b)
|
169
|
+
|
170
|
+
a.select { |record| mark_occurrence(distribution, record) }
|
171
|
+
end
|
172
|
+
|
173
|
+
def mark_occurrence(distribution, record)
|
174
|
+
distribution[record] > 0 && distribution[record] -= 1
|
175
|
+
end
|
176
|
+
|
177
|
+
def distribution(array)
|
178
|
+
array.each_with_object(Hash.new(0)) do |record, distribution|
|
179
|
+
distribution[record] += 1
|
180
|
+
end
|
194
181
|
end
|
195
182
|
|
196
183
|
def through_records_for(record)
|
@@ -221,18 +208,13 @@ module ActiveRecord
|
|
221
208
|
|
222
209
|
def find_target
|
223
210
|
return [] unless target_reflection_has_associated_record?
|
224
|
-
|
211
|
+
super
|
225
212
|
end
|
226
213
|
|
227
214
|
# NOTE - not sure that we can actually cope with inverses here
|
228
215
|
def invertible_for?(record)
|
229
216
|
false
|
230
217
|
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
218
|
end
|
237
219
|
end
|
238
220
|
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,49 @@ 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 :nullify
|
36
|
+
target.update_columns(nullified_owner_attributes) if target.persisted?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def replace(record, save = true)
|
43
|
+
raise_on_type_mismatch!(record) if record
|
26
44
|
|
27
|
-
|
45
|
+
return target unless load_target || record
|
28
46
|
|
29
|
-
|
30
|
-
|
31
|
-
|
47
|
+
assigning_another_record = target != record
|
48
|
+
if assigning_another_record || record.has_changes_to_save?
|
49
|
+
save &&= owner.persisted?
|
32
50
|
|
33
|
-
|
34
|
-
|
51
|
+
transaction_if(save) do
|
52
|
+
remove_target!(options[:dependent]) if target && !target.destroyed? && assigning_another_record
|
35
53
|
|
36
|
-
|
37
|
-
|
38
|
-
|
54
|
+
if record
|
55
|
+
set_owner_attributes(record)
|
56
|
+
set_inverse_instance(record)
|
39
57
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
58
|
+
if save && !record.save
|
59
|
+
nullify_owner_attributes(record)
|
60
|
+
set_owner_attributes(target) if target
|
61
|
+
raise RecordNotSaved, "Failed to save the new associated #{reflection.name}."
|
62
|
+
end
|
44
63
|
end
|
45
64
|
end
|
46
65
|
end
|
47
|
-
end
|
48
66
|
|
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
|
67
|
+
self.target = record
|
62
68
|
end
|
63
|
-
end
|
64
|
-
|
65
|
-
private
|
66
69
|
|
67
70
|
# The reason that the save param for replace is false, if for create (not just build),
|
68
71
|
# is because the setting of the foreign keys is actually handled by the scoping when
|
@@ -74,18 +77,20 @@ module ActiveRecord
|
|
74
77
|
|
75
78
|
def remove_target!(method)
|
76
79
|
case method
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
80
|
+
when :delete
|
81
|
+
target.delete
|
82
|
+
when :destroy
|
83
|
+
target.destroyed_by_association = reflection
|
84
|
+
target.destroy
|
85
|
+
else
|
86
|
+
nullify_owner_attributes(target)
|
87
|
+
remove_inverse_instance(target)
|
88
|
+
|
89
|
+
if target.persisted? && owner.persisted? && !target.save
|
90
|
+
set_owner_attributes(target)
|
91
|
+
raise RecordNotSaved, "Failed to remove the existing associated #{reflection.name}. " \
|
92
|
+
"The record failed to save after its foreign key was set to nil."
|
93
|
+
end
|
89
94
|
end
|
90
95
|
end
|
91
96
|
|
@@ -100,6 +105,14 @@ module ActiveRecord
|
|
100
105
|
yield
|
101
106
|
end
|
102
107
|
end
|
108
|
+
|
109
|
+
def _create_record(attributes, raise_error = false, &block)
|
110
|
+
unless owner.persisted?
|
111
|
+
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
|
112
|
+
end
|
113
|
+
|
114
|
+
super
|
115
|
+
end
|
103
116
|
end
|
104
117
|
end
|
105
118
|
end
|
@@ -1,30 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Has One Through Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Has One Through Association
|
4
6
|
class HasOneThroughAssociation < HasOneAssociation #:nodoc:
|
5
7
|
include ThroughAssociation
|
6
8
|
|
7
|
-
def replace(record)
|
8
|
-
create_through_record(record)
|
9
|
-
self.target = record
|
10
|
-
end
|
11
|
-
|
12
9
|
private
|
10
|
+
def replace(record, save = true)
|
11
|
+
create_through_record(record, save)
|
12
|
+
self.target = record
|
13
|
+
end
|
13
14
|
|
14
|
-
def create_through_record(record)
|
15
|
+
def create_through_record(record, save)
|
15
16
|
ensure_not_nested
|
16
17
|
|
17
|
-
through_proxy =
|
18
|
-
through_record = through_proxy.
|
18
|
+
through_proxy = through_association
|
19
|
+
through_record = through_proxy.load_target
|
19
20
|
|
20
21
|
if through_record && !record
|
21
22
|
through_record.destroy
|
22
23
|
elsif record
|
23
24
|
attributes = construct_join_attributes(record)
|
24
25
|
|
26
|
+
if through_record && through_record.destroyed?
|
27
|
+
through_record = through_proxy.tap(&:reload).target
|
28
|
+
end
|
29
|
+
|
25
30
|
if through_record
|
26
|
-
through_record.
|
27
|
-
|
31
|
+
if through_record.new_record?
|
32
|
+
through_record.assign_attributes(attributes)
|
33
|
+
else
|
34
|
+
through_record.update(attributes)
|
35
|
+
end
|
36
|
+
elsif owner.new_record? || !save
|
28
37
|
through_proxy.build(attributes)
|
29
38
|
else
|
30
39
|
through_proxy.create(attributes)
|