activerecord 4.2.11.3 → 6.0.0
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 +613 -1643
- data/MIT-LICENSE +4 -2
- data/README.rdoc +13 -12
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record.rb +41 -22
- data/lib/active_record/aggregations.rb +267 -251
- data/lib/active_record/association_relation.rb +11 -6
- data/lib/active_record/associations.rb +1737 -1597
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +125 -58
- data/lib/active_record/associations/association_scope.rb +103 -132
- data/lib/active_record/associations/belongs_to_association.rb +65 -60
- 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 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
- 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 +131 -287
- data/lib/active_record/associations/collection_proxy.rb +241 -146
- data/lib/active_record/associations/foreign_association.rb +10 -1
- data/lib/active_record/associations/has_many_association.rb +34 -97
- data/lib/active_record/associations/has_many_through_association.rb +60 -87
- data/lib/active_record/associations/has_one_association.rb +61 -49
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +137 -167
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -86
- 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/preloader.rb +90 -92
- data/lib/active_record/associations/preloader/association.rb +90 -123
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +38 -18
- data/lib/active_record/attribute_assignment.rb +56 -183
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods.rb +120 -135
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
- data/lib/active_record/attribute_methods/dirty.rb +174 -144
- data/lib/active_record/attribute_methods/primary_key.rb +91 -83
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -76
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
- data/lib/active_record/attribute_methods/write.rb +32 -54
- data/lib/active_record/attributes.rb +214 -82
- data/lib/active_record/autosave_association.rb +91 -37
- data/lib/active_record/base.rb +57 -45
- data/lib/active_record/callbacks.rb +100 -74
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -296
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -115
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -243
- data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
- data/lib/active_record/connection_adapters/abstract_adapter.rb +460 -204
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +510 -635
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
- 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 +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -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 +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -180
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -114
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +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 +9 -22
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +10 -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/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 +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +551 -356
- 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 +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -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 +290 -345
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +176 -41
- data/lib/active_record/core.rb +251 -231
- data/lib/active_record/counter_cache.rb +67 -49
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +163 -86
- data/lib/active_record/errors.rb +188 -53
- data/lib/active_record/explain.rb +23 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +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 +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +228 -499
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +158 -112
- 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 +21 -3
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +87 -96
- 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.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +621 -303
- data/lib/active_record/migration/command_recorder.rb +177 -90
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/model_schema.rb +312 -112
- data/lib/active_record/nested_attributes.rb +264 -222
- data/lib/active_record/no_touching.rb +14 -1
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +557 -125
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +43 -29
- data/lib/active_record/railtie.rb +143 -44
- 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 +328 -185
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +428 -279
- data/lib/active_record/relation.rb +518 -341
- data/lib/active_record/relation/batches.rb +207 -55
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/calculations.rb +267 -253
- data/lib/active_record/relation/delegation.rb +70 -80
- data/lib/active_record/relation/finder_methods.rb +277 -241
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +78 -87
- data/lib/active_record/relation/predicate_builder.rb +114 -119
- data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
- 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/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +575 -394
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -13
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/result.rb +79 -42
- 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 -17
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/scoping/default.rb +101 -85
- data/lib/active_record/scoping/named.rb +86 -33
- 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 +75 -0
- data/lib/active_record/tasks/database_tasks.rb +307 -100
- data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
- data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +86 -40
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +216 -150
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +78 -23
- data/lib/active_record/type/adapter_specific_registry.rb +129 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
- 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 +24 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -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 +42 -55
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +51 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -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.rb +68 -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/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration.rb +31 -1
- 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 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +164 -59
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- 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/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord::Associations
|
2
|
-
module ForeignAssociation
|
4
|
+
module ForeignAssociation # :nodoc:
|
3
5
|
def foreign_key_present?
|
4
6
|
if reflection.klass.primary_key
|
5
7
|
owner.attribute_present?(reflection.active_record_primary_key)
|
@@ -7,5 +9,12 @@ module ActiveRecord::Associations
|
|
7
9
|
false
|
8
10
|
end
|
9
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
|
10
19
|
end
|
11
20
|
end
|
@@ -1,6 +1,8 @@
|
|
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
|
@@ -15,39 +17,23 @@ module ActiveRecord
|
|
15
17
|
|
16
18
|
when :restrict_with_error
|
17
19
|
unless empty?
|
18
|
-
record =
|
19
|
-
owner.errors.add(:base, :
|
20
|
-
|
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)
|
21
23
|
end
|
22
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
|
23
29
|
else
|
24
|
-
|
25
|
-
# No point in executing the counter update since we're going to destroy the parent anyway
|
26
|
-
load_target.each { |t| t.destroyed_by_association = reflection }
|
27
|
-
destroy_all
|
28
|
-
else
|
29
|
-
delete_all
|
30
|
-
end
|
30
|
+
delete_all
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
def insert_record(record, validate = true, raise = false)
|
35
35
|
set_owner_attributes(record)
|
36
|
-
|
37
|
-
|
38
|
-
if raise
|
39
|
-
record.save!(:validate => validate)
|
40
|
-
else
|
41
|
-
record.save(:validate => validate)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def empty?
|
46
|
-
if has_cached_counter?
|
47
|
-
size.zero?
|
48
|
-
else
|
49
|
-
super
|
50
|
-
end
|
36
|
+
super
|
51
37
|
end
|
52
38
|
|
53
39
|
private
|
@@ -66,110 +52,53 @@ module ActiveRecord
|
|
66
52
|
# If the collection is empty the target is set to an empty array and
|
67
53
|
# the loaded flag is set to true as well.
|
68
54
|
def count_records
|
69
|
-
count = if has_cached_counter?
|
70
|
-
owner._read_attribute
|
55
|
+
count = if reflection.has_cached_counter?
|
56
|
+
owner._read_attribute(reflection.counter_cache_column).to_i
|
71
57
|
else
|
72
|
-
scope.count
|
58
|
+
scope.count(:all)
|
73
59
|
end
|
74
60
|
|
75
61
|
# If there's nothing in the database and @target has no new records
|
76
62
|
# we are certain the current target is an empty array. This is a
|
77
63
|
# documented side-effect of the method that may avoid an extra SELECT.
|
78
|
-
|
64
|
+
loaded! if count == 0
|
79
65
|
|
80
66
|
[association_scope.limit_value, count].compact.min
|
81
67
|
end
|
82
68
|
|
83
|
-
|
84
|
-
# Returns whether a counter cache should be used for this association.
|
85
|
-
#
|
86
|
-
# The counter_cache option must be given on either the owner or inverse
|
87
|
-
# association, and the column must be present on the owner.
|
88
|
-
def has_cached_counter?(reflection = reflection())
|
89
|
-
if reflection.options[:counter_cache] || (inverse = inverse_which_updates_counter_cache(reflection)) && inverse.options[:counter_cache]
|
90
|
-
owner.attribute_present?(cached_counter_attribute_name(reflection))
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def cached_counter_attribute_name(reflection = reflection())
|
95
|
-
if reflection.options[:counter_cache]
|
96
|
-
reflection.options[:counter_cache].to_s
|
97
|
-
else
|
98
|
-
"#{reflection.name}_count"
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
69
|
def update_counter(difference, reflection = reflection())
|
103
|
-
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
def update_counter_in_database(difference, reflection = reflection())
|
108
|
-
if has_cached_counter?(reflection)
|
109
|
-
counter = cached_counter_attribute_name(reflection)
|
110
|
-
owner.class.update_counters(owner.id, counter => difference)
|
70
|
+
if reflection.has_cached_counter?
|
71
|
+
owner.increment!(reflection.counter_cache_column, difference)
|
111
72
|
end
|
112
73
|
end
|
113
74
|
|
114
75
|
def update_counter_in_memory(difference, reflection = reflection())
|
115
|
-
if counter_must_be_updated_by_has_many?
|
116
|
-
counter =
|
117
|
-
owner
|
118
|
-
owner.send(:
|
76
|
+
if reflection.counter_must_be_updated_by_has_many?
|
77
|
+
counter = reflection.counter_cache_column
|
78
|
+
owner.increment(counter, difference)
|
79
|
+
owner.send(:clear_attribute_change, counter) # eww
|
119
80
|
end
|
120
81
|
end
|
121
82
|
|
122
|
-
# This shit is nasty. We need to avoid the following situation:
|
123
|
-
#
|
124
|
-
# * An associated record is deleted via record.destroy
|
125
|
-
# * Hence the callbacks run, and they find a belongs_to on the record with a
|
126
|
-
# :counter_cache options which points back at our owner. So they update the
|
127
|
-
# counter cache.
|
128
|
-
# * In which case, we must make sure to *not* update the counter cache, or else
|
129
|
-
# it will be decremented twice.
|
130
|
-
#
|
131
|
-
# Hence this method.
|
132
|
-
def inverse_which_updates_counter_cache(reflection = reflection())
|
133
|
-
counter_name = cached_counter_attribute_name(reflection)
|
134
|
-
inverse_which_updates_counter_named(counter_name, reflection)
|
135
|
-
end
|
136
|
-
alias inverse_updates_counter_cache? inverse_which_updates_counter_cache
|
137
|
-
|
138
|
-
def inverse_which_updates_counter_named(counter_name, reflection)
|
139
|
-
reflection.klass._reflections.values.find { |inverse_reflection|
|
140
|
-
inverse_reflection.belongs_to? &&
|
141
|
-
inverse_reflection.counter_cache_column == counter_name
|
142
|
-
}
|
143
|
-
end
|
144
|
-
alias inverse_updates_counter_named? inverse_which_updates_counter_named
|
145
|
-
|
146
|
-
def inverse_updates_counter_in_memory?(reflection)
|
147
|
-
inverse = inverse_which_updates_counter_cache(reflection)
|
148
|
-
inverse && inverse == reflection.inverse_of
|
149
|
-
end
|
150
|
-
|
151
|
-
def counter_must_be_updated_by_has_many?(reflection)
|
152
|
-
!inverse_updates_counter_in_memory?(reflection) && has_cached_counter?(reflection)
|
153
|
-
end
|
154
|
-
|
155
83
|
def delete_count(method, scope)
|
156
84
|
if method == :delete_all
|
157
85
|
scope.delete_all
|
158
86
|
else
|
159
|
-
scope.update_all(
|
87
|
+
scope.update_all(nullified_owner_attributes)
|
160
88
|
end
|
161
89
|
end
|
162
90
|
|
163
91
|
def delete_or_nullify_all_records(method)
|
164
|
-
count = delete_count(method,
|
92
|
+
count = delete_count(method, scope)
|
165
93
|
update_counter(-count)
|
94
|
+
count
|
166
95
|
end
|
167
96
|
|
168
97
|
# Deletes the records according to the <tt>:dependent</tt> option.
|
169
98
|
def delete_records(records, method)
|
170
99
|
if method == :destroy
|
171
100
|
records.each(&:destroy!)
|
172
|
-
update_counter(-records.length) unless inverse_updates_counter_cache?
|
101
|
+
update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
|
173
102
|
else
|
174
103
|
scope = self.scope.where(reflection.klass.primary_key => records)
|
175
104
|
update_counter(-delete_count(method, scope))
|
@@ -194,6 +123,14 @@ module ActiveRecord
|
|
194
123
|
end
|
195
124
|
saved_successfully
|
196
125
|
end
|
126
|
+
|
127
|
+
def difference(a, b)
|
128
|
+
a - b
|
129
|
+
end
|
130
|
+
|
131
|
+
def intersection(a, b)
|
132
|
+
a & b
|
133
|
+
end
|
197
134
|
end
|
198
135
|
end
|
199
136
|
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,21 +57,14 @@ module ActiveRecord
|
|
92
57
|
@through_records[record.object_id] ||= begin
|
93
58
|
ensure_mutable
|
94
59
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
if options[:source_type]
|
99
|
-
through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
|
100
|
-
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]
|
101
63
|
|
102
|
-
|
64
|
+
through_association.build(attributes)
|
103
65
|
end
|
104
66
|
end
|
105
67
|
|
106
|
-
def options_for_through_record
|
107
|
-
[through_scope_attributes]
|
108
|
-
end
|
109
|
-
|
110
68
|
def through_scope_attributes
|
111
69
|
scope.where_values_hash(through_association.reflection.name.to_s).
|
112
70
|
except!(through_association.reflection.foreign_key,
|
@@ -114,7 +72,10 @@ module ActiveRecord
|
|
114
72
|
end
|
115
73
|
|
116
74
|
def save_through_record(record)
|
117
|
-
build_through_record(record)
|
75
|
+
association = build_through_record(record)
|
76
|
+
if association.changed?
|
77
|
+
association.save!
|
78
|
+
end
|
118
79
|
ensure
|
119
80
|
@through_records.delete(record.object_id)
|
120
81
|
end
|
@@ -122,7 +83,7 @@ module ActiveRecord
|
|
122
83
|
def build_record(attributes)
|
123
84
|
ensure_not_nested
|
124
85
|
|
125
|
-
record = super
|
86
|
+
record = super
|
126
87
|
|
127
88
|
inverse = source_reflection.inverse_of
|
128
89
|
if inverse
|
@@ -136,6 +97,11 @@ module ActiveRecord
|
|
136
97
|
record
|
137
98
|
end
|
138
99
|
|
100
|
+
def remove_records(existing_records, records, method)
|
101
|
+
super
|
102
|
+
delete_through_records(records)
|
103
|
+
end
|
104
|
+
|
139
105
|
def target_reflection_has_associated_record?
|
140
106
|
!(through_reflection.belongs_to? && owner[through_reflection.foreign_key].blank?)
|
141
107
|
end
|
@@ -143,7 +109,7 @@ module ActiveRecord
|
|
143
109
|
def update_through_counter?(method)
|
144
110
|
case method
|
145
111
|
when :destroy
|
146
|
-
!inverse_updates_counter_cache?
|
112
|
+
!through_reflection.inverse_updates_counter_cache?
|
147
113
|
when :nullify
|
148
114
|
false
|
149
115
|
else
|
@@ -160,23 +126,15 @@ module ActiveRecord
|
|
160
126
|
|
161
127
|
scope = through_association.scope
|
162
128
|
scope.where! construct_join_attributes(*records)
|
129
|
+
scope = scope.where(through_scope_attributes)
|
163
130
|
|
164
131
|
case method
|
165
132
|
when :destroy
|
166
133
|
if scope.klass.primary_key
|
167
|
-
count = scope.destroy_all.
|
134
|
+
count = scope.destroy_all.count(&:destroyed?)
|
168
135
|
else
|
169
|
-
scope.each
|
170
|
-
|
171
|
-
end
|
172
|
-
|
173
|
-
arel = scope.arel
|
174
|
-
|
175
|
-
stmt = Arel::DeleteManager.new arel.engine
|
176
|
-
stmt.from scope.klass.arel_table
|
177
|
-
stmt.wheres = arel.constraints
|
178
|
-
|
179
|
-
count = scope.klass.connection.delete(stmt, 'SQL', scope.bind_values)
|
136
|
+
scope.each(&:_run_destroy_callbacks)
|
137
|
+
count = scope.delete_all
|
180
138
|
end
|
181
139
|
when :nullify
|
182
140
|
count = scope.update_all(source_reflection.foreign_key => nil)
|
@@ -196,6 +154,30 @@ module ActiveRecord
|
|
196
154
|
else
|
197
155
|
update_counter(-count)
|
198
156
|
end
|
157
|
+
|
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
|
199
181
|
end
|
200
182
|
|
201
183
|
def through_records_for(record)
|
@@ -226,22 +208,13 @@ module ActiveRecord
|
|
226
208
|
|
227
209
|
def find_target
|
228
210
|
return [] unless target_reflection_has_associated_record?
|
229
|
-
|
211
|
+
super
|
230
212
|
end
|
231
213
|
|
232
214
|
# NOTE - not sure that we can actually cope with inverses here
|
233
215
|
def invertible_for?(record)
|
234
216
|
false
|
235
217
|
end
|
236
|
-
|
237
|
-
def has_cached_counter?(reflection = reflection())
|
238
|
-
owner.attribute_present?(cached_counter_attribute_name(reflection))
|
239
|
-
end
|
240
|
-
|
241
|
-
def through_reflection_updates_counter_cache?
|
242
|
-
counter_name = cached_counter_attribute_name
|
243
|
-
inverse_updates_counter_named?(counter_name, through_reflection)
|
244
|
-
end
|
245
218
|
end
|
246
219
|
end
|
247
220
|
end
|