activerecord 4.2.8 → 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 +5 -5
- data/CHANGELOG.md +612 -1583
- 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 +134 -286
- 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 -88
- 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 -244
- 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 -627
- 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 -188
- 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 +5 -3
- 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 +626 -283
- 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 +314 -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 +147 -46
- 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 +330 -197
- 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 +308 -99
- 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 -60
- 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 -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/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 -58
- 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
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
# ActiveRecord::Suppressor prevents the receiver from being saved during
|
5
|
+
# a given block.
|
6
|
+
#
|
7
|
+
# For example, here's a pattern of creating notifications when new comments
|
8
|
+
# are posted. (The notification may in turn trigger an email, a push
|
9
|
+
# notification, or just appear in the UI somewhere):
|
10
|
+
#
|
11
|
+
# class Comment < ActiveRecord::Base
|
12
|
+
# belongs_to :commentable, polymorphic: true
|
13
|
+
# after_create -> { Notification.create! comment: self,
|
14
|
+
# recipients: commentable.recipients }
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# That's what you want the bulk of the time. New comment creates a new
|
18
|
+
# Notification. But there may well be off cases, like copying a commentable
|
19
|
+
# and its comments, where you don't want that. So you'd have a concern
|
20
|
+
# something like this:
|
21
|
+
#
|
22
|
+
# module Copyable
|
23
|
+
# def copy_to(destination)
|
24
|
+
# Notification.suppress do
|
25
|
+
# # Copy logic that creates new comments that we do not want
|
26
|
+
# # triggering notifications.
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
module Suppressor
|
31
|
+
extend ActiveSupport::Concern
|
32
|
+
|
33
|
+
module ClassMethods
|
34
|
+
def suppress(&block)
|
35
|
+
previous_state = SuppressorRegistry.suppressed[name]
|
36
|
+
SuppressorRegistry.suppressed[name] = true
|
37
|
+
yield
|
38
|
+
ensure
|
39
|
+
SuppressorRegistry.suppressed[name] = previous_state
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def save(*) # :nodoc:
|
44
|
+
SuppressorRegistry.suppressed[self.class.name] ? true : super
|
45
|
+
end
|
46
|
+
|
47
|
+
def save!(*) # :nodoc:
|
48
|
+
SuppressorRegistry.suppressed[self.class.name] ? true : super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class SuppressorRegistry # :nodoc:
|
53
|
+
extend ActiveSupport::PerThreadRegistry
|
54
|
+
|
55
|
+
attr_reader :suppressed
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@suppressed = {}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class TableMetadata # :nodoc:
|
5
|
+
delegate :foreign_type, :foreign_key, :join_primary_key, :join_foreign_key, to: :association, prefix: true
|
6
|
+
|
7
|
+
def initialize(klass, arel_table, association = nil, types = klass)
|
8
|
+
@klass = klass
|
9
|
+
@types = types
|
10
|
+
@arel_table = arel_table
|
11
|
+
@association = association
|
12
|
+
end
|
13
|
+
|
14
|
+
def resolve_column_aliases(hash)
|
15
|
+
new_hash = hash.dup
|
16
|
+
hash.each_key do |key|
|
17
|
+
if key.is_a?(Symbol) && new_key = klass.attribute_aliases[key.to_s]
|
18
|
+
new_hash[new_key] = new_hash.delete(key)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
new_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def arel_attribute(column_name)
|
25
|
+
if klass
|
26
|
+
klass.arel_attribute(column_name, arel_table)
|
27
|
+
else
|
28
|
+
arel_table[column_name]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def type(column_name)
|
33
|
+
types.type_for_attribute(column_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def has_column?(column_name)
|
37
|
+
klass && klass.columns_hash.key?(column_name.to_s)
|
38
|
+
end
|
39
|
+
|
40
|
+
def associated_with?(association_name)
|
41
|
+
klass && klass._reflect_on_association(association_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def associated_table(table_name)
|
45
|
+
association = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.to_s.singularize)
|
46
|
+
|
47
|
+
if !association && table_name == arel_table.name
|
48
|
+
return self
|
49
|
+
elsif association && !association.polymorphic?
|
50
|
+
association_klass = association.klass
|
51
|
+
arel_table = association_klass.arel_table.alias(table_name)
|
52
|
+
TableMetadata.new(association_klass, arel_table, association)
|
53
|
+
else
|
54
|
+
type_caster = TypeCaster::Connection.new(klass, table_name)
|
55
|
+
arel_table = Arel::Table.new(table_name, type_caster: type_caster)
|
56
|
+
TableMetadata.new(nil, arel_table, association, type_caster)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def polymorphic_association?
|
61
|
+
association && association.polymorphic?
|
62
|
+
end
|
63
|
+
|
64
|
+
def aggregated_with?(aggregation_name)
|
65
|
+
klass && reflect_on_aggregation(aggregation_name)
|
66
|
+
end
|
67
|
+
|
68
|
+
def reflect_on_aggregation(aggregation_name)
|
69
|
+
klass.reflect_on_aggregation(aggregation_name)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
attr_reader :klass, :types, :arel_table, :association
|
74
|
+
end
|
75
|
+
end
|
@@ -1,14 +1,16 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/database_configurations"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Tasks # :nodoc:
|
5
7
|
class DatabaseAlreadyExists < StandardError; end # :nodoc:
|
6
8
|
class DatabaseNotSupported < StandardError; end # :nodoc:
|
7
9
|
|
8
|
-
#
|
10
|
+
# ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
|
9
11
|
# logic behind common tasks used to manage database and migrations.
|
10
12
|
#
|
11
|
-
# The tasks defined here are used with
|
13
|
+
# The tasks defined here are used with Rails commands provided by Active Record.
|
12
14
|
#
|
13
15
|
# In order to use DatabaseTasks, a few config values need to be set. All the needed
|
14
16
|
# config values are set by Rails already, so it's necessary to do it only if you
|
@@ -18,15 +20,15 @@ module ActiveRecord
|
|
18
20
|
#
|
19
21
|
# The possible config values are:
|
20
22
|
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
23
|
+
# * +env+: current environment (like Rails.env).
|
24
|
+
# * +database_configuration+: configuration of your databases (as in +config/database.yml+).
|
25
|
+
# * +db_dir+: your +db+ directory.
|
26
|
+
# * +fixtures_path+: a path to fixtures directory.
|
27
|
+
# * +migrations_paths+: a list of paths to directories with migrations.
|
28
|
+
# * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.
|
29
|
+
# * +root+: a path to the root of the application.
|
28
30
|
#
|
29
|
-
# Example usage of
|
31
|
+
# Example usage of DatabaseTasks outside Rails could look as such:
|
30
32
|
#
|
31
33
|
# include ActiveRecord::Tasks
|
32
34
|
# DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
|
@@ -35,36 +37,62 @@ module ActiveRecord
|
|
35
37
|
#
|
36
38
|
# DatabaseTasks.create_current('production')
|
37
39
|
module DatabaseTasks
|
40
|
+
##
|
41
|
+
# :singleton-method:
|
42
|
+
# Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:structure:dump
|
43
|
+
mattr_accessor :structure_dump_flags, instance_accessor: false
|
44
|
+
|
45
|
+
##
|
46
|
+
# :singleton-method:
|
47
|
+
# Extra flags passed to database CLI tool when calling db:structure:load
|
48
|
+
mattr_accessor :structure_load_flags, instance_accessor: false
|
49
|
+
|
38
50
|
extend self
|
39
51
|
|
40
52
|
attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
|
41
53
|
attr_accessor :database_configuration
|
42
54
|
|
43
|
-
LOCAL_HOSTS
|
55
|
+
LOCAL_HOSTS = ["127.0.0.1", "localhost"]
|
56
|
+
|
57
|
+
def check_protected_environments!
|
58
|
+
unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
|
59
|
+
current = ActiveRecord::Base.connection.migration_context.current_environment
|
60
|
+
stored = ActiveRecord::Base.connection.migration_context.last_stored_environment
|
61
|
+
|
62
|
+
if ActiveRecord::Base.connection.migration_context.protected_environment?
|
63
|
+
raise ActiveRecord::ProtectedEnvironmentError.new(stored)
|
64
|
+
end
|
65
|
+
|
66
|
+
if stored && stored != current
|
67
|
+
raise ActiveRecord::EnvironmentMismatchError.new(current: current, stored: stored)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
rescue ActiveRecord::NoDatabaseError
|
71
|
+
end
|
44
72
|
|
45
73
|
def register_task(pattern, task)
|
46
74
|
@tasks ||= {}
|
47
75
|
@tasks[pattern] = task
|
48
76
|
end
|
49
77
|
|
50
|
-
register_task(/mysql/, ActiveRecord::Tasks::MySQLDatabaseTasks)
|
51
|
-
register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks)
|
52
|
-
register_task(/sqlite/, ActiveRecord::Tasks::SQLiteDatabaseTasks)
|
78
|
+
register_task(/mysql/, "ActiveRecord::Tasks::MySQLDatabaseTasks")
|
79
|
+
register_task(/postgresql/, "ActiveRecord::Tasks::PostgreSQLDatabaseTasks")
|
80
|
+
register_task(/sqlite/, "ActiveRecord::Tasks::SQLiteDatabaseTasks")
|
53
81
|
|
54
82
|
def db_dir
|
55
83
|
@db_dir ||= Rails.application.config.paths["db"].first
|
56
84
|
end
|
57
85
|
|
58
86
|
def migrations_paths
|
59
|
-
@migrations_paths ||= Rails.application.paths[
|
87
|
+
@migrations_paths ||= Rails.application.paths["db/migrate"].to_a
|
60
88
|
end
|
61
89
|
|
62
90
|
def fixtures_path
|
63
|
-
@fixtures_path ||= if ENV[
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
91
|
+
@fixtures_path ||= if ENV["FIXTURES_PATH"]
|
92
|
+
File.join(root, ENV["FIXTURES_PATH"])
|
93
|
+
else
|
94
|
+
File.join(root, "test", "fixtures")
|
95
|
+
end
|
68
96
|
end
|
69
97
|
|
70
98
|
def root
|
@@ -75,35 +103,85 @@ module ActiveRecord
|
|
75
103
|
@env ||= Rails.env
|
76
104
|
end
|
77
105
|
|
106
|
+
def spec
|
107
|
+
@spec ||= "primary"
|
108
|
+
end
|
109
|
+
|
78
110
|
def seed_loader
|
79
111
|
@seed_loader ||= Rails.application
|
80
112
|
end
|
81
113
|
|
82
114
|
def current_config(options = {})
|
83
|
-
options.reverse_merge! :
|
115
|
+
options.reverse_merge! env: env
|
116
|
+
options[:spec] ||= "primary"
|
84
117
|
if options.has_key?(:config)
|
85
118
|
@current_config = options[:config]
|
86
119
|
else
|
87
|
-
@current_config ||= ActiveRecord::Base.configurations
|
120
|
+
@current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: options[:env], spec_name: options[:spec]).config
|
88
121
|
end
|
89
122
|
end
|
90
123
|
|
91
124
|
def create(*arguments)
|
92
125
|
configuration = arguments.first
|
93
|
-
class_for_adapter(configuration[
|
126
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).create
|
127
|
+
$stdout.puts "Created database '#{configuration['database']}'" if verbose?
|
94
128
|
rescue DatabaseAlreadyExists
|
95
|
-
$stderr.puts "#{configuration['database']} already exists"
|
129
|
+
$stderr.puts "Database '#{configuration['database']}' already exists" if verbose?
|
96
130
|
rescue Exception => error
|
97
|
-
$stderr.puts error
|
98
|
-
$stderr.puts "Couldn't create database
|
131
|
+
$stderr.puts error
|
132
|
+
$stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
|
133
|
+
raise
|
99
134
|
end
|
100
135
|
|
101
136
|
def create_all
|
137
|
+
old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
|
102
138
|
each_local_configuration { |configuration| create configuration }
|
139
|
+
if old_pool
|
140
|
+
ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
|
141
|
+
end
|
103
142
|
end
|
104
143
|
|
105
|
-
def
|
106
|
-
|
144
|
+
def setup_initial_database_yaml
|
145
|
+
return {} unless defined?(Rails)
|
146
|
+
|
147
|
+
begin
|
148
|
+
Rails.application.config.load_database_yaml
|
149
|
+
rescue
|
150
|
+
$stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
|
151
|
+
|
152
|
+
{}
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def for_each(databases)
|
157
|
+
return {} unless defined?(Rails)
|
158
|
+
|
159
|
+
database_configs = ActiveRecord::DatabaseConfigurations.new(databases).configs_for(env_name: Rails.env)
|
160
|
+
|
161
|
+
# if this is a single database application we don't want tasks for each primary database
|
162
|
+
return if database_configs.count == 1
|
163
|
+
|
164
|
+
database_configs.each do |db_config|
|
165
|
+
yield db_config.spec_name
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def raise_for_multi_db(environment = env, command:)
|
170
|
+
db_configs = ActiveRecord::Base.configurations.configs_for(env_name: environment)
|
171
|
+
|
172
|
+
if db_configs.count > 1
|
173
|
+
dbs_list = []
|
174
|
+
|
175
|
+
db_configs.each do |db|
|
176
|
+
dbs_list << "#{command}:#{db.spec_name}"
|
177
|
+
end
|
178
|
+
|
179
|
+
raise "You're using a multiple database application. To use `#{command}` you must run the namespaced task with a VERSION. Available tasks are #{dbs_list.to_sentence}."
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def create_current(environment = env, spec_name = nil)
|
184
|
+
each_current_configuration(environment, spec_name) { |configuration|
|
107
185
|
create configuration
|
108
186
|
}
|
109
187
|
ActiveRecord::Base.establish_connection(environment.to_sym)
|
@@ -111,12 +189,14 @@ module ActiveRecord
|
|
111
189
|
|
112
190
|
def drop(*arguments)
|
113
191
|
configuration = arguments.first
|
114
|
-
class_for_adapter(configuration[
|
192
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).drop
|
193
|
+
$stdout.puts "Dropped database '#{configuration['database']}'" if verbose?
|
115
194
|
rescue ActiveRecord::NoDatabaseError
|
116
195
|
$stderr.puts "Database '#{configuration['database']}' does not exist"
|
117
196
|
rescue Exception => error
|
118
|
-
$stderr.puts error
|
119
|
-
$stderr.puts "Couldn't drop #{configuration['database']}"
|
197
|
+
$stderr.puts error
|
198
|
+
$stderr.puts "Couldn't drop database '#{configuration['database']}'"
|
199
|
+
raise
|
120
200
|
end
|
121
201
|
|
122
202
|
def drop_all
|
@@ -129,39 +209,86 @@ module ActiveRecord
|
|
129
209
|
}
|
130
210
|
end
|
131
211
|
|
212
|
+
def truncate_tables(configuration)
|
213
|
+
ActiveRecord::Base.connected_to(database: { truncation: configuration }) do
|
214
|
+
conn = ActiveRecord::Base.connection
|
215
|
+
table_names = conn.tables
|
216
|
+
table_names -= [
|
217
|
+
conn.schema_migration.table_name,
|
218
|
+
InternalMetadata.table_name
|
219
|
+
]
|
220
|
+
|
221
|
+
ActiveRecord::Base.connection.truncate_tables(*table_names)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
private :truncate_tables
|
225
|
+
|
226
|
+
def truncate_all(environment = env)
|
227
|
+
ActiveRecord::Base.configurations.configs_for(env_name: environment).each do |db_config|
|
228
|
+
truncate_tables db_config.config
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
132
232
|
def migrate
|
133
|
-
|
134
|
-
|
135
|
-
scope
|
136
|
-
verbose_was, Migration.verbose = Migration.verbose, verbose
|
137
|
-
|
233
|
+
check_target_version
|
234
|
+
|
235
|
+
scope = ENV["SCOPE"]
|
236
|
+
verbose_was, Migration.verbose = Migration.verbose, verbose?
|
237
|
+
|
238
|
+
Base.connection.migration_context.migrate(target_version) do |migration|
|
138
239
|
scope.blank? || scope == migration.scope
|
139
240
|
end
|
241
|
+
|
140
242
|
ActiveRecord::Base.clear_cache!
|
141
243
|
ensure
|
142
244
|
Migration.verbose = verbose_was
|
143
245
|
end
|
144
246
|
|
145
|
-
def
|
146
|
-
|
247
|
+
def migrate_status
|
248
|
+
unless ActiveRecord::Base.connection.schema_migration.table_exists?
|
249
|
+
Kernel.abort "Schema migrations table does not exist yet."
|
250
|
+
end
|
251
|
+
|
252
|
+
# output
|
253
|
+
puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
|
254
|
+
puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
|
255
|
+
puts "-" * 50
|
256
|
+
ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
|
257
|
+
puts "#{status.center(8)} #{version.ljust(14)} #{name}"
|
258
|
+
end
|
259
|
+
puts
|
260
|
+
end
|
261
|
+
|
262
|
+
def check_target_version
|
263
|
+
if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"]))
|
264
|
+
raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def target_version
|
269
|
+
ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
|
270
|
+
end
|
271
|
+
|
272
|
+
def charset_current(environment = env, specification_name = spec)
|
273
|
+
charset ActiveRecord::Base.configurations.configs_for(env_name: environment, spec_name: specification_name).config
|
147
274
|
end
|
148
275
|
|
149
276
|
def charset(*arguments)
|
150
277
|
configuration = arguments.first
|
151
|
-
class_for_adapter(configuration[
|
278
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).charset
|
152
279
|
end
|
153
280
|
|
154
|
-
def collation_current(environment = env)
|
155
|
-
collation ActiveRecord::Base.configurations
|
281
|
+
def collation_current(environment = env, specification_name = spec)
|
282
|
+
collation ActiveRecord::Base.configurations.configs_for(env_name: environment, spec_name: specification_name).config
|
156
283
|
end
|
157
284
|
|
158
285
|
def collation(*arguments)
|
159
286
|
configuration = arguments.first
|
160
|
-
class_for_adapter(configuration[
|
287
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).collation
|
161
288
|
end
|
162
289
|
|
163
290
|
def purge(configuration)
|
164
|
-
class_for_adapter(configuration[
|
291
|
+
class_for_adapter(configuration["adapter"]).new(configuration).purge
|
165
292
|
end
|
166
293
|
|
167
294
|
def purge_all
|
@@ -180,68 +307,130 @@ module ActiveRecord
|
|
180
307
|
def structure_dump(*arguments)
|
181
308
|
configuration = arguments.first
|
182
309
|
filename = arguments.delete_at 1
|
183
|
-
class_for_adapter(configuration[
|
310
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
|
184
311
|
end
|
185
312
|
|
186
313
|
def structure_load(*arguments)
|
187
314
|
configuration = arguments.first
|
188
315
|
filename = arguments.delete_at 1
|
189
|
-
class_for_adapter(configuration[
|
316
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
|
190
317
|
end
|
191
318
|
|
192
|
-
def load_schema(format = ActiveRecord::Base.schema_format, file = nil)
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
319
|
+
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary") # :nodoc:
|
320
|
+
file ||= dump_filename(spec_name, format)
|
321
|
+
|
322
|
+
verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
|
323
|
+
check_schema_file(file)
|
324
|
+
ActiveRecord::Base.establish_connection(configuration)
|
197
325
|
|
198
|
-
|
326
|
+
case format
|
327
|
+
when :ruby
|
328
|
+
load(file)
|
329
|
+
when :sql
|
330
|
+
structure_load(configuration, file)
|
331
|
+
else
|
332
|
+
raise ArgumentError, "unknown format #{format.inspect}"
|
333
|
+
end
|
334
|
+
ActiveRecord::InternalMetadata.create_table
|
335
|
+
ActiveRecord::InternalMetadata[:environment] = environment
|
336
|
+
ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
|
337
|
+
ensure
|
338
|
+
Migration.verbose = verbose_was
|
199
339
|
end
|
200
340
|
|
201
|
-
def
|
341
|
+
def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary")
|
342
|
+
file ||= dump_filename(spec_name, format)
|
343
|
+
|
344
|
+
return true unless File.exist?(file)
|
345
|
+
|
346
|
+
ActiveRecord::Base.establish_connection(configuration)
|
347
|
+
return false unless ActiveRecord::InternalMetadata.table_exists?
|
348
|
+
ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
|
349
|
+
end
|
350
|
+
|
351
|
+
def reconstruct_from_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary") # :nodoc:
|
352
|
+
file ||= dump_filename(spec_name, format)
|
353
|
+
|
354
|
+
check_schema_file(file)
|
355
|
+
|
356
|
+
ActiveRecord::Base.establish_connection(configuration)
|
357
|
+
|
358
|
+
if schema_up_to_date?(configuration, format, file, environment, spec_name)
|
359
|
+
truncate_tables(configuration)
|
360
|
+
else
|
361
|
+
purge(configuration)
|
362
|
+
load_schema(configuration, format, file, environment, spec_name)
|
363
|
+
end
|
364
|
+
rescue ActiveRecord::NoDatabaseError
|
365
|
+
create(configuration)
|
366
|
+
load_schema(configuration, format, file, environment, spec_name)
|
367
|
+
end
|
368
|
+
|
369
|
+
def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc:
|
370
|
+
require "active_record/schema_dumper"
|
371
|
+
filename = dump_filename(spec_name, format)
|
372
|
+
connection = ActiveRecord::Base.connection
|
373
|
+
|
202
374
|
case format
|
203
375
|
when :ruby
|
204
|
-
File.
|
376
|
+
File.open(filename, "w:utf-8") do |file|
|
377
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
378
|
+
end
|
205
379
|
when :sql
|
206
|
-
|
380
|
+
structure_dump(configuration, filename)
|
381
|
+
if connection.schema_migration.table_exists?
|
382
|
+
File.open(filename, "a") do |f|
|
383
|
+
f.puts connection.dump_schema_information
|
384
|
+
f.print "\n"
|
385
|
+
end
|
386
|
+
end
|
207
387
|
end
|
208
388
|
end
|
209
389
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
file ||= schema_file(format)
|
390
|
+
def schema_file(format = ActiveRecord::Base.schema_format)
|
391
|
+
File.join(db_dir, schema_file_type(format))
|
392
|
+
end
|
214
393
|
|
394
|
+
def schema_file_type(format = ActiveRecord::Base.schema_format)
|
215
395
|
case format
|
216
396
|
when :ruby
|
217
|
-
|
218
|
-
ActiveRecord::Base.establish_connection(configuration)
|
219
|
-
load(file)
|
397
|
+
"schema.rb"
|
220
398
|
when :sql
|
221
|
-
|
222
|
-
|
399
|
+
"structure.sql"
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
def dump_filename(namespace, format = ActiveRecord::Base.schema_format)
|
404
|
+
filename = if namespace == "primary"
|
405
|
+
schema_file_type(format)
|
223
406
|
else
|
224
|
-
|
407
|
+
"#{namespace}_#{schema_file_type(format)}"
|
225
408
|
end
|
409
|
+
|
410
|
+
ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
|
226
411
|
end
|
227
412
|
|
228
|
-
def
|
229
|
-
if
|
230
|
-
|
413
|
+
def cache_dump_filename(namespace)
|
414
|
+
filename = if namespace == "primary"
|
415
|
+
"schema_cache.yml"
|
416
|
+
else
|
417
|
+
"#{namespace}_schema_cache.yml"
|
231
418
|
end
|
419
|
+
|
420
|
+
ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
|
232
421
|
end
|
233
422
|
|
234
423
|
def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
|
235
|
-
each_current_configuration(environment) { |configuration|
|
236
|
-
|
424
|
+
each_current_configuration(environment) { |configuration, spec_name, env|
|
425
|
+
load_schema(configuration, format, file, env, spec_name)
|
237
426
|
}
|
238
427
|
ActiveRecord::Base.establish_connection(environment.to_sym)
|
239
428
|
end
|
240
429
|
|
241
430
|
def check_schema_file(filename)
|
242
431
|
unless File.exist?(filename)
|
243
|
-
message =
|
244
|
-
message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails)
|
432
|
+
message = +%{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
|
433
|
+
message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails.root)
|
245
434
|
Kernel.abort message
|
246
435
|
end
|
247
436
|
end
|
@@ -250,48 +439,68 @@ module ActiveRecord
|
|
250
439
|
if seed_loader
|
251
440
|
seed_loader.load_seed
|
252
441
|
else
|
253
|
-
raise "You tried to load seed data, but no seed loader is specified. Please specify seed "
|
254
|
-
"loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n"
|
442
|
+
raise "You tried to load seed data, but no seed loader is specified. Please specify seed " \
|
443
|
+
"loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" \
|
255
444
|
"Seed loader should respond to load_seed method"
|
256
445
|
end
|
257
446
|
end
|
258
447
|
|
448
|
+
# Dumps the schema cache in YAML format for the connection into the file
|
449
|
+
#
|
450
|
+
# ==== Examples:
|
451
|
+
# ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
|
452
|
+
def dump_schema_cache(conn, filename)
|
453
|
+
conn.schema_cache.clear!
|
454
|
+
conn.data_sources.each { |table| conn.schema_cache.add(table) }
|
455
|
+
open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
|
456
|
+
end
|
457
|
+
|
259
458
|
private
|
459
|
+
def verbose?
|
460
|
+
ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
|
461
|
+
end
|
260
462
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
463
|
+
def class_for_adapter(adapter)
|
464
|
+
_key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
|
465
|
+
unless task
|
466
|
+
raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
|
467
|
+
end
|
468
|
+
task.is_a?(String) ? task.constantize : task
|
265
469
|
end
|
266
|
-
@tasks[key]
|
267
|
-
end
|
268
470
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
471
|
+
def each_current_configuration(environment, spec_name = nil)
|
472
|
+
environments = [environment]
|
473
|
+
environments << "test" if environment == "development"
|
474
|
+
|
475
|
+
environments.each do |env|
|
476
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
|
477
|
+
next if spec_name && spec_name != db_config.spec_name
|
273
478
|
|
274
|
-
|
275
|
-
|
276
|
-
|
479
|
+
yield db_config.config, db_config.spec_name, env
|
480
|
+
end
|
481
|
+
end
|
277
482
|
end
|
278
|
-
end
|
279
483
|
|
280
|
-
|
281
|
-
|
282
|
-
|
484
|
+
def each_local_configuration
|
485
|
+
ActiveRecord::Base.configurations.configs_for.each do |db_config|
|
486
|
+
configuration = db_config.config
|
487
|
+
next unless configuration["database"]
|
283
488
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
489
|
+
if local_database?(configuration)
|
490
|
+
yield configuration
|
491
|
+
else
|
492
|
+
$stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
|
493
|
+
end
|
288
494
|
end
|
289
495
|
end
|
290
|
-
end
|
291
496
|
|
292
|
-
|
293
|
-
|
294
|
-
|
497
|
+
def local_database?(configuration)
|
498
|
+
configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
|
499
|
+
end
|
500
|
+
|
501
|
+
def schema_sha1(file)
|
502
|
+
Digest::SHA1.hexdigest(File.read(file))
|
503
|
+
end
|
295
504
|
end
|
296
505
|
end
|
297
506
|
end
|