activerecord 4.2.0 → 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 -971
- 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/aggregations.rb +267 -248
- data/lib/active_record/association_relation.rb +24 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +135 -56
- data/lib/active_record/associations/association_scope.rb +103 -131
- data/lib/active_record/associations/belongs_to_association.rb +67 -54
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +27 -40
- data/lib/active_record/associations/builder/belongs_to.rb +69 -55
- data/lib/active_record/associations/builder/collection_association.rb +10 -29
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +60 -70
- data/lib/active_record/associations/builder/has_many.rb +8 -4
- data/lib/active_record/associations/builder/has_one.rb +46 -5
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +138 -274
- data/lib/active_record/associations/collection_proxy.rb +252 -151
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +35 -83
- data/lib/active_record/associations/has_many_through_association.rb +62 -80
- data/lib/active_record/associations/has_one_association.rb +62 -49
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -80
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/join_dependency.rb +138 -162
- data/lib/active_record/associations/preloader/association.rb +90 -119
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +92 -94
- data/lib/active_record/associations/singular_association.rb +18 -45
- data/lib/active_record/associations/through_association.rb +48 -23
- data/lib/active_record/associations.rb +1737 -1596
- data/lib/active_record/attribute_assignment.rb +56 -183
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +15 -5
- data/lib/active_record/attribute_methods/dirty.rb +174 -134
- 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 +62 -36
- data/lib/active_record/attribute_methods/write.rb +33 -55
- data/lib/active_record/attribute_methods.rb +124 -143
- data/lib/active_record/attributes.rb +214 -74
- data/lib/active_record/autosave_association.rb +115 -46
- data/lib/active_record/base.rb +60 -49
- 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 -290
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +247 -108
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +171 -53
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +366 -227
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +706 -222
- data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -87
- data/lib/active_record/connection_adapters/abstract_adapter.rb +468 -194
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +535 -597
- 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 +59 -195
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +65 -115
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +7 -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 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +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/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +474 -286
- 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 +558 -363
- data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +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 +288 -359
- 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 +266 -233
- data/lib/active_record/counter_cache.rb +68 -50
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +164 -88
- data/lib/active_record/errors.rb +189 -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 +11 -6
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +226 -495
- data/lib/active_record/gem_version.rb +4 -2
- 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 +48 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +91 -98
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +76 -33
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- 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/migration.rb +634 -288
- data/lib/active_record/model_schema.rb +314 -112
- data/lib/active_record/nested_attributes.rb +266 -214
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +559 -124
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +43 -29
- data/lib/active_record/railtie.rb +148 -47
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +338 -202
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +460 -299
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +207 -55
- data/lib/active_record/relation/calculations.rb +269 -248
- data/lib/active_record/relation/delegation.rb +70 -80
- data/lib/active_record/relation/finder_methods.rb +279 -255
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +83 -69
- data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -25
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +116 -92
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +574 -391
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -16
- 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/relation.rb +518 -340
- 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 -20
- data/lib/active_record/scoping/default.rb +101 -84
- data/lib/active_record/scoping/named.rb +86 -33
- data/lib/active_record/scoping.rb +45 -26
- 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 +309 -99
- data/lib/active_record/tasks/mysql_database_tasks.rb +58 -88
- data/lib/active_record/tasks/postgresql_database_tasks.rb +82 -31
- 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 +215 -139
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +129 -0
- data/lib/active_record/type/date.rb +4 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +13 -5
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +30 -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.rb +78 -23
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +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 +43 -46
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +43 -21
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +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/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/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +51 -0
- 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/migration_generator.rb +42 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -8
- data/lib/rails/generators/active_record/migration.rb +31 -1
- 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.rb +7 -5
- metadata +166 -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 -149
- data/lib/active_record/attribute_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/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 -30
- data/lib/active_record/type/decimal.rb +0 -40
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -55
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,7 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
3
5
|
IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN"]
|
4
6
|
|
7
|
+
class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
|
8
|
+
|
5
9
|
def self.runtime=(value)
|
6
10
|
ActiveRecord::RuntimeRegistry.sql_runtime = value
|
7
11
|
end
|
@@ -15,25 +19,6 @@ module ActiveRecord
|
|
15
19
|
rt
|
16
20
|
end
|
17
21
|
|
18
|
-
def initialize
|
19
|
-
super
|
20
|
-
@odd = false
|
21
|
-
end
|
22
|
-
|
23
|
-
def render_bind(column, value)
|
24
|
-
if column
|
25
|
-
if column.binary?
|
26
|
-
# This specifically deals with the PG adapter that casts bytea columns into a Hash.
|
27
|
-
value = value[:value] if value.is_a?(Hash)
|
28
|
-
value = value ? "<#{value.bytesize} bytes of binary data>" : "<NULL binary data>"
|
29
|
-
end
|
30
|
-
|
31
|
-
[column.name, value]
|
32
|
-
else
|
33
|
-
[nil, value]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
22
|
def sql(event)
|
38
23
|
self.class.runtime += event.duration
|
39
24
|
return unless logger.debug?
|
@@ -43,32 +28,90 @@ module ActiveRecord
|
|
43
28
|
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
44
29
|
|
45
30
|
name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
|
31
|
+
name = "CACHE #{name}" if payload[:cached]
|
46
32
|
sql = payload[:sql]
|
47
33
|
binds = nil
|
48
34
|
|
49
35
|
unless (payload[:binds] || []).empty?
|
50
|
-
|
51
|
-
|
36
|
+
casted_params = type_casted_binds(payload[:type_casted_binds])
|
37
|
+
binds = " " + payload[:binds].zip(casted_params).map { |attr, value|
|
38
|
+
render_bind(attr, value)
|
52
39
|
}.inspect
|
53
40
|
end
|
54
41
|
|
55
|
-
|
56
|
-
|
57
|
-
sql = color(sql, nil, true)
|
58
|
-
else
|
59
|
-
name = color(name, MAGENTA, true)
|
60
|
-
end
|
42
|
+
name = colorize_payload_name(name, payload[:name])
|
43
|
+
sql = color(sql, sql_color(sql), true)
|
61
44
|
|
62
45
|
debug " #{name} #{sql}#{binds}"
|
63
46
|
end
|
64
47
|
|
65
|
-
|
66
|
-
|
67
|
-
|
48
|
+
private
|
49
|
+
def type_casted_binds(casted_binds)
|
50
|
+
casted_binds.respond_to?(:call) ? casted_binds.call : casted_binds
|
51
|
+
end
|
68
52
|
|
69
|
-
|
70
|
-
|
71
|
-
|
53
|
+
def render_bind(attr, value)
|
54
|
+
if attr.is_a?(Array)
|
55
|
+
attr = attr.first
|
56
|
+
elsif attr.type.binary? && attr.value
|
57
|
+
value = "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
|
58
|
+
end
|
59
|
+
|
60
|
+
[attr && attr.name, value]
|
61
|
+
end
|
62
|
+
|
63
|
+
def colorize_payload_name(name, payload_name)
|
64
|
+
if payload_name.blank? || payload_name == "SQL" # SQL vs Model Load/Exists
|
65
|
+
color(name, MAGENTA, true)
|
66
|
+
else
|
67
|
+
color(name, CYAN, true)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def sql_color(sql)
|
72
|
+
case sql
|
73
|
+
when /\A\s*rollback/mi
|
74
|
+
RED
|
75
|
+
when /select .*for update/mi, /\A\s*lock/mi
|
76
|
+
WHITE
|
77
|
+
when /\A\s*select/i
|
78
|
+
BLUE
|
79
|
+
when /\A\s*insert/i
|
80
|
+
GREEN
|
81
|
+
when /\A\s*update/i
|
82
|
+
YELLOW
|
83
|
+
when /\A\s*delete/i
|
84
|
+
RED
|
85
|
+
when /transaction\s*\Z/i
|
86
|
+
CYAN
|
87
|
+
else
|
88
|
+
MAGENTA
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def logger
|
93
|
+
ActiveRecord::Base.logger
|
94
|
+
end
|
95
|
+
|
96
|
+
def debug(progname = nil, &block)
|
97
|
+
return unless super
|
98
|
+
|
99
|
+
if ActiveRecord::Base.verbose_query_logs
|
100
|
+
log_query_source
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def log_query_source
|
105
|
+
source = extract_query_source_location(caller)
|
106
|
+
|
107
|
+
if source
|
108
|
+
logger.debug(" ↳ #{source}")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def extract_query_source_location(locations)
|
113
|
+
backtrace_cleaner.clean(locations.lazy).first
|
114
|
+
end
|
72
115
|
end
|
73
116
|
end
|
74
117
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Middleware
|
5
|
+
class DatabaseSelector
|
6
|
+
class Resolver
|
7
|
+
# The session class is used by the DatabaseSelector::Resolver to save
|
8
|
+
# timestamps of the last write in the session.
|
9
|
+
#
|
10
|
+
# The last_write is used to determine whether it's safe to read
|
11
|
+
# from the replica or the request needs to be sent to the primary.
|
12
|
+
class Session # :nodoc:
|
13
|
+
def self.call(request)
|
14
|
+
new(request.session)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Converts time to a timestamp that represents milliseconds since
|
18
|
+
# epoch.
|
19
|
+
def self.convert_time_to_timestamp(time)
|
20
|
+
time.to_i * 1000 + time.usec / 1000
|
21
|
+
end
|
22
|
+
|
23
|
+
# Converts milliseconds since epoch timestamp into a time object.
|
24
|
+
def self.convert_timestamp_to_time(timestamp)
|
25
|
+
timestamp ? Time.at(timestamp / 1000, (timestamp % 1000) * 1000) : Time.at(0)
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(session)
|
29
|
+
@session = session
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :session
|
33
|
+
|
34
|
+
def last_write_timestamp
|
35
|
+
self.class.convert_timestamp_to_time(session[:last_write])
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_last_write_timestamp
|
39
|
+
session[:last_write] = self.class.convert_time_to_timestamp(Time.now)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/middleware/database_selector/resolver/session"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module Middleware
|
7
|
+
class DatabaseSelector
|
8
|
+
# The Resolver class is used by the DatabaseSelector middleware to
|
9
|
+
# determine which database the request should use.
|
10
|
+
#
|
11
|
+
# To change the behavior of the Resolver class in your application,
|
12
|
+
# create a custom resolver class that inherits from
|
13
|
+
# DatabaseSelector::Resolver and implements the methods that need to
|
14
|
+
# be changed.
|
15
|
+
#
|
16
|
+
# By default the Resolver class will send read traffic to the replica
|
17
|
+
# if it's been 2 seconds since the last write.
|
18
|
+
class Resolver # :nodoc:
|
19
|
+
SEND_TO_REPLICA_DELAY = 2.seconds
|
20
|
+
|
21
|
+
def self.call(context, options = {})
|
22
|
+
new(context, options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(context, options = {})
|
26
|
+
@context = context
|
27
|
+
@options = options
|
28
|
+
@delay = @options && @options[:delay] ? @options[:delay] : SEND_TO_REPLICA_DELAY
|
29
|
+
@instrumenter = ActiveSupport::Notifications.instrumenter
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :context, :delay, :instrumenter
|
33
|
+
|
34
|
+
def read(&blk)
|
35
|
+
if read_from_primary?
|
36
|
+
read_from_primary(&blk)
|
37
|
+
else
|
38
|
+
read_from_replica(&blk)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def write(&blk)
|
43
|
+
write_to_primary(&blk)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def read_from_primary(&blk)
|
49
|
+
ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do
|
50
|
+
ActiveRecord::Base.connection_handler.while_preventing_writes(true) do
|
51
|
+
instrumenter.instrument("database_selector.active_record.read_from_primary") do
|
52
|
+
yield
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def read_from_replica(&blk)
|
59
|
+
ActiveRecord::Base.connected_to(role: ActiveRecord::Base.reading_role) do
|
60
|
+
instrumenter.instrument("database_selector.active_record.read_from_replica") do
|
61
|
+
yield
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def write_to_primary(&blk)
|
67
|
+
ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do
|
68
|
+
ActiveRecord::Base.connection_handler.while_preventing_writes(false) do
|
69
|
+
instrumenter.instrument("database_selector.active_record.wrote_to_primary") do
|
70
|
+
yield
|
71
|
+
ensure
|
72
|
+
context.update_last_write_timestamp
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def read_from_primary?
|
79
|
+
!time_since_last_write_ok?
|
80
|
+
end
|
81
|
+
|
82
|
+
def send_to_replica_delay
|
83
|
+
delay
|
84
|
+
end
|
85
|
+
|
86
|
+
def time_since_last_write_ok?
|
87
|
+
Time.now - context.last_write_timestamp >= send_to_replica_delay
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/middleware/database_selector/resolver"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module Middleware
|
7
|
+
# The DatabaseSelector Middleware provides a framework for automatically
|
8
|
+
# swapping from the primary to the replica database connection. Rails
|
9
|
+
# provides a basic framework to determine when to swap and allows for
|
10
|
+
# applications to write custom strategy classes to override the default
|
11
|
+
# behavior.
|
12
|
+
#
|
13
|
+
# The resolver class defines when the application should switch (i.e. read
|
14
|
+
# from the primary if a write occurred less than 2 seconds ago) and a
|
15
|
+
# resolver context class that sets a value that helps the resolver class
|
16
|
+
# decide when to switch.
|
17
|
+
#
|
18
|
+
# Rails default middleware uses the request's session to set a timestamp
|
19
|
+
# that informs the application when to read from a primary or read from a
|
20
|
+
# replica.
|
21
|
+
#
|
22
|
+
# To use the DatabaseSelector in your application with default settings add
|
23
|
+
# the following options to your environment config:
|
24
|
+
#
|
25
|
+
# config.active_record.database_selector = { delay: 2.seconds }
|
26
|
+
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
|
27
|
+
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
|
28
|
+
#
|
29
|
+
# New applications will include these lines commented out in the production.rb.
|
30
|
+
#
|
31
|
+
# The default behavior can be changed by setting the config options to a
|
32
|
+
# custom class:
|
33
|
+
#
|
34
|
+
# config.active_record.database_selector = { delay: 2.seconds }
|
35
|
+
# config.active_record.database_resolver = MyResolver
|
36
|
+
# config.active_record.database_resolver_context = MyResolver::MySession
|
37
|
+
class DatabaseSelector
|
38
|
+
def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
|
39
|
+
@app = app
|
40
|
+
@resolver_klass = resolver_klass || Resolver
|
41
|
+
@context_klass = context_klass || Resolver::Session
|
42
|
+
@options = options
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :resolver_klass, :context_klass, :options
|
46
|
+
|
47
|
+
# Middleware that determines which database connection to use in a multiple
|
48
|
+
# database application.
|
49
|
+
def call(env)
|
50
|
+
request = ActionDispatch::Request.new(env)
|
51
|
+
|
52
|
+
select_database(request) do
|
53
|
+
@app.call(env)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def select_database(request, &blk)
|
60
|
+
context = context_klass.call(request)
|
61
|
+
resolver = resolver_klass.call(context, options)
|
62
|
+
|
63
|
+
if reading_request?(request)
|
64
|
+
resolver.read(&blk)
|
65
|
+
else
|
66
|
+
resolver.write(&blk)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def reading_request?(request)
|
71
|
+
request.get? || request.head?
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class Migration
|
3
5
|
# <tt>ActiveRecord::Migration::CommandRecorder</tt> records commands done during
|
@@ -5,15 +7,39 @@ module ActiveRecord
|
|
5
7
|
# knows how to invert the following commands:
|
6
8
|
#
|
7
9
|
# * add_column
|
10
|
+
# * add_foreign_key
|
8
11
|
# * add_index
|
12
|
+
# * add_reference
|
9
13
|
# * add_timestamps
|
10
|
-
# *
|
14
|
+
# * change_column
|
15
|
+
# * change_column_default (must supply a :from and :to option)
|
16
|
+
# * change_column_null
|
17
|
+
# * change_column_comment (must supply a :from and :to option)
|
18
|
+
# * change_table_comment (must supply a :from and :to option)
|
11
19
|
# * create_join_table
|
20
|
+
# * create_table
|
21
|
+
# * disable_extension
|
22
|
+
# * drop_join_table
|
23
|
+
# * drop_table (must supply a block)
|
24
|
+
# * enable_extension
|
25
|
+
# * remove_column (must supply a type)
|
26
|
+
# * remove_columns (must specify at least one column name or more)
|
27
|
+
# * remove_foreign_key (must supply a second table)
|
28
|
+
# * remove_index
|
29
|
+
# * remove_reference
|
12
30
|
# * remove_timestamps
|
13
31
|
# * rename_column
|
14
32
|
# * rename_index
|
15
33
|
# * rename_table
|
16
34
|
class CommandRecorder
|
35
|
+
ReversibleAndIrreversibleMethods = [:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
|
36
|
+
:rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
|
37
|
+
:change_column_default, :add_reference, :remove_reference, :transaction,
|
38
|
+
:drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension,
|
39
|
+
:change_column, :execute, :remove_columns, :change_column_null,
|
40
|
+
:add_foreign_key, :remove_foreign_key,
|
41
|
+
:change_column_comment, :change_table_comment
|
42
|
+
]
|
17
43
|
include JoinTable
|
18
44
|
|
19
45
|
attr_accessor :commands, :delegate, :reverting
|
@@ -41,7 +67,7 @@ module ActiveRecord
|
|
41
67
|
@reverting = !@reverting
|
42
68
|
end
|
43
69
|
|
44
|
-
#
|
70
|
+
# Record +command+. +command+ should be a method name and arguments.
|
45
71
|
# For example:
|
46
72
|
#
|
47
73
|
# recorder.record(:method_name, [:arg1, :arg2])
|
@@ -62,22 +88,16 @@ module ActiveRecord
|
|
62
88
|
# invert the +command+.
|
63
89
|
def inverse_of(command, args, &block)
|
64
90
|
method = :"invert_#{command}"
|
65
|
-
raise IrreversibleMigration unless respond_to?(method, true)
|
91
|
+
raise IrreversibleMigration, <<~MSG unless respond_to?(method, true)
|
92
|
+
This migration uses #{command}, which is not automatically reversible.
|
93
|
+
To make the migration reversible you can either:
|
94
|
+
1. Define #up and #down methods in place of the #change method.
|
95
|
+
2. Use the #reversible method to define reversible behavior.
|
96
|
+
MSG
|
66
97
|
send(method, args, &block)
|
67
98
|
end
|
68
99
|
|
69
|
-
|
70
|
-
super || delegate.respond_to?(*args)
|
71
|
-
end
|
72
|
-
|
73
|
-
[:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
|
74
|
-
:rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
|
75
|
-
:change_column_default, :add_reference, :remove_reference, :transaction,
|
76
|
-
:drop_join_table, :drop_table, :execute_block, :enable_extension,
|
77
|
-
:change_column, :execute, :remove_columns, :change_column_null,
|
78
|
-
:add_foreign_key, :remove_foreign_key
|
79
|
-
# irreversible methods need to be here too
|
80
|
-
].each do |method|
|
100
|
+
ReversibleAndIrreversibleMethods.each do |method|
|
81
101
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
82
102
|
def #{method}(*args, &block) # def create_table(*args, &block)
|
83
103
|
record(:"#{method}", args, &block) # record(:create_table, args, &block)
|
@@ -91,107 +111,174 @@ module ActiveRecord
|
|
91
111
|
yield delegate.update_table_definition(table_name, self)
|
92
112
|
end
|
93
113
|
|
114
|
+
def replay(migration)
|
115
|
+
commands.each do |cmd, args, block|
|
116
|
+
migration.send(cmd, *args, &block)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
94
120
|
private
|
95
121
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
122
|
+
module StraightReversions # :nodoc:
|
123
|
+
private
|
124
|
+
{
|
125
|
+
execute_block: :execute_block,
|
126
|
+
create_table: :drop_table,
|
127
|
+
create_join_table: :drop_join_table,
|
128
|
+
add_column: :remove_column,
|
129
|
+
add_timestamps: :remove_timestamps,
|
130
|
+
add_reference: :remove_reference,
|
131
|
+
enable_extension: :disable_extension
|
132
|
+
}.each do |cmd, inv|
|
133
|
+
[[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
|
134
|
+
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
135
|
+
def invert_#{method}(args, &block) # def invert_create_table(args, &block)
|
136
|
+
[:#{inverse}, args, block] # [:drop_table, args, block]
|
137
|
+
end # end
|
138
|
+
EOV
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
include StraightReversions
|
144
|
+
|
145
|
+
def invert_transaction(args)
|
146
|
+
sub_recorder = CommandRecorder.new(delegate)
|
147
|
+
sub_recorder.revert { yield }
|
148
|
+
|
149
|
+
invertions_proc = proc {
|
150
|
+
sub_recorder.replay(self)
|
151
|
+
}
|
152
|
+
|
153
|
+
[:transaction, args, invertions_proc]
|
154
|
+
end
|
155
|
+
|
156
|
+
def invert_drop_table(args, &block)
|
157
|
+
if args.size == 1 && block == nil
|
158
|
+
raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
|
113
159
|
end
|
160
|
+
super
|
114
161
|
end
|
115
|
-
end
|
116
162
|
|
117
|
-
|
163
|
+
def invert_rename_table(args)
|
164
|
+
[:rename_table, args.reverse]
|
165
|
+
end
|
118
166
|
|
119
|
-
|
120
|
-
|
121
|
-
|
167
|
+
def invert_remove_column(args)
|
168
|
+
raise ActiveRecord::IrreversibleMigration, "remove_column is only reversible if given a type." if args.size <= 2
|
169
|
+
super
|
122
170
|
end
|
123
|
-
super
|
124
|
-
end
|
125
171
|
|
126
|
-
|
127
|
-
|
128
|
-
|
172
|
+
def invert_rename_index(args)
|
173
|
+
[:rename_index, [args.first] + args.last(2).reverse]
|
174
|
+
end
|
129
175
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
end
|
176
|
+
def invert_rename_column(args)
|
177
|
+
[:rename_column, [args.first] + args.last(2).reverse]
|
178
|
+
end
|
134
179
|
|
135
|
-
|
136
|
-
|
137
|
-
|
180
|
+
def invert_add_index(args)
|
181
|
+
table, columns, options = *args
|
182
|
+
options ||= {}
|
138
183
|
|
139
|
-
|
140
|
-
|
141
|
-
end
|
184
|
+
options_hash = options.slice(:name, :algorithm)
|
185
|
+
options_hash[:column] = columns if !options_hash[:name]
|
142
186
|
|
143
|
-
|
144
|
-
|
145
|
-
options ||= {}
|
187
|
+
[:remove_index, [table, options_hash]]
|
188
|
+
end
|
146
189
|
|
147
|
-
|
148
|
-
|
190
|
+
def invert_remove_index(args)
|
191
|
+
table, options_or_column = *args
|
192
|
+
if (options = options_or_column).is_a?(Hash)
|
193
|
+
unless options[:column]
|
194
|
+
raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
|
195
|
+
end
|
196
|
+
options = options.dup
|
197
|
+
[:add_index, [table, options.delete(:column), options]]
|
198
|
+
elsif (column = options_or_column).present?
|
199
|
+
[:add_index, [table, column]]
|
200
|
+
end
|
201
|
+
end
|
149
202
|
|
150
|
-
|
151
|
-
|
203
|
+
alias :invert_add_belongs_to :invert_add_reference
|
204
|
+
alias :invert_remove_belongs_to :invert_remove_reference
|
152
205
|
|
153
|
-
|
154
|
-
|
206
|
+
def invert_change_column_default(args)
|
207
|
+
table, column, options = *args
|
155
208
|
|
156
|
-
|
157
|
-
|
209
|
+
unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
210
|
+
raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
|
211
|
+
end
|
212
|
+
|
213
|
+
[:change_column_default, [table, column, from: options[:to], to: options[:from]]]
|
158
214
|
end
|
159
215
|
|
160
|
-
|
161
|
-
|
162
|
-
|
216
|
+
def invert_change_column_null(args)
|
217
|
+
args[2] = !args[2]
|
218
|
+
[:change_column_null, args]
|
219
|
+
end
|
163
220
|
|
164
|
-
|
165
|
-
|
221
|
+
def invert_add_foreign_key(args)
|
222
|
+
from_table, to_table, add_options = args
|
223
|
+
add_options ||= {}
|
166
224
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
225
|
+
if add_options[:name]
|
226
|
+
options = { name: add_options[:name] }
|
227
|
+
elsif add_options[:column]
|
228
|
+
options = { column: add_options[:column] }
|
229
|
+
else
|
230
|
+
options = to_table
|
231
|
+
end
|
171
232
|
|
172
|
-
|
173
|
-
|
174
|
-
add_options ||= {}
|
233
|
+
[:remove_foreign_key, [from_table, options]]
|
234
|
+
end
|
175
235
|
|
176
|
-
|
177
|
-
options =
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
236
|
+
def invert_remove_foreign_key(args)
|
237
|
+
options = args.extract_options!
|
238
|
+
from_table, to_table = args
|
239
|
+
|
240
|
+
to_table ||= options.delete(:to_table)
|
241
|
+
|
242
|
+
raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil?
|
243
|
+
|
244
|
+
reversed_args = [from_table, to_table]
|
245
|
+
reversed_args << options unless options.empty?
|
246
|
+
|
247
|
+
[:add_foreign_key, reversed_args]
|
182
248
|
end
|
183
249
|
|
184
|
-
|
185
|
-
|
250
|
+
def invert_change_column_comment(args)
|
251
|
+
table, column, options = *args
|
186
252
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
253
|
+
unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
254
|
+
raise ActiveRecord::IrreversibleMigration, "change_column_comment is only reversible if given a :from and :to option."
|
255
|
+
end
|
256
|
+
|
257
|
+
[:change_column_comment, [table, column, from: options[:to], to: options[:from]]]
|
258
|
+
end
|
259
|
+
|
260
|
+
def invert_change_table_comment(args)
|
261
|
+
table, options = *args
|
262
|
+
|
263
|
+
unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
264
|
+
raise ActiveRecord::IrreversibleMigration, "change_table_comment is only reversible if given a :from and :to option."
|
265
|
+
end
|
266
|
+
|
267
|
+
[:change_table_comment, [table, from: options[:to], to: options[:from]]]
|
268
|
+
end
|
269
|
+
|
270
|
+
def respond_to_missing?(method, _)
|
271
|
+
super || delegate.respond_to?(method)
|
272
|
+
end
|
273
|
+
|
274
|
+
# Forwards any missing method call to the \target.
|
275
|
+
def method_missing(method, *args, &block)
|
276
|
+
if delegate.respond_to?(method)
|
277
|
+
delegate.public_send(method, *args, &block)
|
278
|
+
else
|
279
|
+
super
|
280
|
+
end
|
193
281
|
end
|
194
|
-
end
|
195
282
|
end
|
196
283
|
end
|
197
284
|
end
|