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,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record Counter Cache
|
3
5
|
module CounterCache
|
@@ -12,13 +14,21 @@ module ActiveRecord
|
|
12
14
|
#
|
13
15
|
# * +id+ - The id of the object you wish to reset a counter on.
|
14
16
|
# * +counters+ - One or more association counters to reset. Association name or counter name can be given.
|
17
|
+
# * <tt>:touch</tt> - Touch timestamp columns when updating.
|
18
|
+
# Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
|
19
|
+
# touch that column or an array of symbols to touch just those ones.
|
15
20
|
#
|
16
21
|
# ==== Examples
|
17
22
|
#
|
18
|
-
# # For Post with id #1
|
23
|
+
# # For the Post with id #1, reset the comments_count
|
19
24
|
# Post.reset_counters(1, :comments)
|
20
|
-
|
25
|
+
#
|
26
|
+
# # Like above, but also touch the +updated_at+ and/or +updated_on+
|
27
|
+
# # attributes.
|
28
|
+
# Post.reset_counters(1, :comments, touch: true)
|
29
|
+
def reset_counters(id, *counters, touch: nil)
|
21
30
|
object = find(id)
|
31
|
+
|
22
32
|
counters.each do |counter_association|
|
23
33
|
has_many_association = _reflect_on_association(counter_association)
|
24
34
|
unless has_many_association
|
@@ -26,7 +36,7 @@ module ActiveRecord
|
|
26
36
|
has_many_association = has_many.find { |association| association.counter_cache_column && association.counter_cache_column.to_sym == counter_association.to_sym }
|
27
37
|
counter_association = has_many_association.plural_name if has_many_association
|
28
38
|
end
|
29
|
-
raise ArgumentError, "'#{
|
39
|
+
raise ArgumentError, "'#{name}' has no association called '#{counter_association}'" unless has_many_association
|
30
40
|
|
31
41
|
if has_many_association.is_a? ActiveRecord::Reflection::ThroughReflection
|
32
42
|
has_many_association = has_many_association.through_reflection
|
@@ -37,25 +47,33 @@ module ActiveRecord
|
|
37
47
|
reflection = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
|
38
48
|
counter_name = reflection.counter_cache_column
|
39
49
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
50
|
+
updates = { counter_name => object.send(counter_association).count(:all) }
|
51
|
+
|
52
|
+
if touch
|
53
|
+
names = touch if touch != true
|
54
|
+
updates.merge!(touch_attributes_with_time(*names))
|
55
|
+
end
|
56
|
+
|
57
|
+
unscoped.where(primary_key => object.id).update_all(updates)
|
44
58
|
end
|
45
|
-
|
59
|
+
|
60
|
+
true
|
46
61
|
end
|
47
62
|
|
48
63
|
# A generic "counter updater" implementation, intended primarily to be
|
49
|
-
# used by increment_counter and decrement_counter, but which may also
|
64
|
+
# used by #increment_counter and #decrement_counter, but which may also
|
50
65
|
# be useful on its own. It simply does a direct SQL update for the record
|
51
66
|
# with the given ID, altering the given hash of counters by the amount
|
52
67
|
# given by the corresponding value:
|
53
68
|
#
|
54
69
|
# ==== Parameters
|
55
70
|
#
|
56
|
-
# * +id+ - The id of the object you wish to update a counter on or an
|
71
|
+
# * +id+ - The id of the object you wish to update a counter on or an array of ids.
|
57
72
|
# * +counters+ - A Hash containing the names of the fields
|
58
73
|
# to update as keys and the amount to update the field by as values.
|
74
|
+
# * <tt>:touch</tt> option - Touch timestamp columns when updating.
|
75
|
+
# If attribute names are passed, they are updated along with updated_at/on
|
76
|
+
# attributes.
|
59
77
|
#
|
60
78
|
# ==== Examples
|
61
79
|
#
|
@@ -74,75 +92,78 @@ module ActiveRecord
|
|
74
92
|
# # UPDATE posts
|
75
93
|
# # SET comment_count = COALESCE(comment_count, 0) + 1
|
76
94
|
# # WHERE id IN (10, 15)
|
95
|
+
#
|
96
|
+
# # For the Posts with id of 10 and 15, increment the comment_count by 1
|
97
|
+
# # and update the updated_at value for each counter.
|
98
|
+
# Post.update_counters [10, 15], comment_count: 1, touch: true
|
99
|
+
# # Executes the following SQL:
|
100
|
+
# # UPDATE posts
|
101
|
+
# # SET comment_count = COALESCE(comment_count, 0) + 1,
|
102
|
+
# # `updated_at` = '2016-10-13T09:59:23-05:00'
|
103
|
+
# # WHERE id IN (10, 15)
|
77
104
|
def update_counters(id, counters)
|
78
|
-
|
79
|
-
operator = value < 0 ? '-' : '+'
|
80
|
-
quoted_column = connection.quote_column_name(counter_name)
|
81
|
-
"#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}"
|
82
|
-
end
|
83
|
-
|
84
|
-
unscoped.where(primary_key => id).update_all updates.join(', ')
|
105
|
+
unscoped.where!(primary_key => id).update_counters(counters)
|
85
106
|
end
|
86
107
|
|
87
108
|
# Increment a numeric field by one, via a direct SQL update.
|
88
109
|
#
|
89
110
|
# This method is used primarily for maintaining counter_cache columns that are
|
90
|
-
# used to store aggregate values. For example, a DiscussionBoard may cache
|
111
|
+
# used to store aggregate values. For example, a +DiscussionBoard+ may cache
|
91
112
|
# posts_count and comments_count to avoid running an SQL query to calculate the
|
92
113
|
# number of posts and comments there are, each time it is displayed.
|
93
114
|
#
|
94
115
|
# ==== Parameters
|
95
116
|
#
|
96
117
|
# * +counter_name+ - The name of the field that should be incremented.
|
97
|
-
# * +id+ - The id of the object that should be incremented or an
|
118
|
+
# * +id+ - The id of the object that should be incremented or an array of ids.
|
119
|
+
# * <tt>:touch</tt> - Touch timestamp columns when updating.
|
120
|
+
# Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
|
121
|
+
# touch that column or an array of symbols to touch just those ones.
|
98
122
|
#
|
99
123
|
# ==== Examples
|
100
124
|
#
|
101
|
-
# # Increment the
|
102
|
-
# DiscussionBoard.increment_counter(:
|
103
|
-
|
104
|
-
|
125
|
+
# # Increment the posts_count column for the record with an id of 5
|
126
|
+
# DiscussionBoard.increment_counter(:posts_count, 5)
|
127
|
+
#
|
128
|
+
# # Increment the posts_count column for the record with an id of 5
|
129
|
+
# # and update the updated_at value.
|
130
|
+
# DiscussionBoard.increment_counter(:posts_count, 5, touch: true)
|
131
|
+
def increment_counter(counter_name, id, touch: nil)
|
132
|
+
update_counters(id, counter_name => 1, touch: touch)
|
105
133
|
end
|
106
134
|
|
107
135
|
# Decrement a numeric field by one, via a direct SQL update.
|
108
136
|
#
|
109
|
-
# This works the same as increment_counter but reduces the column value by
|
137
|
+
# This works the same as #increment_counter but reduces the column value by
|
110
138
|
# 1 instead of increasing it.
|
111
139
|
#
|
112
140
|
# ==== Parameters
|
113
141
|
#
|
114
142
|
# * +counter_name+ - The name of the field that should be decremented.
|
115
|
-
# * +id+ - The id of the object that should be decremented or an
|
143
|
+
# * +id+ - The id of the object that should be decremented or an array of ids.
|
144
|
+
# * <tt>:touch</tt> - Touch timestamp columns when updating.
|
145
|
+
# Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
|
146
|
+
# touch that column or an array of symbols to touch just those ones.
|
116
147
|
#
|
117
148
|
# ==== Examples
|
118
149
|
#
|
119
|
-
# # Decrement the
|
120
|
-
# DiscussionBoard.decrement_counter(:
|
121
|
-
|
122
|
-
|
150
|
+
# # Decrement the posts_count column for the record with an id of 5
|
151
|
+
# DiscussionBoard.decrement_counter(:posts_count, 5)
|
152
|
+
#
|
153
|
+
# # Decrement the posts_count column for the record with an id of 5
|
154
|
+
# # and update the updated_at value.
|
155
|
+
# DiscussionBoard.decrement_counter(:posts_count, 5, touch: true)
|
156
|
+
def decrement_counter(counter_name, id, touch: nil)
|
157
|
+
update_counters(id, counter_name => -1, touch: touch)
|
123
158
|
end
|
124
159
|
end
|
125
160
|
|
126
|
-
protected
|
127
|
-
|
128
|
-
def actually_destroyed?
|
129
|
-
@_actually_destroyed
|
130
|
-
end
|
131
|
-
|
132
|
-
def clear_destroy_state
|
133
|
-
@_actually_destroyed = nil
|
134
|
-
end
|
135
|
-
|
136
161
|
private
|
137
|
-
|
138
|
-
def _create_record(*)
|
162
|
+
def _create_record(attribute_names = self.attribute_names)
|
139
163
|
id = super
|
140
164
|
|
141
165
|
each_counter_cached_associations do |association|
|
142
|
-
|
143
|
-
association.increment_counters
|
144
|
-
@_after_create_counter_called = true
|
145
|
-
end
|
166
|
+
association.increment_counters
|
146
167
|
end
|
147
168
|
|
148
169
|
id
|
@@ -155,9 +176,7 @@ module ActiveRecord
|
|
155
176
|
each_counter_cached_associations do |association|
|
156
177
|
foreign_key = association.reflection.foreign_key.to_sym
|
157
178
|
unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == foreign_key
|
158
|
-
|
159
|
-
association.decrement_counters
|
160
|
-
end
|
179
|
+
association.decrement_counters
|
161
180
|
end
|
162
181
|
end
|
163
182
|
end
|
@@ -170,6 +189,5 @@ module ActiveRecord
|
|
170
189
|
yield association(name.to_sym) if reflection.belongs_to? && reflection.counter_cache_column
|
171
190
|
end
|
172
191
|
end
|
173
|
-
|
174
192
|
end
|
175
193
|
end
|
@@ -0,0 +1,233 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/database_configurations/database_config"
|
4
|
+
require "active_record/database_configurations/hash_config"
|
5
|
+
require "active_record/database_configurations/url_config"
|
6
|
+
|
7
|
+
module ActiveRecord
|
8
|
+
# ActiveRecord::DatabaseConfigurations returns an array of DatabaseConfig
|
9
|
+
# objects (either a HashConfig or UrlConfig) that are constructed from the
|
10
|
+
# application's database configuration hash or URL string.
|
11
|
+
class DatabaseConfigurations
|
12
|
+
class InvalidConfigurationError < StandardError; end
|
13
|
+
|
14
|
+
attr_reader :configurations
|
15
|
+
delegate :any?, to: :configurations
|
16
|
+
|
17
|
+
def initialize(configurations = {})
|
18
|
+
@configurations = build_configs(configurations)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Collects the configs for the environment and optionally the specification
|
22
|
+
# name passed in. To include replica configurations pass <tt>include_replicas: true</tt>.
|
23
|
+
#
|
24
|
+
# If a spec name is provided a single DatabaseConfig object will be
|
25
|
+
# returned, otherwise an array of DatabaseConfig objects will be
|
26
|
+
# returned that corresponds with the environment and type requested.
|
27
|
+
#
|
28
|
+
# ==== Options
|
29
|
+
#
|
30
|
+
# * <tt>env_name:</tt> The environment name. Defaults to +nil+ which will collect
|
31
|
+
# configs for all environments.
|
32
|
+
# * <tt>spec_name:</tt> The specification name (i.e. primary, animals, etc.). Defaults
|
33
|
+
# to +nil+.
|
34
|
+
# * <tt>include_replicas:</tt> Determines whether to include replicas in
|
35
|
+
# the returned list. Most of the time we're only iterating over the write
|
36
|
+
# connection (i.e. migrations don't need to run for the write and read connection).
|
37
|
+
# Defaults to +false+.
|
38
|
+
def configs_for(env_name: nil, spec_name: nil, include_replicas: false)
|
39
|
+
configs = env_with_configs(env_name)
|
40
|
+
|
41
|
+
unless include_replicas
|
42
|
+
configs = configs.select do |db_config|
|
43
|
+
!db_config.replica?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if spec_name
|
48
|
+
configs.find do |db_config|
|
49
|
+
db_config.spec_name == spec_name
|
50
|
+
end
|
51
|
+
else
|
52
|
+
configs
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the config hash that corresponds with the environment
|
57
|
+
#
|
58
|
+
# If the application has multiple databases +default_hash+ will
|
59
|
+
# return the first config hash for the environment.
|
60
|
+
#
|
61
|
+
# { database: "my_db", adapter: "mysql2" }
|
62
|
+
def default_hash(env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_s)
|
63
|
+
default = find_db_config(env)
|
64
|
+
default.config if default
|
65
|
+
end
|
66
|
+
alias :[] :default_hash
|
67
|
+
|
68
|
+
# Returns a single DatabaseConfig object based on the requested environment.
|
69
|
+
#
|
70
|
+
# If the application has multiple databases +find_db_config+ will return
|
71
|
+
# the first DatabaseConfig for the environment.
|
72
|
+
def find_db_config(env)
|
73
|
+
configurations.find do |db_config|
|
74
|
+
db_config.env_name == env.to_s ||
|
75
|
+
(db_config.for_current_env? && db_config.spec_name == env.to_s)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns the DatabaseConfigurations object as a Hash.
|
80
|
+
def to_h
|
81
|
+
configs = configurations.reverse.inject({}) do |memo, db_config|
|
82
|
+
memo.merge(db_config.to_legacy_hash)
|
83
|
+
end
|
84
|
+
|
85
|
+
Hash[configs.to_a.reverse]
|
86
|
+
end
|
87
|
+
|
88
|
+
# Checks if the application's configurations are empty.
|
89
|
+
#
|
90
|
+
# Aliased to blank?
|
91
|
+
def empty?
|
92
|
+
configurations.empty?
|
93
|
+
end
|
94
|
+
alias :blank? :empty?
|
95
|
+
|
96
|
+
def each
|
97
|
+
throw_getter_deprecation(:each)
|
98
|
+
configurations.each { |config|
|
99
|
+
yield [config.env_name, config.config]
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def first
|
104
|
+
throw_getter_deprecation(:first)
|
105
|
+
config = configurations.first
|
106
|
+
[config.env_name, config.config]
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
def env_with_configs(env = nil)
|
111
|
+
if env
|
112
|
+
configurations.select { |db_config| db_config.env_name == env }
|
113
|
+
else
|
114
|
+
configurations
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def build_configs(configs)
|
119
|
+
return configs.configurations if configs.is_a?(DatabaseConfigurations)
|
120
|
+
return configs if configs.is_a?(Array)
|
121
|
+
|
122
|
+
db_configs = configs.flat_map do |env_name, config|
|
123
|
+
if config.is_a?(Hash) && config.all? { |_, v| v.is_a?(Hash) }
|
124
|
+
walk_configs(env_name.to_s, config)
|
125
|
+
else
|
126
|
+
build_db_config_from_raw_config(env_name.to_s, "primary", config)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_s
|
131
|
+
|
132
|
+
unless db_configs.find(&:for_current_env?)
|
133
|
+
db_configs << environment_url_config(current_env, "primary", {})
|
134
|
+
end
|
135
|
+
|
136
|
+
merge_db_environment_variables(current_env, db_configs.compact)
|
137
|
+
end
|
138
|
+
|
139
|
+
def walk_configs(env_name, config)
|
140
|
+
config.map do |spec_name, sub_config|
|
141
|
+
build_db_config_from_raw_config(env_name, spec_name.to_s, sub_config)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def build_db_config_from_raw_config(env_name, spec_name, config)
|
146
|
+
case config
|
147
|
+
when String
|
148
|
+
build_db_config_from_string(env_name, spec_name, config)
|
149
|
+
when Hash
|
150
|
+
build_db_config_from_hash(env_name, spec_name, config.stringify_keys)
|
151
|
+
else
|
152
|
+
raise InvalidConfigurationError, "'{ #{env_name} => #{config} }' is not a valid configuration. Expected '#{config}' to be a URL string or a Hash."
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def build_db_config_from_string(env_name, spec_name, config)
|
157
|
+
url = config
|
158
|
+
uri = URI.parse(url)
|
159
|
+
if uri.scheme
|
160
|
+
ActiveRecord::DatabaseConfigurations::UrlConfig.new(env_name, spec_name, url)
|
161
|
+
else
|
162
|
+
raise InvalidConfigurationError, "'{ #{env_name} => #{config} }' is not a valid configuration. Expected '#{config}' to be a URL string or a Hash."
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def build_db_config_from_hash(env_name, spec_name, config)
|
167
|
+
if config.has_key?("url")
|
168
|
+
url = config["url"]
|
169
|
+
config_without_url = config.dup
|
170
|
+
config_without_url.delete "url"
|
171
|
+
|
172
|
+
ActiveRecord::DatabaseConfigurations::UrlConfig.new(env_name, spec_name, url, config_without_url)
|
173
|
+
else
|
174
|
+
ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, spec_name, config)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def merge_db_environment_variables(current_env, configs)
|
179
|
+
configs.map do |config|
|
180
|
+
next config if config.url_config? || config.env_name != current_env
|
181
|
+
|
182
|
+
url_config = environment_url_config(current_env, config.spec_name, config.config)
|
183
|
+
url_config || config
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def environment_url_config(env, spec_name, config)
|
188
|
+
url = environment_value_for(spec_name)
|
189
|
+
return unless url
|
190
|
+
|
191
|
+
ActiveRecord::DatabaseConfigurations::UrlConfig.new(env, spec_name, url, config)
|
192
|
+
end
|
193
|
+
|
194
|
+
def environment_value_for(spec_name)
|
195
|
+
spec_env_key = "#{spec_name.upcase}_DATABASE_URL"
|
196
|
+
url = ENV[spec_env_key]
|
197
|
+
url ||= ENV["DATABASE_URL"] if spec_name == "primary"
|
198
|
+
url
|
199
|
+
end
|
200
|
+
|
201
|
+
def method_missing(method, *args, &blk)
|
202
|
+
case method
|
203
|
+
when :fetch
|
204
|
+
throw_getter_deprecation(method)
|
205
|
+
configs_for(env_name: args.first)
|
206
|
+
when :values
|
207
|
+
throw_getter_deprecation(method)
|
208
|
+
configurations.map(&:config)
|
209
|
+
when :[]=
|
210
|
+
throw_setter_deprecation(method)
|
211
|
+
|
212
|
+
env_name = args[0]
|
213
|
+
config = args[1]
|
214
|
+
|
215
|
+
remaining_configs = configurations.reject { |db_config| db_config.env_name == env_name }
|
216
|
+
new_config = build_configs(env_name => config)
|
217
|
+
new_configs = remaining_configs + new_config
|
218
|
+
|
219
|
+
ActiveRecord::Base.configurations = new_configs
|
220
|
+
else
|
221
|
+
raise NotImplementedError, "`ActiveRecord::Base.configurations` in Rails 6 now returns an object instead of a hash. The `#{method}` method is not supported. Please use `configs_for` or consult the documentation for supported methods."
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def throw_setter_deprecation(method)
|
226
|
+
ActiveSupport::Deprecation.warn("Setting `ActiveRecord::Base.configurations` with `#{method}` is deprecated. Use `ActiveRecord::Base.configurations=` directly to set the configurations instead.")
|
227
|
+
end
|
228
|
+
|
229
|
+
def throw_getter_deprecation(method)
|
230
|
+
ActiveSupport::Deprecation.warn("`ActiveRecord::Base.configurations` no longer returns a hash. Methods that act on the hash like `#{method}` are deprecated and will be removed in Rails 6.1. Use the `configs_for` method to collect and iterate over the database configurations.")
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class DatabaseConfigurations
|
5
|
+
# ActiveRecord::Base.configurations will return either a HashConfig or
|
6
|
+
# UrlConfig respectively. It will never return a DatabaseConfig object,
|
7
|
+
# as this is the parent class for the types of database configuration objects.
|
8
|
+
class DatabaseConfig # :nodoc:
|
9
|
+
attr_reader :env_name, :spec_name
|
10
|
+
|
11
|
+
def initialize(env_name, spec_name)
|
12
|
+
@env_name = env_name
|
13
|
+
@spec_name = spec_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def replica?
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
def migrations_paths
|
21
|
+
raise NotImplementedError
|
22
|
+
end
|
23
|
+
|
24
|
+
def url_config?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_legacy_hash
|
29
|
+
{ env_name => config }
|
30
|
+
end
|
31
|
+
|
32
|
+
def for_current_env?
|
33
|
+
env_name == ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|