activerecord 4.2.11.2 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +613 -1638
- data/MIT-LICENSE +4 -2
- data/README.rdoc +13 -12
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record.rb +41 -22
- data/lib/active_record/aggregations.rb +267 -251
- data/lib/active_record/association_relation.rb +11 -6
- data/lib/active_record/associations.rb +1737 -1597
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +125 -58
- data/lib/active_record/associations/association_scope.rb +103 -132
- data/lib/active_record/associations/belongs_to_association.rb +65 -60
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +27 -40
- data/lib/active_record/associations/builder/belongs_to.rb +69 -55
- data/lib/active_record/associations/builder/collection_association.rb +10 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
- data/lib/active_record/associations/builder/has_many.rb +8 -4
- data/lib/active_record/associations/builder/has_one.rb +46 -5
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +131 -287
- data/lib/active_record/associations/collection_proxy.rb +241 -146
- data/lib/active_record/associations/foreign_association.rb +10 -1
- data/lib/active_record/associations/has_many_association.rb +34 -97
- data/lib/active_record/associations/has_many_through_association.rb +60 -87
- data/lib/active_record/associations/has_one_association.rb +61 -49
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +137 -167
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -86
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/preloader.rb +90 -92
- data/lib/active_record/associations/preloader/association.rb +90 -123
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +38 -18
- data/lib/active_record/attribute_assignment.rb +56 -183
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods.rb +120 -135
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
- data/lib/active_record/attribute_methods/dirty.rb +174 -144
- data/lib/active_record/attribute_methods/primary_key.rb +91 -83
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -76
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
- data/lib/active_record/attribute_methods/write.rb +32 -54
- data/lib/active_record/attributes.rb +214 -82
- data/lib/active_record/autosave_association.rb +91 -37
- data/lib/active_record/base.rb +57 -45
- data/lib/active_record/callbacks.rb +100 -74
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -296
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -115
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -243
- data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
- data/lib/active_record/connection_adapters/abstract_adapter.rb +460 -204
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +510 -635
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -180
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -114
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +10 -5
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +551 -356
- data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -345
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +176 -41
- data/lib/active_record/core.rb +251 -231
- data/lib/active_record/counter_cache.rb +67 -49
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +163 -86
- data/lib/active_record/errors.rb +188 -53
- data/lib/active_record/explain.rb +23 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +228 -499
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +158 -112
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +123 -29
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +21 -3
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +87 -96
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +76 -33
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +621 -303
- data/lib/active_record/migration/command_recorder.rb +177 -90
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/model_schema.rb +312 -112
- data/lib/active_record/nested_attributes.rb +264 -222
- data/lib/active_record/no_touching.rb +14 -1
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +557 -125
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +43 -29
- data/lib/active_record/railtie.rb +143 -44
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +328 -185
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +428 -279
- data/lib/active_record/relation.rb +518 -341
- data/lib/active_record/relation/batches.rb +207 -55
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/calculations.rb +267 -253
- data/lib/active_record/relation/delegation.rb +70 -80
- data/lib/active_record/relation/finder_methods.rb +277 -241
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +78 -87
- data/lib/active_record/relation/predicate_builder.rb +114 -119
- data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +575 -394
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -13
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/result.rb +79 -42
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +144 -121
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +112 -93
- data/lib/active_record/schema_migration.rb +24 -17
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/scoping/default.rb +101 -85
- data/lib/active_record/scoping/named.rb +86 -33
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +73 -36
- data/lib/active_record/store.rb +127 -42
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +75 -0
- data/lib/active_record/tasks/database_tasks.rb +307 -100
- data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
- data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +86 -40
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +216 -150
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +78 -23
- data/lib/active_record/type/adapter_specific_registry.rb +129 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +24 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +42 -55
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +51 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration.rb +31 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +164 -59
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,68 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module AttributeMethods
|
3
5
|
module TimeZoneConversion
|
4
6
|
class TimeZoneConverter < DelegateClass(Type::Value) # :nodoc:
|
5
|
-
|
6
|
-
|
7
|
-
def type_cast_from_database(value)
|
7
|
+
def deserialize(value)
|
8
8
|
convert_time_to_time_zone(super)
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
if value.
|
13
|
-
|
11
|
+
def cast(value)
|
12
|
+
return if value.nil?
|
13
|
+
|
14
|
+
if value.is_a?(Hash)
|
15
|
+
set_time_zone_without_conversion(super)
|
14
16
|
elsif value.respond_to?(:in_time_zone)
|
15
17
|
begin
|
16
|
-
value
|
18
|
+
super(user_input_in_time_zone(value)) || super
|
17
19
|
rescue ArgumentError
|
18
20
|
nil
|
19
21
|
end
|
22
|
+
else
|
23
|
+
map_avoiding_infinite_recursion(super) { |v| cast(v) }
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
private
|
28
|
+
|
29
|
+
def convert_time_to_time_zone(value)
|
30
|
+
return if value.nil?
|
31
|
+
|
32
|
+
if value.acts_like?(:time)
|
33
|
+
value.in_time_zone
|
34
|
+
elsif value.is_a?(::Float)
|
35
|
+
value
|
36
|
+
else
|
37
|
+
map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def set_time_zone_without_conversion(value)
|
42
|
+
::Time.zone.local_to_utc(value).try(:in_time_zone) if value
|
43
|
+
end
|
44
|
+
|
45
|
+
def map_avoiding_infinite_recursion(value)
|
46
|
+
map(value) do |v|
|
47
|
+
if value.equal?(v)
|
48
|
+
nil
|
49
|
+
else
|
50
|
+
yield(v)
|
51
|
+
end
|
52
|
+
end
|
30
53
|
end
|
31
|
-
end
|
32
54
|
end
|
33
55
|
|
34
56
|
extend ActiveSupport::Concern
|
35
57
|
|
36
58
|
included do
|
37
|
-
mattr_accessor :time_zone_aware_attributes, instance_writer: false
|
38
|
-
self.time_zone_aware_attributes = false
|
59
|
+
mattr_accessor :time_zone_aware_attributes, instance_writer: false, default: false
|
39
60
|
|
40
|
-
class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false
|
41
|
-
|
61
|
+
class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false, default: []
|
62
|
+
class_attribute :time_zone_aware_types, instance_writer: false, default: [ :datetime, :time ]
|
42
63
|
end
|
43
64
|
|
44
|
-
module ClassMethods
|
65
|
+
module ClassMethods # :nodoc:
|
45
66
|
private
|
46
67
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
68
|
+
def inherited(subclass)
|
69
|
+
super
|
70
|
+
# We need to apply this decorator here, rather than on module inclusion. The closure
|
71
|
+
# created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the
|
72
|
+
# sub class being decorated. As such, changes to `time_zone_aware_attributes`, or
|
73
|
+
# `skip_time_zone_conversion_for_attributes` would not be picked up.
|
74
|
+
subclass.class_eval do
|
75
|
+
matcher = ->(name, type) { create_time_zone_conversion_attribute?(name, type) }
|
76
|
+
decorate_matching_attribute_types(matcher, "_time_zone_conversion") do |type|
|
77
|
+
TimeZoneConverter.new(type)
|
78
|
+
end
|
56
79
|
end
|
57
80
|
end
|
58
|
-
super
|
59
|
-
end
|
60
81
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
82
|
+
def create_time_zone_conversion_attribute?(name, cast_type)
|
83
|
+
enabled_for_column = time_zone_aware_attributes &&
|
84
|
+
!skip_time_zone_conversion_for_attributes.include?(name.to_sym)
|
85
|
+
|
86
|
+
enabled_for_column && time_zone_aware_types.include?(cast_type.type)
|
87
|
+
end
|
66
88
|
end
|
67
89
|
end
|
68
90
|
end
|
@@ -1,83 +1,61 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module AttributeMethods
|
5
5
|
module Write
|
6
|
-
WriterMethodCache = Class.new(AttributeMethodCache) {
|
7
|
-
private
|
8
|
-
|
9
|
-
def method_body(method_name, const_name)
|
10
|
-
<<-EOMETHOD
|
11
|
-
def #{method_name}(value)
|
12
|
-
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{const_name}
|
13
|
-
write_attribute(name, value)
|
14
|
-
end
|
15
|
-
EOMETHOD
|
16
|
-
end
|
17
|
-
}.new
|
18
|
-
|
19
6
|
extend ActiveSupport::Concern
|
20
7
|
|
21
8
|
included do
|
22
9
|
attribute_method_suffix "="
|
23
10
|
end
|
24
11
|
|
25
|
-
module ClassMethods
|
26
|
-
|
12
|
+
module ClassMethods # :nodoc:
|
13
|
+
private
|
27
14
|
|
28
|
-
if Module.methods_transplantable?
|
29
|
-
def define_method_attribute=(name)
|
30
|
-
method = WriterMethodCache[name]
|
31
|
-
generated_attribute_methods.module_eval {
|
32
|
-
define_method "#{name}=", method
|
33
|
-
}
|
34
|
-
end
|
35
|
-
else
|
36
15
|
def define_method_attribute=(name)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
STR
|
16
|
+
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
17
|
+
generated_attribute_methods, name, writer: true,
|
18
|
+
) do |temp_method_name, attr_name_expr|
|
19
|
+
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
20
|
+
def #{temp_method_name}(value)
|
21
|
+
name = #{attr_name_expr}
|
22
|
+
_write_attribute(name, value)
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
end
|
48
26
|
end
|
49
|
-
end
|
50
27
|
end
|
51
28
|
|
52
29
|
# Updates the attribute identified by <tt>attr_name</tt> with the
|
53
30
|
# specified +value+. Empty strings for Integer and Float columns are
|
54
31
|
# turned into +nil+.
|
55
32
|
def write_attribute(attr_name, value)
|
56
|
-
|
57
|
-
|
33
|
+
name = attr_name.to_s
|
34
|
+
name = self.class.attribute_aliases[name] || name
|
58
35
|
|
59
|
-
|
60
|
-
|
36
|
+
name = @primary_key if name == "id" && @primary_key
|
37
|
+
_write_attribute(name, value)
|
61
38
|
end
|
62
39
|
|
63
|
-
|
64
|
-
#
|
65
|
-
def
|
66
|
-
|
40
|
+
# This method exists to avoid the expensive primary_key check internally, without
|
41
|
+
# breaking compatibility with the write_attribute API
|
42
|
+
def _write_attribute(attr_name, value) # :nodoc:
|
43
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
44
|
+
@attributes.write_from_user(attr_name.to_s, value)
|
45
|
+
value
|
67
46
|
end
|
68
47
|
|
69
|
-
|
70
|
-
attr_name
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
@attributes.write_from_user(attr_name, value)
|
75
|
-
else
|
76
|
-
@attributes.write_cast_value(attr_name, value)
|
48
|
+
private
|
49
|
+
def write_attribute_without_type_cast(attr_name, value)
|
50
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
51
|
+
@attributes.write_cast_value(attr_name.to_s, value)
|
52
|
+
value
|
77
53
|
end
|
78
54
|
|
79
|
-
|
80
|
-
|
55
|
+
# Dispatch target for <tt>*=</tt> attribute methods.
|
56
|
+
def attribute=(attribute_name, value)
|
57
|
+
_write_attribute(attribute_name, value)
|
58
|
+
end
|
81
59
|
end
|
82
60
|
end
|
83
61
|
end
|
@@ -1,33 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model/attribute/user_provided_default"
|
4
|
+
|
1
5
|
module ActiveRecord
|
2
|
-
|
6
|
+
# See ActiveRecord::Attributes::ClassMethods for documentation
|
7
|
+
module Attributes
|
3
8
|
extend ActiveSupport::Concern
|
4
9
|
|
5
|
-
Type = ActiveRecord::Type
|
6
|
-
|
7
10
|
included do
|
8
|
-
class_attribute :
|
9
|
-
class_attribute :user_provided_defaults, instance_accessor: false # :internal:
|
10
|
-
self.user_provided_columns = {}
|
11
|
-
self.user_provided_defaults = {}
|
12
|
-
|
13
|
-
delegate :persistable_attribute_names, to: :class
|
11
|
+
class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false, default: {} # :internal:
|
14
12
|
end
|
15
13
|
|
16
|
-
module ClassMethods
|
17
|
-
# Defines
|
18
|
-
#
|
19
|
-
#
|
14
|
+
module ClassMethods
|
15
|
+
# Defines an attribute with a type on this model. It will override the
|
16
|
+
# type of existing attributes if needed. This allows control over how
|
17
|
+
# values are converted to and from SQL when assigned to a model. It also
|
18
|
+
# changes the behavior of values passed to
|
19
|
+
# {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where]. This will let you use
|
20
|
+
# your domain objects across much of Active Record, without having to
|
21
|
+
# rely on implementation details or monkey patching.
|
20
22
|
#
|
21
|
-
# +name+ The name of the methods to define attribute methods for, and the
|
22
|
-
# this will persist to.
|
23
|
+
# +name+ The name of the methods to define attribute methods for, and the
|
24
|
+
# column which this will persist to.
|
23
25
|
#
|
24
|
-
# +cast_type+ A
|
25
|
-
# See the examples
|
26
|
+
# +cast_type+ A symbol such as +:string+ or +:integer+, or a type object
|
27
|
+
# to be used for this attribute. See the examples below for more
|
28
|
+
# information about providing custom type objects.
|
26
29
|
#
|
27
30
|
# ==== Options
|
28
|
-
# The options hash accepts the following options:
|
29
31
|
#
|
30
|
-
#
|
32
|
+
# The following options are accepted:
|
33
|
+
#
|
34
|
+
# +default+ The default value to use when no value is provided. If this option
|
35
|
+
# is not passed, the previous default value (if any) will be used.
|
36
|
+
# Otherwise, the default will be +nil+.
|
37
|
+
#
|
38
|
+
# +array+ (PostgreSQL only) specifies that the type should be an array (see the
|
39
|
+
# examples below).
|
40
|
+
#
|
41
|
+
# +range+ (PostgreSQL only) specifies that the type should be a range (see the
|
42
|
+
# examples below).
|
43
|
+
#
|
44
|
+
# When using a symbol for +cast_type+, extra options are forwarded to the
|
45
|
+
# constructor of the type object.
|
31
46
|
#
|
32
47
|
# ==== Examples
|
33
48
|
#
|
@@ -45,103 +60,220 @@ module ActiveRecord
|
|
45
60
|
# store_listing = StoreListing.new(price_in_cents: '10.1')
|
46
61
|
#
|
47
62
|
# # before
|
48
|
-
# store_listing.price_in_cents # => BigDecimal
|
63
|
+
# store_listing.price_in_cents # => BigDecimal(10.1)
|
49
64
|
#
|
50
65
|
# class StoreListing < ActiveRecord::Base
|
51
|
-
# attribute :price_in_cents,
|
66
|
+
# attribute :price_in_cents, :integer
|
52
67
|
# end
|
53
68
|
#
|
54
69
|
# # after
|
55
70
|
# store_listing.price_in_cents # => 10
|
56
71
|
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
72
|
+
# A default can also be provided.
|
73
|
+
#
|
74
|
+
# # db/schema.rb
|
75
|
+
# create_table :store_listings, force: true do |t|
|
76
|
+
# t.string :my_string, default: "original default"
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# StoreListing.new.my_string # => "original default"
|
80
|
+
#
|
81
|
+
# # app/models/store_listing.rb
|
82
|
+
# class StoreListing < ActiveRecord::Base
|
83
|
+
# attribute :my_string, :string, default: "new default"
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# StoreListing.new.my_string # => "new default"
|
87
|
+
#
|
88
|
+
# class Product < ActiveRecord::Base
|
89
|
+
# attribute :my_default_proc, :datetime, default: -> { Time.now }
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# Product.new.my_default_proc # => 2015-05-30 11:04:48 -0600
|
93
|
+
# sleep 1
|
94
|
+
# Product.new.my_default_proc # => 2015-05-30 11:04:49 -0600
|
95
|
+
#
|
96
|
+
# \Attributes do not need to be backed by a database column.
|
97
|
+
#
|
98
|
+
# # app/models/my_model.rb
|
99
|
+
# class MyModel < ActiveRecord::Base
|
100
|
+
# attribute :my_string, :string
|
101
|
+
# attribute :my_int_array, :integer, array: true
|
102
|
+
# attribute :my_float_range, :float, range: true
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# model = MyModel.new(
|
106
|
+
# my_string: "string",
|
107
|
+
# my_int_array: ["1", "2", "3"],
|
108
|
+
# my_float_range: "[1,3.5]",
|
109
|
+
# )
|
110
|
+
# model.attributes
|
111
|
+
# # =>
|
112
|
+
# {
|
113
|
+
# my_string: "string",
|
114
|
+
# my_int_array: [1, 2, 3],
|
115
|
+
# my_float_range: 1.0..3.5
|
116
|
+
# }
|
117
|
+
#
|
118
|
+
# Passing options to the type constructor
|
119
|
+
#
|
120
|
+
# # app/models/my_model.rb
|
121
|
+
# class MyModel < ActiveRecord::Base
|
122
|
+
# attribute :small_int, :integer, limit: 2
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
# MyModel.create(small_int: 65537)
|
126
|
+
# # => Error: 65537 is out of range for the limit of two bytes
|
127
|
+
#
|
128
|
+
# ==== Creating Custom Types
|
129
|
+
#
|
130
|
+
# Users may also define their own custom types, as long as they respond
|
131
|
+
# to the methods defined on the value type. The method +deserialize+ or
|
132
|
+
# +cast+ will be called on your type object, with raw input from the
|
133
|
+
# database or from your controllers. See ActiveModel::Type::Value for the
|
134
|
+
# expected API. It is recommended that your type objects inherit from an
|
135
|
+
# existing type, or from ActiveRecord::Type::Value
|
62
136
|
#
|
63
137
|
# class MoneyType < ActiveRecord::Type::Integer
|
64
|
-
# def
|
65
|
-
# if value.include?('$')
|
138
|
+
# def cast(value)
|
139
|
+
# if !value.kind_of?(Numeric) && value.include?('$')
|
66
140
|
# price_in_dollars = value.gsub(/\$/, '').to_f
|
67
|
-
# price_in_dollars * 100
|
141
|
+
# super(price_in_dollars * 100)
|
68
142
|
# else
|
69
|
-
#
|
143
|
+
# super
|
70
144
|
# end
|
71
145
|
# end
|
72
146
|
# end
|
73
147
|
#
|
148
|
+
# # config/initializers/types.rb
|
149
|
+
# ActiveRecord::Type.register(:money, MoneyType)
|
150
|
+
#
|
151
|
+
# # app/models/store_listing.rb
|
74
152
|
# class StoreListing < ActiveRecord::Base
|
75
|
-
# attribute :price_in_cents,
|
153
|
+
# attribute :price_in_cents, :money
|
76
154
|
# end
|
77
155
|
#
|
78
156
|
# store_listing = StoreListing.new(price_in_cents: '$10.00')
|
79
157
|
# store_listing.price_in_cents # => 1000
|
80
|
-
|
158
|
+
#
|
159
|
+
# For more details on creating custom types, see the documentation for
|
160
|
+
# ActiveModel::Type::Value. For more details on registering your types
|
161
|
+
# to be referenced by a symbol, see ActiveRecord::Type.register. You can
|
162
|
+
# also pass a type object directly, in place of a symbol.
|
163
|
+
#
|
164
|
+
# ==== \Querying
|
165
|
+
#
|
166
|
+
# When {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where] is called, it will
|
167
|
+
# use the type defined by the model class to convert the value to SQL,
|
168
|
+
# calling +serialize+ on your type object. For example:
|
169
|
+
#
|
170
|
+
# class Money < Struct.new(:amount, :currency)
|
171
|
+
# end
|
172
|
+
#
|
173
|
+
# class MoneyType < Type::Value
|
174
|
+
# def initialize(currency_converter:)
|
175
|
+
# @currency_converter = currency_converter
|
176
|
+
# end
|
177
|
+
#
|
178
|
+
# # value will be the result of +deserialize+ or
|
179
|
+
# # +cast+. Assumed to be an instance of +Money+ in
|
180
|
+
# # this case.
|
181
|
+
# def serialize(value)
|
182
|
+
# value_in_bitcoins = @currency_converter.convert_to_bitcoins(value)
|
183
|
+
# value_in_bitcoins.amount
|
184
|
+
# end
|
185
|
+
# end
|
186
|
+
#
|
187
|
+
# # config/initializers/types.rb
|
188
|
+
# ActiveRecord::Type.register(:money, MoneyType)
|
189
|
+
#
|
190
|
+
# # app/models/product.rb
|
191
|
+
# class Product < ActiveRecord::Base
|
192
|
+
# currency_converter = ConversionRatesFromTheInternet.new
|
193
|
+
# attribute :price_in_bitcoins, :money, currency_converter: currency_converter
|
194
|
+
# end
|
195
|
+
#
|
196
|
+
# Product.where(price_in_bitcoins: Money.new(5, "USD"))
|
197
|
+
# # => SELECT * FROM products WHERE price_in_bitcoins = 0.02230
|
198
|
+
#
|
199
|
+
# Product.where(price_in_bitcoins: Money.new(5, "GBP"))
|
200
|
+
# # => SELECT * FROM products WHERE price_in_bitcoins = 0.03412
|
201
|
+
#
|
202
|
+
# ==== Dirty Tracking
|
203
|
+
#
|
204
|
+
# The type of an attribute is given the opportunity to change how dirty
|
205
|
+
# tracking is performed. The methods +changed?+ and +changed_in_place?+
|
206
|
+
# will be called from ActiveModel::Dirty. See the documentation for those
|
207
|
+
# methods in ActiveModel::Type::Value for more details.
|
208
|
+
def attribute(name, cast_type = Type::Value.new, **options)
|
81
209
|
name = name.to_s
|
82
|
-
|
83
|
-
# Assign a new hash to ensure that subclasses do not share a hash
|
84
|
-
self.user_provided_columns = user_provided_columns.merge(name => cast_type)
|
210
|
+
reload_schema_from_cache
|
85
211
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
# Returns an array of column objects for the table associated with this class.
|
92
|
-
def columns
|
93
|
-
@columns ||= add_user_provided_columns(connection.schema_cache.columns(table_name))
|
212
|
+
self.attributes_to_define_after_schema_loads =
|
213
|
+
attributes_to_define_after_schema_loads.merge(
|
214
|
+
name => [cast_type, options]
|
215
|
+
)
|
94
216
|
end
|
95
217
|
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
218
|
+
# This is the low level API which sits beneath +attribute+. It only
|
219
|
+
# accepts type objects, and will do its work immediately instead of
|
220
|
+
# waiting for the schema to load. Automatic schema detection and
|
221
|
+
# ClassMethods#attribute both call this under the hood. While this method
|
222
|
+
# is provided so it can be used by plugin authors, application code
|
223
|
+
# should probably use ClassMethods#attribute.
|
224
|
+
#
|
225
|
+
# +name+ The name of the attribute being defined. Expected to be a +String+.
|
226
|
+
#
|
227
|
+
# +cast_type+ The type object to use for this attribute.
|
228
|
+
#
|
229
|
+
# +default+ The default value to use when no value is provided. If this option
|
230
|
+
# is not passed, the previous default value (if any) will be used.
|
231
|
+
# Otherwise, the default will be +nil+. A proc can also be passed, and
|
232
|
+
# will be called once each time a new value is needed.
|
233
|
+
#
|
234
|
+
# +user_provided_default+ Whether the default value should be cast using
|
235
|
+
# +cast+ or +deserialize+.
|
236
|
+
def define_attribute(
|
237
|
+
name,
|
238
|
+
cast_type,
|
239
|
+
default: NO_DEFAULT_PROVIDED,
|
240
|
+
user_provided_default: true
|
241
|
+
)
|
242
|
+
attribute_types[name] = cast_type
|
243
|
+
define_default_attribute(name, default, cast_type, from_user: user_provided_default)
|
103
244
|
end
|
104
245
|
|
105
|
-
def
|
246
|
+
def load_schema! # :nodoc:
|
106
247
|
super
|
107
|
-
|
248
|
+
attributes_to_define_after_schema_loads.each do |name, (type, options)|
|
249
|
+
if type.is_a?(Symbol)
|
250
|
+
type = ActiveRecord::Type.lookup(type, **options.except(:default))
|
251
|
+
end
|
252
|
+
|
253
|
+
define_attribute(name, type, **options.slice(:default))
|
254
|
+
end
|
108
255
|
end
|
109
256
|
|
110
257
|
private
|
111
258
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
259
|
+
NO_DEFAULT_PROVIDED = Object.new # :nodoc:
|
260
|
+
private_constant :NO_DEFAULT_PROVIDED
|
261
|
+
|
262
|
+
def define_default_attribute(name, value, type, from_user:)
|
263
|
+
if value == NO_DEFAULT_PROVIDED
|
264
|
+
default_attribute = _default_attributes[name].with_type(type)
|
265
|
+
elsif from_user
|
266
|
+
default_attribute = ActiveModel::Attribute::UserProvidedDefault.new(
|
267
|
+
name,
|
268
|
+
value,
|
269
|
+
type,
|
270
|
+
_default_attributes.fetch(name.to_s) { nil },
|
271
|
+
)
|
117
272
|
else
|
118
|
-
|
273
|
+
default_attribute = ActiveModel::Attribute.from_database(name, value, type)
|
119
274
|
end
|
275
|
+
_default_attributes[name] = default_attribute
|
120
276
|
end
|
121
|
-
|
122
|
-
existing_column_names = existing_columns.map(&:name)
|
123
|
-
new_columns = user_provided_columns.except(*existing_column_names).map do |(name, type)|
|
124
|
-
connection.new_column(name, nil, type)
|
125
|
-
end
|
126
|
-
|
127
|
-
existing_columns + new_columns
|
128
|
-
end
|
129
|
-
|
130
|
-
def clear_caches_calculated_from_columns
|
131
|
-
@attributes_builder = nil
|
132
|
-
@column_names = nil
|
133
|
-
@column_types = nil
|
134
|
-
@columns = nil
|
135
|
-
@columns_hash = nil
|
136
|
-
@content_columns = nil
|
137
|
-
@default_attributes = nil
|
138
|
-
@persistable_attribute_names = nil
|
139
|
-
@attribute_names = nil
|
140
|
-
end
|
141
|
-
|
142
|
-
def raw_default_values
|
143
|
-
super.merge(user_provided_defaults)
|
144
|
-
end
|
145
277
|
end
|
146
278
|
end
|
147
279
|
end
|