activerecord 3.2.6 → 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 +7 -0
- data/CHANGELOG.md +611 -6417
- data/MIT-LICENSE +4 -2
- data/README.rdoc +44 -47
- data/examples/performance.rb +79 -71
- data/examples/simple.rb +6 -5
- data/lib/active_record/aggregations.rb +268 -238
- data/lib/active_record/association_relation.rb +40 -0
- data/lib/active_record/associations/alias_tracker.rb +47 -42
- data/lib/active_record/associations/association.rb +173 -81
- data/lib/active_record/associations/association_scope.rb +124 -92
- data/lib/active_record/associations/belongs_to_association.rb +83 -38
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +11 -9
- data/lib/active_record/associations/builder/association.rb +113 -32
- data/lib/active_record/associations/builder/belongs_to.rb +105 -60
- data/lib/active_record/associations/builder/collection_association.rb +53 -56
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +98 -41
- data/lib/active_record/associations/builder/has_many.rb +11 -63
- data/lib/active_record/associations/builder/has_one.rb +47 -45
- data/lib/active_record/associations/builder/singular_association.rb +30 -18
- data/lib/active_record/associations/collection_association.rb +217 -295
- data/lib/active_record/associations/collection_proxy.rb +1074 -77
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +78 -50
- data/lib/active_record/associations/has_many_through_association.rb +99 -61
- data/lib/active_record/associations/has_one_association.rb +75 -30
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +45 -119
- data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
- data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
- data/lib/active_record/associations/join_dependency.rb +208 -164
- data/lib/active_record/associations/preloader/association.rb +93 -87
- data/lib/active_record/associations/preloader/through_association.rb +87 -38
- data/lib/active_record/associations/preloader.rb +134 -110
- data/lib/active_record/associations/singular_association.rb +19 -24
- data/lib/active_record/associations/through_association.rb +61 -27
- data/lib/active_record/associations.rb +1766 -1505
- data/lib/active_record/attribute_assignment.rb +57 -193
- data/lib/active_record/attribute_decorators.rb +90 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +58 -8
- data/lib/active_record/attribute_methods/dirty.rb +187 -67
- data/lib/active_record/attribute_methods/primary_key.rb +100 -78
- data/lib/active_record/attribute_methods/query.rb +10 -8
- data/lib/active_record/attribute_methods/read.rb +29 -118
- data/lib/active_record/attribute_methods/serialization.rb +60 -72
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -42
- data/lib/active_record/attribute_methods/write.rb +36 -44
- data/lib/active_record/attribute_methods.rb +306 -161
- data/lib/active_record/attributes.rb +279 -0
- data/lib/active_record/autosave_association.rb +324 -238
- data/lib/active_record/base.rb +114 -507
- data/lib/active_record/callbacks.rb +147 -83
- data/lib/active_record/coders/json.rb +15 -0
- data/lib/active_record/coders/yaml_column.rb +32 -23
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +962 -279
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +32 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +331 -209
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +201 -65
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +510 -289
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1182 -313
- data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +585 -120
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +610 -463
- data/lib/active_record/connection_adapters/column.rb +58 -233
- data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
- 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 +75 -207
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +695 -1052
- data/lib/active_record/connection_adapters/schema_cache.rb +115 -24
- 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 +528 -26
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +267 -0
- data/lib/active_record/core.rb +599 -0
- data/lib/active_record/counter_cache.rb +177 -103
- 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 +107 -64
- data/lib/active_record/enum.rb +274 -0
- data/lib/active_record/errors.rb +254 -61
- data/lib/active_record/explain.rb +35 -70
- data/lib/active_record/explain_registry.rb +32 -0
- data/lib/active_record/explain_subscriber.rb +18 -8
- data/lib/active_record/fixture_set/file.rb +82 -0
- 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 +291 -475
- data/lib/active_record/gem_version.rb +17 -0
- data/lib/active_record/inheritance.rb +219 -100
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +175 -17
- 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 +9 -1
- data/lib/active_record/locking/optimistic.rb +106 -92
- data/lib/active_record/locking/pessimistic.rb +23 -11
- data/lib/active_record/log_subscriber.rb +80 -30
- 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 +235 -56
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +17 -0
- data/lib/active_record/migration.rb +917 -301
- data/lib/active_record/model_schema.rb +351 -175
- data/lib/active_record/nested_attributes.rb +366 -235
- data/lib/active_record/no_touching.rb +65 -0
- data/lib/active_record/null_relation.rb +68 -0
- data/lib/active_record/persistence.rb +761 -166
- data/lib/active_record/query_cache.rb +22 -44
- data/lib/active_record/querying.rb +55 -31
- data/lib/active_record/railtie.rb +185 -47
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +5 -4
- data/lib/active_record/railties/controller_runtime.rb +35 -33
- data/lib/active_record/railties/databases.rake +366 -463
- data/lib/active_record/readonly_attributes.rb +4 -6
- data/lib/active_record/reflection.rb +736 -228
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +252 -52
- data/lib/active_record/relation/calculations.rb +340 -270
- data/lib/active_record/relation/delegation.rb +117 -36
- data/lib/active_record/relation/finder_methods.rb +439 -286
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +184 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
- 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 +19 -0
- data/lib/active_record/relation/predicate_builder.rb +131 -39
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +1163 -221
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +49 -120
- 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 +671 -349
- data/lib/active_record/result.rb +149 -15
- data/lib/active_record/runtime_registry.rb +24 -0
- data/lib/active_record/sanitization.rb +153 -133
- data/lib/active_record/schema.rb +22 -19
- data/lib/active_record/schema_dumper.rb +178 -112
- data/lib/active_record/schema_migration.rb +60 -0
- data/lib/active_record/scoping/default.rb +107 -98
- data/lib/active_record/scoping/named.rb +130 -115
- data/lib/active_record/scoping.rb +77 -123
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +10 -6
- data/lib/active_record/statement_cache.rb +148 -0
- data/lib/active_record/store.rb +256 -16
- 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 +506 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +93 -39
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +260 -129
- 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 +9 -0
- data/lib/active_record/type/date_time.rb +9 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
- 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 +71 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +21 -0
- data/lib/active_record/type/type_map.rb +62 -0
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +78 -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/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +35 -18
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +68 -0
- data/lib/active_record/validations/uniqueness.rb +123 -77
- data/lib/active_record/validations.rb +54 -43
- data/lib/active_record/version.rb +7 -7
- data/lib/active_record.rb +97 -49
- 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 +59 -9
- 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.tt +48 -0
- data/lib/rails/generators/active_record/migration.rb +41 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +24 -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} +1 -1
- data/lib/rails/generators/active_record.rb +10 -16
- metadata +285 -149
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
- data/lib/active_record/associations/join_helper.rb +0 -55
- 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_and_belongs_to_many.rb +0 -60
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
- 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_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -188
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -426
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -579
- data/lib/active_record/dynamic_finder_match.rb +0 -68
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/fixtures/file.rb +0 -65
- data/lib/active_record/identity_map.rb +0 -162
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -203
- data/lib/active_record/session_store.rb +0 -358
- data/lib/active_record/test_case.rb +0 -73
- data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,51 +1,246 @@
|
|
1
|
-
|
2
|
-
require 'date'
|
3
|
-
require 'set'
|
4
|
-
require 'bigdecimal'
|
5
|
-
require 'bigdecimal/util'
|
1
|
+
# frozen_string_literal: true
|
6
2
|
|
7
3
|
module ActiveRecord
|
8
4
|
module ConnectionAdapters #:nodoc:
|
9
|
-
|
5
|
+
# Abstract representation of an index definition on a table. Instances of
|
6
|
+
# this type are typically created and returned by methods in database
|
7
|
+
# adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes
|
8
|
+
class IndexDefinition # :nodoc:
|
9
|
+
attr_reader :table, :name, :unique, :columns, :lengths, :orders, :opclasses, :where, :type, :using, :comment
|
10
|
+
|
11
|
+
def initialize(
|
12
|
+
table, name,
|
13
|
+
unique = false,
|
14
|
+
columns = [],
|
15
|
+
lengths: {},
|
16
|
+
orders: {},
|
17
|
+
opclasses: {},
|
18
|
+
where: nil,
|
19
|
+
type: nil,
|
20
|
+
using: nil,
|
21
|
+
comment: nil
|
22
|
+
)
|
23
|
+
@table = table
|
24
|
+
@name = name
|
25
|
+
@unique = unique
|
26
|
+
@columns = columns
|
27
|
+
@lengths = concise_options(lengths)
|
28
|
+
@orders = concise_options(orders)
|
29
|
+
@opclasses = concise_options(opclasses)
|
30
|
+
@where = where
|
31
|
+
@type = type
|
32
|
+
@using = using
|
33
|
+
@comment = comment
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def concise_options(options)
|
38
|
+
if columns.size == options.size && options.values.uniq.size == 1
|
39
|
+
options.values.first
|
40
|
+
else
|
41
|
+
options
|
42
|
+
end
|
43
|
+
end
|
10
44
|
end
|
11
45
|
|
12
46
|
# Abstract representation of a column definition. Instances of this type
|
13
47
|
# are typically created by methods in TableDefinition, and added to the
|
14
48
|
# +columns+ attribute of said TableDefinition object, in order to be used
|
15
49
|
# for generating a number of table creation or table changing SQL statements.
|
16
|
-
|
50
|
+
ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
|
51
|
+
def primary_key?
|
52
|
+
options[:primary_key]
|
53
|
+
end
|
54
|
+
|
55
|
+
[:limit, :precision, :scale, :default, :null, :collation, :comment].each do |option_name|
|
56
|
+
module_eval <<-CODE, __FILE__, __LINE__ + 1
|
57
|
+
def #{option_name}
|
58
|
+
options[:#{option_name}]
|
59
|
+
end
|
60
|
+
|
61
|
+
def #{option_name}=(value)
|
62
|
+
options[:#{option_name}] = value
|
63
|
+
end
|
64
|
+
CODE
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
AddColumnDefinition = Struct.new(:column) # :nodoc:
|
69
|
+
|
70
|
+
ChangeColumnDefinition = Struct.new(:column, :name) #:nodoc:
|
71
|
+
|
72
|
+
PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
|
73
|
+
|
74
|
+
ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do #:nodoc:
|
75
|
+
def name
|
76
|
+
options[:name]
|
77
|
+
end
|
78
|
+
|
79
|
+
def column
|
80
|
+
options[:column]
|
81
|
+
end
|
82
|
+
|
83
|
+
def primary_key
|
84
|
+
options[:primary_key] || default_primary_key
|
85
|
+
end
|
86
|
+
|
87
|
+
def on_delete
|
88
|
+
options[:on_delete]
|
89
|
+
end
|
90
|
+
|
91
|
+
def on_update
|
92
|
+
options[:on_update]
|
93
|
+
end
|
94
|
+
|
95
|
+
def custom_primary_key?
|
96
|
+
options[:primary_key] != default_primary_key
|
97
|
+
end
|
17
98
|
|
18
|
-
def
|
19
|
-
|
99
|
+
def validate?
|
100
|
+
options.fetch(:validate, true)
|
20
101
|
end
|
102
|
+
alias validated? validate?
|
21
103
|
|
22
|
-
def
|
23
|
-
|
104
|
+
def export_name_on_schema_dump?
|
105
|
+
!ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
|
24
106
|
end
|
25
107
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
column_options[:null] = null unless null.nil?
|
30
|
-
column_options[:default] = default unless default.nil?
|
31
|
-
add_column_options!(column_sql, column_options) unless type.to_sym == :primary_key
|
32
|
-
column_sql
|
108
|
+
def defined_for?(to_table: nil, **options)
|
109
|
+
(to_table.nil? || to_table.to_s == self.to_table) &&
|
110
|
+
options.all? { |k, v| self.options[k].to_s == v.to_s }
|
33
111
|
end
|
34
112
|
|
35
113
|
private
|
114
|
+
def default_primary_key
|
115
|
+
"id"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class ReferenceDefinition # :nodoc:
|
120
|
+
def initialize(
|
121
|
+
name,
|
122
|
+
polymorphic: false,
|
123
|
+
index: true,
|
124
|
+
foreign_key: false,
|
125
|
+
type: :bigint,
|
126
|
+
**options
|
127
|
+
)
|
128
|
+
@name = name
|
129
|
+
@polymorphic = polymorphic
|
130
|
+
@index = index
|
131
|
+
@foreign_key = foreign_key
|
132
|
+
@type = type
|
133
|
+
@options = options
|
134
|
+
|
135
|
+
if polymorphic && foreign_key
|
136
|
+
raise ArgumentError, "Cannot add a foreign key to a polymorphic relation"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def add_to(table)
|
141
|
+
columns.each do |column_options|
|
142
|
+
table.column(*column_options)
|
143
|
+
end
|
144
|
+
|
145
|
+
if index
|
146
|
+
table.index(column_names, index_options)
|
147
|
+
end
|
148
|
+
|
149
|
+
if foreign_key
|
150
|
+
table.foreign_key(foreign_table_name, foreign_key_options)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
|
156
|
+
|
157
|
+
def as_options(value)
|
158
|
+
value.is_a?(Hash) ? value : {}
|
159
|
+
end
|
160
|
+
|
161
|
+
def polymorphic_options
|
162
|
+
as_options(polymorphic).merge(options.slice(:null, :first, :after))
|
163
|
+
end
|
36
164
|
|
37
|
-
def
|
38
|
-
|
165
|
+
def index_options
|
166
|
+
as_options(index)
|
39
167
|
end
|
168
|
+
|
169
|
+
def foreign_key_options
|
170
|
+
as_options(foreign_key).merge(column: column_name)
|
171
|
+
end
|
172
|
+
|
173
|
+
def columns
|
174
|
+
result = [[column_name, type, options]]
|
175
|
+
if polymorphic
|
176
|
+
result.unshift(["#{name}_type", :string, polymorphic_options])
|
177
|
+
end
|
178
|
+
result
|
179
|
+
end
|
180
|
+
|
181
|
+
def column_name
|
182
|
+
"#{name}_id"
|
183
|
+
end
|
184
|
+
|
185
|
+
def column_names
|
186
|
+
columns.map(&:first)
|
187
|
+
end
|
188
|
+
|
189
|
+
def foreign_table_name
|
190
|
+
foreign_key_options.fetch(:to_table) do
|
191
|
+
Base.pluralize_table_names ? name.to_s.pluralize : name
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
module ColumnMethods
|
197
|
+
extend ActiveSupport::Concern
|
198
|
+
|
199
|
+
# Appends a primary key definition to the table definition.
|
200
|
+
# Can be called multiple times, but this is probably not a good idea.
|
201
|
+
def primary_key(name, type = :primary_key, **options)
|
202
|
+
column(name, type, options.merge(primary_key: true))
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# :method: column
|
207
|
+
# :call-seq: column(name, type, **options)
|
208
|
+
#
|
209
|
+
# Appends a column or columns of a specified type.
|
210
|
+
#
|
211
|
+
# t.string(:goat)
|
212
|
+
# t.string(:goat, :sheep)
|
213
|
+
#
|
214
|
+
# See TableDefinition#column
|
215
|
+
|
216
|
+
included do
|
217
|
+
define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
|
218
|
+
:float, :integer, :json, :string, :text, :time, :timestamp, :virtual
|
219
|
+
|
220
|
+
alias :numeric :decimal
|
221
|
+
end
|
222
|
+
|
223
|
+
class_methods do
|
224
|
+
private def define_column_methods(*column_types) # :nodoc:
|
225
|
+
column_types.each do |column_type|
|
226
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
227
|
+
def #{column_type}(*names, **options)
|
228
|
+
raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
|
229
|
+
names.each { |name| column(name, :#{column_type}, options) }
|
230
|
+
end
|
231
|
+
RUBY
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
40
235
|
end
|
41
236
|
|
42
237
|
# Represents the schema of an SQL table in an abstract way. This class
|
43
238
|
# provides methods for manipulating the schema representation.
|
44
239
|
#
|
45
|
-
# Inside migration files, the +t+ object in
|
46
|
-
#
|
240
|
+
# Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
|
241
|
+
# is actually of this type:
|
47
242
|
#
|
48
|
-
# class SomeMigration < ActiveRecord::Migration
|
243
|
+
# class SomeMigration < ActiveRecord::Migration[5.0]
|
49
244
|
# def up
|
50
245
|
# create_table :foo do |t|
|
51
246
|
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
@@ -57,33 +252,41 @@ module ActiveRecord
|
|
57
252
|
# end
|
58
253
|
# end
|
59
254
|
#
|
60
|
-
# The table definitions
|
61
|
-
# The Columns are stored as a ColumnDefinition in the +columns+ attribute.
|
62
255
|
class TableDefinition
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
def initialize(
|
68
|
-
|
256
|
+
include ColumnMethods
|
257
|
+
|
258
|
+
attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
|
259
|
+
|
260
|
+
def initialize(
|
261
|
+
conn,
|
262
|
+
name,
|
263
|
+
temporary: false,
|
264
|
+
if_not_exists: false,
|
265
|
+
options: nil,
|
266
|
+
as: nil,
|
267
|
+
comment: nil,
|
268
|
+
**
|
269
|
+
)
|
270
|
+
@conn = conn
|
69
271
|
@columns_hash = {}
|
70
|
-
@
|
272
|
+
@indexes = []
|
273
|
+
@foreign_keys = []
|
274
|
+
@primary_keys = nil
|
275
|
+
@temporary = temporary
|
276
|
+
@if_not_exists = if_not_exists
|
277
|
+
@options = options
|
278
|
+
@as = as
|
279
|
+
@name = name
|
280
|
+
@comment = comment
|
71
281
|
end
|
72
282
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
}.include? @base.adapter_name.downcase
|
77
|
-
|
78
|
-
options = args.extract_options!
|
79
|
-
column(args[0], :text, options)
|
283
|
+
def primary_keys(name = nil) # :nodoc:
|
284
|
+
@primary_keys = PrimaryKeyDefinition.new(name) if name
|
285
|
+
@primary_keys
|
80
286
|
end
|
81
287
|
|
82
|
-
#
|
83
|
-
|
84
|
-
def primary_key(name)
|
85
|
-
column(name, :primary_key)
|
86
|
-
end
|
288
|
+
# Returns an array of ColumnDefinition objects for the columns of the table.
|
289
|
+
def columns; @columns_hash.values; end
|
87
290
|
|
88
291
|
# Returns a ColumnDefinition for the column with name +name+.
|
89
292
|
def [](name)
|
@@ -91,117 +294,46 @@ module ActiveRecord
|
|
91
294
|
end
|
92
295
|
|
93
296
|
# Instantiates a new column for the table.
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
# You may use a type not in this list as long as it is supported by your
|
102
|
-
# database (for example, "polygon" in MySQL), but this will not be database
|
103
|
-
# agnostic and should usually be avoided.
|
104
|
-
#
|
105
|
-
# Available options are (none of these exists by default):
|
106
|
-
# * <tt>:limit</tt> -
|
107
|
-
# Requests a maximum column length. This is number of characters for <tt>:string</tt> and
|
108
|
-
# <tt>:text</tt> columns and number of bytes for <tt>:binary</tt> and <tt>:integer</tt> columns.
|
109
|
-
# * <tt>:default</tt> -
|
110
|
-
# The column's default value. Use nil for NULL.
|
111
|
-
# * <tt>:null</tt> -
|
112
|
-
# Allows or disallows +NULL+ values in the column. This option could
|
113
|
-
# have been named <tt>:null_allowed</tt>.
|
114
|
-
# * <tt>:precision</tt> -
|
115
|
-
# Specifies the precision for a <tt>:decimal</tt> column.
|
116
|
-
# * <tt>:scale</tt> -
|
117
|
-
# Specifies the scale for a <tt>:decimal</tt> column.
|
118
|
-
#
|
119
|
-
# For clarity's sake: the precision is the number of significant digits,
|
120
|
-
# while the scale is the number of digits that can be stored following
|
121
|
-
# the decimal point. For example, the number 123.45 has a precision of 5
|
122
|
-
# and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
|
123
|
-
# range from -999.99 to 999.99.
|
124
|
-
#
|
125
|
-
# Please be aware of different RDBMS implementations behavior with
|
126
|
-
# <tt>:decimal</tt> columns:
|
127
|
-
# * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
|
128
|
-
# <tt>:precision</tt>, and makes no comments about the requirements of
|
129
|
-
# <tt>:precision</tt>.
|
130
|
-
# * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
|
131
|
-
# Default is (10,0).
|
132
|
-
# * PostgreSQL: <tt>:precision</tt> [1..infinity],
|
133
|
-
# <tt>:scale</tt> [0..infinity]. No default.
|
134
|
-
# * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
|
135
|
-
# Internal storage as strings. No default.
|
136
|
-
# * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
|
137
|
-
# but the maximum supported <tt>:precision</tt> is 16. No default.
|
138
|
-
# * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
|
139
|
-
# Default is (38,0).
|
140
|
-
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
|
141
|
-
# Default unknown.
|
142
|
-
# * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
|
143
|
-
# Default (9,0). Internal types NUMERIC and DECIMAL have different
|
144
|
-
# storage rules, decimal being better.
|
145
|
-
# * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
146
|
-
# Default (38,0). WARNING Max <tt>:precision</tt>/<tt>:scale</tt> for
|
147
|
-
# NUMERIC is 19, and DECIMAL is 38.
|
148
|
-
# * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
149
|
-
# Default (38,0).
|
150
|
-
# * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
151
|
-
# Default (38,0).
|
152
|
-
# * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
|
297
|
+
# See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column]
|
298
|
+
# for available options.
|
299
|
+
#
|
300
|
+
# Additional options are:
|
301
|
+
# * <tt>:index</tt> -
|
302
|
+
# Create an index for the column. Can be either <tt>true</tt> or an options hash.
|
153
303
|
#
|
154
304
|
# This method returns <tt>self</tt>.
|
155
305
|
#
|
156
306
|
# == Examples
|
157
|
-
# # Assuming +td+ is an instance of TableDefinition
|
158
|
-
# td.column(:granted, :boolean)
|
159
|
-
# # granted BOOLEAN
|
160
|
-
#
|
161
|
-
# td.column(:picture, :binary, :limit => 2.megabytes)
|
162
|
-
# # => picture BLOB(2097152)
|
163
307
|
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
# td.column(:bill_gates_money, :decimal, :precision => 15, :scale => 2)
|
168
|
-
# # => bill_gates_money DECIMAL(15,2)
|
169
|
-
#
|
170
|
-
# td.column(:sensor_reading, :decimal, :precision => 30, :scale => 20)
|
171
|
-
# # => sensor_reading DECIMAL(30,20)
|
172
|
-
#
|
173
|
-
# # While <tt>:scale</tt> defaults to zero on most databases, it
|
174
|
-
# # probably wouldn't hurt to include it.
|
175
|
-
# td.column(:huge_integer, :decimal, :precision => 30)
|
176
|
-
# # => huge_integer DECIMAL(30)
|
177
|
-
#
|
178
|
-
# # Defines a column with a database-specific type.
|
179
|
-
# td.column(:foo, 'polygon')
|
180
|
-
# # => foo polygon
|
308
|
+
# # Assuming +td+ is an instance of TableDefinition
|
309
|
+
# td.column(:granted, :boolean, index: true)
|
181
310
|
#
|
182
311
|
# == Short-hand examples
|
183
312
|
#
|
184
|
-
# Instead of calling
|
313
|
+
# Instead of calling #column directly, you can also work with the short-hand definitions for the default types.
|
185
314
|
# They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
|
186
315
|
# in a single statement.
|
187
316
|
#
|
188
317
|
# What can be written like this with the regular calls to column:
|
189
318
|
#
|
190
|
-
# create_table
|
191
|
-
# t.column
|
192
|
-
# t.column
|
193
|
-
# t.column
|
194
|
-
# t.column
|
195
|
-
# t.column
|
196
|
-
# t.column
|
319
|
+
# create_table :products do |t|
|
320
|
+
# t.column :shop_id, :integer
|
321
|
+
# t.column :creator_id, :integer
|
322
|
+
# t.column :item_number, :string
|
323
|
+
# t.column :name, :string, default: "Untitled"
|
324
|
+
# t.column :value, :string, default: "Untitled"
|
325
|
+
# t.column :created_at, :datetime
|
326
|
+
# t.column :updated_at, :datetime
|
197
327
|
# end
|
328
|
+
# add_index :products, :item_number
|
198
329
|
#
|
199
|
-
#
|
330
|
+
# can also be written as follows using the short-hand:
|
200
331
|
#
|
201
332
|
# create_table :products do |t|
|
202
333
|
# t.integer :shop_id, :creator_id
|
203
|
-
# t.string :
|
204
|
-
# t.
|
334
|
+
# t.string :item_number, index: true
|
335
|
+
# t.string :name, :value, default: "Untitled"
|
336
|
+
# t.timestamps null: false
|
205
337
|
# end
|
206
338
|
#
|
207
339
|
# There's a short-hand method for each of the type values declared at the top. And then there's
|
@@ -209,96 +341,158 @@ module ActiveRecord
|
|
209
341
|
#
|
210
342
|
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
|
211
343
|
# column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
|
212
|
-
# options, these will be used when creating the <tt>_type</tt> column.
|
344
|
+
# options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
|
345
|
+
# will also create an index, similar to calling {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index].
|
346
|
+
# So what can be written like this:
|
213
347
|
#
|
214
348
|
# create_table :taggings do |t|
|
215
349
|
# t.integer :tag_id, :tagger_id, :taggable_id
|
216
350
|
# t.string :tagger_type
|
217
|
-
# t.string :taggable_type, :
|
351
|
+
# t.string :taggable_type, default: 'Photo'
|
218
352
|
# end
|
353
|
+
# add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
|
354
|
+
# add_index :taggings, [:tagger_id, :tagger_type]
|
219
355
|
#
|
220
356
|
# Can also be written as follows using references:
|
221
357
|
#
|
222
358
|
# create_table :taggings do |t|
|
223
|
-
# t.references :tag
|
224
|
-
# t.references :tagger, :
|
225
|
-
# t.references :taggable, :
|
359
|
+
# t.references :tag, index: { name: 'index_taggings_on_tag_id' }
|
360
|
+
# t.references :tagger, polymorphic: true
|
361
|
+
# t.references :taggable, polymorphic: { default: 'Photo' }, index: false
|
226
362
|
# end
|
227
|
-
def column(name, type, options
|
363
|
+
def column(name, type, **options)
|
228
364
|
name = name.to_s
|
229
|
-
type = type.to_sym
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
365
|
+
type = type.to_sym if type
|
366
|
+
options = options.dup
|
367
|
+
|
368
|
+
if @columns_hash[name]
|
369
|
+
if @columns_hash[name].primary_key?
|
370
|
+
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
371
|
+
else
|
372
|
+
raise ArgumentError, "you can't define an already defined column '#{name}'."
|
373
|
+
end
|
235
374
|
end
|
236
375
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
column.default = options[:default]
|
241
|
-
column.null = options[:null]
|
376
|
+
index_options = options.delete(:index)
|
377
|
+
index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
|
378
|
+
@columns_hash[name] = new_column_definition(name, type, options)
|
242
379
|
self
|
243
380
|
end
|
244
381
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
382
|
+
# remove the column +name+ from the table.
|
383
|
+
# remove_column(:account_id)
|
384
|
+
def remove_column(name)
|
385
|
+
@columns_hash.delete name.to_s
|
386
|
+
end
|
387
|
+
|
388
|
+
# Adds index options to the indexes hash, keyed by column name
|
389
|
+
# This is primarily used to track indexes that need to be created after the table
|
390
|
+
#
|
391
|
+
# index(:account_id, name: 'index_projects_on_account_id')
|
392
|
+
def index(column_name, options = {})
|
393
|
+
indexes << [column_name, options]
|
394
|
+
end
|
395
|
+
|
396
|
+
def foreign_key(table_name, options = {}) # :nodoc:
|
397
|
+
foreign_keys << [table_name, options]
|
254
398
|
end
|
255
399
|
|
256
400
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
257
|
-
# <tt>:updated_at</tt> to the table.
|
258
|
-
|
259
|
-
|
401
|
+
# <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
|
402
|
+
#
|
403
|
+
# t.timestamps null: false
|
404
|
+
def timestamps(**options)
|
405
|
+
options[:null] = false if options[:null].nil?
|
406
|
+
|
407
|
+
if !options.key?(:precision) && @conn.supports_datetime_with_precision?
|
408
|
+
options[:precision] = 6
|
409
|
+
end
|
410
|
+
|
260
411
|
column(:created_at, :datetime, options)
|
261
412
|
column(:updated_at, :datetime, options)
|
262
413
|
end
|
263
414
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
415
|
+
# Adds a reference.
|
416
|
+
#
|
417
|
+
# t.references(:user)
|
418
|
+
# t.belongs_to(:supplier, foreign_key: true)
|
419
|
+
# t.belongs_to(:supplier, foreign_key: true, type: :integer)
|
420
|
+
#
|
421
|
+
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
422
|
+
def references(*args, **options)
|
423
|
+
args.each do |ref_name|
|
424
|
+
ReferenceDefinition.new(ref_name, options).add_to(self)
|
270
425
|
end
|
271
426
|
end
|
272
427
|
alias :belongs_to :references
|
273
428
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
429
|
+
def new_column_definition(name, type, **options) # :nodoc:
|
430
|
+
if integer_like_primary_key?(type, options)
|
431
|
+
type = integer_like_primary_key_type(type, options)
|
432
|
+
end
|
433
|
+
type = aliased_types(type.to_s, type)
|
434
|
+
options[:primary_key] ||= type == :primary_key
|
435
|
+
options[:null] = false if options[:primary_key]
|
436
|
+
create_column_definition(name, type, options)
|
279
437
|
end
|
280
438
|
|
281
439
|
private
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
440
|
+
def create_column_definition(name, type, options)
|
441
|
+
ColumnDefinition.new(name, type, options)
|
442
|
+
end
|
443
|
+
|
444
|
+
def aliased_types(name, fallback)
|
445
|
+
"timestamp" == name ? :datetime : fallback
|
446
|
+
end
|
447
|
+
|
448
|
+
def integer_like_primary_key?(type, options)
|
449
|
+
options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
|
450
|
+
end
|
451
|
+
|
452
|
+
def integer_like_primary_key_type(type, options)
|
453
|
+
type
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
class AlterTable # :nodoc:
|
458
|
+
attr_reader :adds
|
459
|
+
attr_reader :foreign_key_adds
|
460
|
+
attr_reader :foreign_key_drops
|
461
|
+
|
462
|
+
def initialize(td)
|
463
|
+
@td = td
|
464
|
+
@adds = []
|
465
|
+
@foreign_key_adds = []
|
466
|
+
@foreign_key_drops = []
|
287
467
|
end
|
288
468
|
|
289
|
-
def
|
290
|
-
|
469
|
+
def name; @td.name; end
|
470
|
+
|
471
|
+
def add_foreign_key(to_table, options)
|
472
|
+
@foreign_key_adds << ForeignKeyDefinition.new(name, to_table, options)
|
473
|
+
end
|
474
|
+
|
475
|
+
def drop_foreign_key(name)
|
476
|
+
@foreign_key_drops << name
|
477
|
+
end
|
478
|
+
|
479
|
+
def add_column(name, type, options)
|
480
|
+
name = name.to_s
|
481
|
+
type = type.to_sym
|
482
|
+
@adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
|
291
483
|
end
|
292
484
|
end
|
293
485
|
|
294
486
|
# Represents an SQL table in an abstract way for updating a table.
|
295
|
-
# Also see TableDefinition and SchemaStatements#create_table
|
487
|
+
# Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
|
296
488
|
#
|
297
489
|
# Available transformations are:
|
298
490
|
#
|
299
491
|
# change_table :table do |t|
|
492
|
+
# t.primary_key
|
300
493
|
# t.column
|
301
494
|
# t.index
|
495
|
+
# t.rename_index
|
302
496
|
# t.timestamps
|
303
497
|
# t.change
|
304
498
|
# t.change_default
|
@@ -308,15 +502,21 @@ module ActiveRecord
|
|
308
502
|
# t.string
|
309
503
|
# t.text
|
310
504
|
# t.integer
|
505
|
+
# t.bigint
|
311
506
|
# t.float
|
312
507
|
# t.decimal
|
508
|
+
# t.numeric
|
313
509
|
# t.datetime
|
314
510
|
# t.timestamp
|
315
511
|
# t.time
|
316
512
|
# t.date
|
317
513
|
# t.binary
|
318
514
|
# t.boolean
|
515
|
+
# t.foreign_key
|
516
|
+
# t.json
|
517
|
+
# t.virtual
|
319
518
|
# t.remove
|
519
|
+
# t.remove_foreign_key
|
320
520
|
# t.remove_references
|
321
521
|
# t.remove_belongs_to
|
322
522
|
# t.remove_index
|
@@ -324,169 +524,190 @@ module ActiveRecord
|
|
324
524
|
# end
|
325
525
|
#
|
326
526
|
class Table
|
527
|
+
include ColumnMethods
|
528
|
+
|
529
|
+
attr_reader :name
|
530
|
+
|
327
531
|
def initialize(table_name, base)
|
328
|
-
@
|
532
|
+
@name = table_name
|
329
533
|
@base = base
|
330
534
|
end
|
331
535
|
|
332
536
|
# Adds a new column to the named table.
|
333
|
-
#
|
334
|
-
# ===== Example
|
335
|
-
# ====== Creating a simple column
|
537
|
+
#
|
336
538
|
# t.column(:name, :string)
|
337
|
-
|
338
|
-
|
539
|
+
#
|
540
|
+
# See TableDefinition#column for details of the options you can use.
|
541
|
+
def column(column_name, type, **options)
|
542
|
+
index_options = options.delete(:index)
|
543
|
+
@base.add_column(name, column_name, type, options)
|
544
|
+
index(column_name, index_options.is_a?(Hash) ? index_options : {}) if index_options
|
339
545
|
end
|
340
546
|
|
341
|
-
# Checks to see if a column exists.
|
547
|
+
# Checks to see if a column exists.
|
548
|
+
#
|
549
|
+
# t.string(:name) unless t.column_exists?(:name, :string)
|
550
|
+
#
|
551
|
+
# See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
|
342
552
|
def column_exists?(column_name, type = nil, options = {})
|
343
|
-
@base.column_exists?(
|
553
|
+
@base.column_exists?(name, column_name, type, options)
|
344
554
|
end
|
345
555
|
|
346
556
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
347
|
-
# an Array of Symbols.
|
557
|
+
# an Array of Symbols.
|
348
558
|
#
|
349
|
-
# ===== Examples
|
350
|
-
# ====== Creating a simple index
|
351
559
|
# t.index(:name)
|
352
|
-
#
|
353
|
-
# t.index([:branch_id, :party_id], :
|
354
|
-
#
|
355
|
-
#
|
560
|
+
# t.index([:branch_id, :party_id], unique: true)
|
561
|
+
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
|
562
|
+
#
|
563
|
+
# See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
|
356
564
|
def index(column_name, options = {})
|
357
|
-
@base.add_index(
|
565
|
+
@base.add_index(name, column_name, options)
|
358
566
|
end
|
359
567
|
|
360
|
-
# Checks to see if an index exists.
|
568
|
+
# Checks to see if an index exists.
|
569
|
+
#
|
570
|
+
# unless t.index_exists?(:branch_id)
|
571
|
+
# t.index(:branch_id)
|
572
|
+
# end
|
573
|
+
#
|
574
|
+
# See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
|
361
575
|
def index_exists?(column_name, options = {})
|
362
|
-
@base.index_exists?(
|
576
|
+
@base.index_exists?(name, column_name, options)
|
363
577
|
end
|
364
578
|
|
365
|
-
#
|
366
|
-
#
|
367
|
-
# t.
|
368
|
-
|
369
|
-
|
579
|
+
# Renames the given index on the table.
|
580
|
+
#
|
581
|
+
# t.rename_index(:user_id, :account_id)
|
582
|
+
#
|
583
|
+
# See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
|
584
|
+
def rename_index(index_name, new_index_name)
|
585
|
+
@base.rename_index(name, index_name, new_index_name)
|
586
|
+
end
|
587
|
+
|
588
|
+
# Adds timestamps (+created_at+ and +updated_at+) columns to the table.
|
589
|
+
#
|
590
|
+
# t.timestamps(null: false)
|
591
|
+
#
|
592
|
+
# See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
|
593
|
+
def timestamps(options = {})
|
594
|
+
@base.add_timestamps(name, options)
|
370
595
|
end
|
371
596
|
|
372
597
|
# Changes the column's definition according to the new options.
|
373
|
-
#
|
374
|
-
#
|
375
|
-
# t.change(:name, :string, :limit => 80)
|
598
|
+
#
|
599
|
+
# t.change(:name, :string, limit: 80)
|
376
600
|
# t.change(:description, :text)
|
601
|
+
#
|
602
|
+
# See TableDefinition#column for details of the options you can use.
|
377
603
|
def change(column_name, type, options = {})
|
378
|
-
@base.change_column(
|
604
|
+
@base.change_column(name, column_name, type, options)
|
379
605
|
end
|
380
606
|
|
381
|
-
# Sets a new default value for a column.
|
382
|
-
#
|
607
|
+
# Sets a new default value for a column.
|
608
|
+
#
|
383
609
|
# t.change_default(:qualification, 'new')
|
384
610
|
# t.change_default(:authorized, 1)
|
385
|
-
|
386
|
-
|
611
|
+
# t.change_default(:status, from: nil, to: "draft")
|
612
|
+
#
|
613
|
+
# See {connection.change_column_default}[rdoc-ref:SchemaStatements#change_column_default]
|
614
|
+
def change_default(column_name, default_or_changes)
|
615
|
+
@base.change_column_default(name, column_name, default_or_changes)
|
387
616
|
end
|
388
617
|
|
389
618
|
# Removes the column(s) from the table definition.
|
390
|
-
#
|
619
|
+
#
|
391
620
|
# t.remove(:qualification)
|
392
621
|
# t.remove(:qualification, :experience)
|
622
|
+
#
|
623
|
+
# See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
|
393
624
|
def remove(*column_names)
|
394
|
-
@base.
|
625
|
+
@base.remove_columns(name, *column_names)
|
395
626
|
end
|
396
627
|
|
397
628
|
# Removes the given index from the table.
|
398
629
|
#
|
399
|
-
#
|
400
|
-
#
|
401
|
-
# t.remove_index :
|
402
|
-
#
|
403
|
-
#
|
404
|
-
# ====== Remove the index named index_table_name_on_branch_id_and_party_id in the table_name table
|
405
|
-
# t.remove_index :column => [:branch_id, :party_id]
|
406
|
-
# ====== Remove the index named by_branch_party in the table_name table
|
407
|
-
# t.remove_index :name => :by_branch_party
|
630
|
+
# t.remove_index(:branch_id)
|
631
|
+
# t.remove_index(column: [:branch_id, :party_id])
|
632
|
+
# t.remove_index(name: :by_branch_party)
|
633
|
+
#
|
634
|
+
# See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
|
408
635
|
def remove_index(options = {})
|
409
|
-
@base.remove_index(
|
636
|
+
@base.remove_index(name, options)
|
410
637
|
end
|
411
638
|
|
412
639
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
|
413
|
-
#
|
640
|
+
#
|
414
641
|
# t.remove_timestamps
|
415
|
-
|
416
|
-
|
642
|
+
#
|
643
|
+
# See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
|
644
|
+
def remove_timestamps(options = {})
|
645
|
+
@base.remove_timestamps(name, options)
|
417
646
|
end
|
418
647
|
|
419
648
|
# Renames a column.
|
420
|
-
#
|
649
|
+
#
|
421
650
|
# t.rename(:description, :name)
|
651
|
+
#
|
652
|
+
# See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
|
422
653
|
def rename(column_name, new_column_name)
|
423
|
-
@base.rename_column(
|
424
|
-
end
|
425
|
-
|
426
|
-
# Adds a reference.
|
427
|
-
#
|
428
|
-
#
|
429
|
-
# t.
|
430
|
-
#
|
431
|
-
#
|
432
|
-
def references(*args)
|
433
|
-
|
434
|
-
|
435
|
-
args.each do |col|
|
436
|
-
@base.add_column(@table_name, "#{col}_id", :integer, options)
|
437
|
-
@base.add_column(@table_name, "#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
|
654
|
+
@base.rename_column(name, column_name, new_column_name)
|
655
|
+
end
|
656
|
+
|
657
|
+
# Adds a reference.
|
658
|
+
#
|
659
|
+
# t.references(:user)
|
660
|
+
# t.belongs_to(:supplier, foreign_key: true)
|
661
|
+
#
|
662
|
+
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
663
|
+
def references(*args, **options)
|
664
|
+
args.each do |ref_name|
|
665
|
+
@base.add_reference(name, ref_name, options)
|
438
666
|
end
|
439
667
|
end
|
440
668
|
alias :belongs_to :references
|
441
669
|
|
442
670
|
# Removes a reference. Optionally removes a +type+ column.
|
443
|
-
#
|
444
|
-
#
|
445
|
-
# t.
|
446
|
-
#
|
447
|
-
#
|
448
|
-
def remove_references(*args)
|
449
|
-
|
450
|
-
|
451
|
-
args.each do |col|
|
452
|
-
@base.remove_column(@table_name, "#{col}_id")
|
453
|
-
@base.remove_column(@table_name, "#{col}_type") unless polymorphic.nil?
|
671
|
+
#
|
672
|
+
# t.remove_references(:user)
|
673
|
+
# t.remove_belongs_to(:supplier, polymorphic: true)
|
674
|
+
#
|
675
|
+
# See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
|
676
|
+
def remove_references(*args, **options)
|
677
|
+
args.each do |ref_name|
|
678
|
+
@base.remove_reference(name, ref_name, options)
|
454
679
|
end
|
455
680
|
end
|
456
|
-
alias :remove_belongs_to
|
681
|
+
alias :remove_belongs_to :remove_references
|
457
682
|
|
458
|
-
# Adds a
|
459
|
-
#
|
460
|
-
# t.
|
461
|
-
# t.
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
column_names = args # column_names = args
|
467
|
-
type = :'#{column_type}' # type = :string
|
468
|
-
column_names.each do |name| # column_names.each do |name|
|
469
|
-
column = ColumnDefinition.new(@base, name.to_s, type) # column = ColumnDefinition.new(@base, name, type)
|
470
|
-
if options[:limit] # if options[:limit]
|
471
|
-
column.limit = options[:limit] # column.limit = options[:limit]
|
472
|
-
elsif native[type].is_a?(Hash) # elsif native[type].is_a?(Hash)
|
473
|
-
column.limit = native[type][:limit] # column.limit = native[type][:limit]
|
474
|
-
end # end
|
475
|
-
column.precision = options[:precision] # column.precision = options[:precision]
|
476
|
-
column.scale = options[:scale] # column.scale = options[:scale]
|
477
|
-
column.default = options[:default] # column.default = options[:default]
|
478
|
-
column.null = options[:null] # column.null = options[:null]
|
479
|
-
@base.add_column(@table_name, name, column.sql_type, options) # @base.add_column(@table_name, name, column.sql_type, options)
|
480
|
-
end # end
|
481
|
-
end # end
|
482
|
-
EOV
|
683
|
+
# Adds a foreign key to the table using a supplied table name.
|
684
|
+
#
|
685
|
+
# t.foreign_key(:authors)
|
686
|
+
# t.foreign_key(:authors, column: :author_id, primary_key: "id")
|
687
|
+
#
|
688
|
+
# See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
|
689
|
+
def foreign_key(*args)
|
690
|
+
@base.add_foreign_key(name, *args)
|
483
691
|
end
|
484
692
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
693
|
+
# Removes the given foreign key from the table.
|
694
|
+
#
|
695
|
+
# t.remove_foreign_key(:authors)
|
696
|
+
# t.remove_foreign_key(column: :author_id)
|
697
|
+
#
|
698
|
+
# See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
|
699
|
+
def remove_foreign_key(*args)
|
700
|
+
@base.remove_foreign_key(name, *args)
|
701
|
+
end
|
490
702
|
|
703
|
+
# Checks to see if a foreign key exists.
|
704
|
+
#
|
705
|
+
# t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
|
706
|
+
#
|
707
|
+
# See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
|
708
|
+
def foreign_key_exists?(*args)
|
709
|
+
@base.foreign_key_exists?(name, *args)
|
710
|
+
end
|
711
|
+
end
|
491
712
|
end
|
492
713
|
end
|