activerecord 4.2.11.1 → 6.0.3.5
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 +721 -1522
- data/MIT-LICENSE +4 -2
- data/README.rdoc +14 -13
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +266 -251
- data/lib/active_record/association_relation.rb +20 -13
- data/lib/active_record/associations/alias_tracker.rb +29 -36
- data/lib/active_record/associations/association.rb +128 -57
- 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 +50 -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 +136 -288
- data/lib/active_record/associations/collection_proxy.rb +241 -147
- data/lib/active_record/associations/foreign_association.rb +10 -1
- data/lib/active_record/associations/has_many_association.rb +34 -98
- 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/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/join_dependency.rb +149 -166
- 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/preloader.rb +90 -93
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +38 -18
- data/lib/active_record/associations.rb +1737 -1597
- data/lib/active_record/attribute_assignment.rb +57 -185
- data/lib/active_record/attribute_decorators.rb +39 -17
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
- data/lib/active_record/attribute_methods/dirty.rb +174 -144
- data/lib/active_record/attribute_methods/primary_key.rb +90 -84
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -77
- data/lib/active_record/attribute_methods/serialization.rb +40 -21
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +57 -37
- data/lib/active_record/attribute_methods/write.rb +32 -55
- data/lib/active_record/attribute_methods.rb +120 -135
- data/lib/active_record/attributes.rb +213 -82
- data/lib/active_record/autosave_association.rb +97 -41
- data/lib/active_record/base.rb +57 -45
- data/lib/active_record/callbacks.rb +101 -76
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +23 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +804 -297
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +240 -115
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +83 -24
- 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 -47
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +371 -242
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +694 -256
- data/lib/active_record/connection_adapters/abstract/transaction.rb +190 -83
- data/lib/active_record/connection_adapters/abstract_adapter.rb +473 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +507 -639
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -153
- 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 +196 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +71 -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 -181
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -114
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -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 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
- 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 +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +51 -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 +9 -5
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -296
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -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 +119 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -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 +299 -349
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_handling.rb +167 -41
- data/lib/active_record/core.rb +252 -230
- data/lib/active_record/counter_cache.rb +70 -49
- 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 +78 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -106
- data/lib/active_record/enum.rb +163 -86
- data/lib/active_record/errors.rb +188 -53
- data/lib/active_record/explain.rb +22 -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 +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +227 -501
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +158 -115
- 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 +86 -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/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
- data/lib/active_record/middleware/database_selector.rb +74 -0
- data/lib/active_record/migration/command_recorder.rb +166 -91
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +623 -305
- data/lib/active_record/model_schema.rb +313 -112
- data/lib/active_record/nested_attributes.rb +263 -223
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +557 -126
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +44 -30
- 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 +331 -185
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +430 -281
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +206 -55
- data/lib/active_record/relation/calculations.rb +268 -254
- data/lib/active_record/relation/delegation.rb +75 -84
- data/lib/active_record/relation/finder_methods.rb +285 -241
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +78 -88
- 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/predicate_builder.rb +110 -119
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +603 -397
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -14
- data/lib/active_record/relation/where_clause.rb +189 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/relation.rb +530 -341
- data/lib/active_record/result.rb +79 -43
- 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/default.rb +98 -83
- data/lib/active_record/scoping/named.rb +86 -33
- data/lib/active_record/scoping.rb +45 -27
- 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 +90 -0
- data/lib/active_record/tasks/database_tasks.rb +307 -100
- data/lib/active_record/tasks/mysql_database_tasks.rb +55 -100
- data/lib/active_record/tasks/postgresql_database_tasks.rb +80 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +37 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +225 -0
- data/lib/active_record/timestamp.rb +86 -41
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +223 -157
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +126 -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 -4
- 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 +23 -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 +16 -19
- data/lib/active_record/type/unsigned_integer.rb +9 -8
- data/lib/active_record/type.rb +77 -23
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +12 -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/validations.rb +38 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +42 -22
- 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 +256 -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 +203 -0
- data/lib/arel/visitors/dot.rb +296 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +156 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +158 -0
- data/lib/arel/visitors/oracle12.rb +65 -0
- data/lib/arel/visitors/postgresql.rb +109 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +888 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors/where_sql.rb +22 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +62 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
- data/lib/rails/generators/active_record/migration.rb +30 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +18 -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
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +168 -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/builder.rb +0 -106
- data/lib/active_record/attribute_set.rb +0 -81
- 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/integer.rb +0 -11
- 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,212 +1,84 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model/forbidden_attributes_protection"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module AttributeAssignment
|
5
|
-
|
6
|
-
include ActiveModel::ForbiddenAttributesProtection
|
7
|
-
|
8
|
-
# Allows you to set all the attributes by passing in a hash of attributes with
|
9
|
-
# keys matching the attribute names (which again matches the column names).
|
10
|
-
#
|
11
|
-
# If the passed hash responds to <tt>permitted?</tt> method and the return value
|
12
|
-
# of this method is +false+ an <tt>ActiveModel::ForbiddenAttributesError</tt>
|
13
|
-
# exception is raised.
|
14
|
-
#
|
15
|
-
# cat = Cat.new(name: "Gorby", status: "yawning")
|
16
|
-
# cat.attributes # => { "name" => "Gorby", "status" => "yawning", "created_at" => nil, "updated_at" => nil}
|
17
|
-
# cat.assign_attributes(status: "sleeping")
|
18
|
-
# cat.attributes # => { "name" => "Gorby", "status" => "sleeping", "created_at" => nil, "updated_at" => nil }
|
19
|
-
#
|
20
|
-
# New attributes will be persisted in the database when the object is saved.
|
21
|
-
#
|
22
|
-
# Aliased to <tt>attributes=</tt>.
|
23
|
-
def assign_attributes(new_attributes)
|
24
|
-
if !new_attributes.respond_to?(:stringify_keys)
|
25
|
-
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
|
26
|
-
end
|
27
|
-
return if new_attributes.blank?
|
28
|
-
|
29
|
-
attributes = new_attributes.stringify_keys
|
30
|
-
multi_parameter_attributes = []
|
31
|
-
nested_parameter_attributes = []
|
32
|
-
|
33
|
-
attributes = sanitize_for_mass_assignment(attributes)
|
34
|
-
|
35
|
-
attributes.each do |k, v|
|
36
|
-
if k.include?("(")
|
37
|
-
multi_parameter_attributes << [ k, v ]
|
38
|
-
elsif v.is_a?(Hash)
|
39
|
-
nested_parameter_attributes << [ k, v ]
|
40
|
-
else
|
41
|
-
_assign_attribute(k, v)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
|
46
|
-
assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
|
47
|
-
end
|
48
|
-
|
49
|
-
alias attributes= assign_attributes
|
7
|
+
include ActiveModel::AttributeAssignment
|
50
8
|
|
51
9
|
private
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
# Assign any deferred nested attributes after the base attributes have been set.
|
64
|
-
def assign_nested_parameter_attributes(pairs)
|
65
|
-
pairs.each { |k, v| _assign_attribute(k, v) }
|
66
|
-
end
|
67
|
-
|
68
|
-
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
|
69
|
-
# by calling new on the column type or aggregation type (through composed_of) object with these parameters.
|
70
|
-
# So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
|
71
|
-
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
72
|
-
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
|
73
|
-
# f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
|
74
|
-
def assign_multiparameter_attributes(pairs)
|
75
|
-
execute_callstack_for_multiparameter_attributes(
|
76
|
-
extract_callstack_for_multiparameter_attributes(pairs)
|
77
|
-
)
|
78
|
-
end
|
79
|
-
|
80
|
-
def execute_callstack_for_multiparameter_attributes(callstack)
|
81
|
-
errors = []
|
82
|
-
callstack.each do |name, values_with_empty_parameters|
|
83
|
-
begin
|
84
|
-
send("#{name}=", MultiparameterAttribute.new(self, name, values_with_empty_parameters).read_value)
|
85
|
-
rescue => ex
|
86
|
-
errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
|
10
|
+
def _assign_attributes(attributes)
|
11
|
+
multi_parameter_attributes = {}
|
12
|
+
nested_parameter_attributes = {}
|
13
|
+
|
14
|
+
attributes.each do |k, v|
|
15
|
+
if k.include?("(")
|
16
|
+
multi_parameter_attributes[k] = attributes.delete(k)
|
17
|
+
elsif v.is_a?(Hash)
|
18
|
+
nested_parameter_attributes[k] = attributes.delete(k)
|
19
|
+
end
|
87
20
|
end
|
88
|
-
|
89
|
-
unless errors.empty?
|
90
|
-
error_descriptions = errors.map { |ex| ex.message }.join(",")
|
91
|
-
raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes [#{error_descriptions}]"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def extract_callstack_for_multiparameter_attributes(pairs)
|
96
|
-
attributes = {}
|
97
|
-
|
98
|
-
pairs.each do |(multiparameter_name, value)|
|
99
|
-
attribute_name = multiparameter_name.split("(").first
|
100
|
-
attributes[attribute_name] ||= {}
|
21
|
+
super(attributes)
|
101
22
|
|
102
|
-
|
103
|
-
|
23
|
+
assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
|
24
|
+
assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
|
104
25
|
end
|
105
26
|
|
106
|
-
attributes
|
107
|
-
|
108
|
-
|
109
|
-
def type_cast_attribute_value(multiparameter_name, value)
|
110
|
-
multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
|
111
|
-
end
|
112
|
-
|
113
|
-
def find_parameter_position(multiparameter_name)
|
114
|
-
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
|
115
|
-
end
|
116
|
-
|
117
|
-
class MultiparameterAttribute #:nodoc:
|
118
|
-
attr_reader :object, :name, :values, :cast_type
|
119
|
-
|
120
|
-
def initialize(object, name, values)
|
121
|
-
@object = object
|
122
|
-
@name = name
|
123
|
-
@values = values
|
27
|
+
# Assign any deferred nested attributes after the base attributes have been set.
|
28
|
+
def assign_nested_parameter_attributes(pairs)
|
29
|
+
pairs.each { |k, v| _assign_attribute(k, v) }
|
124
30
|
end
|
125
31
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
else
|
137
|
-
read_other
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
private
|
142
|
-
|
143
|
-
def instantiate_time_object(set_values)
|
144
|
-
if object.class.send(:create_time_zone_conversion_attribute?, name, cast_type)
|
145
|
-
Time.zone.local(*set_values)
|
146
|
-
else
|
147
|
-
Time.send(object.class.default_timezone, *set_values)
|
148
|
-
end
|
32
|
+
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
|
33
|
+
# by calling new on the column type or aggregation type (through composed_of) object with these parameters.
|
34
|
+
# So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
|
35
|
+
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
36
|
+
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
|
37
|
+
# f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
|
38
|
+
def assign_multiparameter_attributes(pairs)
|
39
|
+
execute_callstack_for_multiparameter_attributes(
|
40
|
+
extract_callstack_for_multiparameter_attributes(pairs)
|
41
|
+
)
|
149
42
|
end
|
150
43
|
|
151
|
-
def
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
values
|
44
|
+
def execute_callstack_for_multiparameter_attributes(callstack)
|
45
|
+
errors = []
|
46
|
+
callstack.each do |name, values_with_empty_parameters|
|
47
|
+
if values_with_empty_parameters.each_value.all?(&:nil?)
|
48
|
+
values = nil
|
49
|
+
else
|
50
|
+
values = values_with_empty_parameters
|
158
51
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
# If Date bits were provided but blank, then return nil
|
164
|
-
return if blank_date_parameter?
|
52
|
+
send("#{name}=", values)
|
53
|
+
rescue => ex
|
54
|
+
errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
|
165
55
|
end
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
# If Time bits are not there, then default to 0
|
170
|
-
(3..5).each { |i| set_values[i] = set_values[i].presence || 0 }
|
171
|
-
instantiate_time_object(set_values)
|
172
|
-
end
|
173
|
-
|
174
|
-
def read_date
|
175
|
-
return if blank_date_parameter?
|
176
|
-
set_values = values.values_at(1,2,3)
|
177
|
-
begin
|
178
|
-
Date.new(*set_values)
|
179
|
-
rescue ArgumentError # if Date.new raises an exception on an invalid date
|
180
|
-
instantiate_time_object(set_values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
|
56
|
+
unless errors.empty?
|
57
|
+
error_descriptions = errors.map(&:message).join(",")
|
58
|
+
raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes [#{error_descriptions}]"
|
181
59
|
end
|
182
60
|
end
|
183
61
|
|
184
|
-
def
|
185
|
-
|
186
|
-
positions = (1..max_position)
|
187
|
-
validate_required_parameters!(positions)
|
62
|
+
def extract_callstack_for_multiparameter_attributes(pairs)
|
63
|
+
attributes = {}
|
188
64
|
|
189
|
-
|
190
|
-
|
65
|
+
pairs.each do |(multiparameter_name, value)|
|
66
|
+
attribute_name = multiparameter_name.split("(").first
|
67
|
+
attributes[attribute_name] ||= {}
|
191
68
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
(1..3).any? { |position| values[position].blank? }
|
69
|
+
parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
|
70
|
+
attributes[attribute_name][find_parameter_position(multiparameter_name)] ||= parameter_value
|
71
|
+
end
|
72
|
+
|
73
|
+
attributes
|
198
74
|
end
|
199
75
|
|
200
|
-
|
201
|
-
|
202
|
-
if missing_parameter = positions.detect { |position| !values.key?(position) }
|
203
|
-
raise ArgumentError.new("Missing Parameter - #{name}(#{missing_parameter})")
|
204
|
-
end
|
76
|
+
def type_cast_attribute_value(multiparameter_name, value)
|
77
|
+
multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
|
205
78
|
end
|
206
79
|
|
207
|
-
def
|
208
|
-
[
|
80
|
+
def find_parameter_position(multiparameter_name)
|
81
|
+
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
|
209
82
|
end
|
210
|
-
end
|
211
83
|
end
|
212
84
|
end
|
@@ -1,21 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module AttributeDecorators # :nodoc:
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
|
5
7
|
included do
|
6
|
-
class_attribute :attribute_type_decorations, instance_accessor: false # :internal:
|
7
|
-
self.attribute_type_decorations = TypeDecorator.new
|
8
|
+
class_attribute :attribute_type_decorations, instance_accessor: false, default: TypeDecorator.new # :internal:
|
8
9
|
end
|
9
10
|
|
10
11
|
module ClassMethods # :nodoc:
|
12
|
+
# This method is an internal API used to create class macros such as
|
13
|
+
# +serialize+, and features like time zone aware attributes.
|
14
|
+
#
|
15
|
+
# Used to wrap the type of an attribute in a new type.
|
16
|
+
# When the schema for a model is loaded, attributes with the same name as
|
17
|
+
# +column_name+ will have their type yielded to the given block. The
|
18
|
+
# return value of that block will be used instead.
|
19
|
+
#
|
20
|
+
# Subsequent calls where +column_name+ and +decorator_name+ are the same
|
21
|
+
# will override the previous decorator, not decorate twice. This can be
|
22
|
+
# used to create idempotent class macros like +serialize+
|
11
23
|
def decorate_attribute_type(column_name, decorator_name, &block)
|
12
24
|
matcher = ->(name, _) { name == column_name.to_s }
|
13
25
|
key = "_#{column_name}_#{decorator_name}"
|
14
26
|
decorate_matching_attribute_types(matcher, key, &block)
|
15
27
|
end
|
16
28
|
|
29
|
+
# This method is an internal API used to create higher level features like
|
30
|
+
# time zone aware attributes.
|
31
|
+
#
|
32
|
+
# When the schema for a model is loaded, +matcher+ will be called for each
|
33
|
+
# attribute with its name and type. If the matcher returns a truthy value,
|
34
|
+
# the type will then be yielded to the given block, and the return value
|
35
|
+
# of that block will replace the type.
|
36
|
+
#
|
37
|
+
# Subsequent calls to this method with the same value for +decorator_name+
|
38
|
+
# will replace the previous decorator, not decorate twice. This can be
|
39
|
+
# used to ensure that class macros are idempotent.
|
17
40
|
def decorate_matching_attribute_types(matcher, decorator_name, &block)
|
18
|
-
|
41
|
+
reload_schema_from_cache
|
19
42
|
decorator_name = decorator_name.to_s
|
20
43
|
|
21
44
|
# Create new hashes so we don't modify parent classes
|
@@ -23,13 +46,13 @@ module ActiveRecord
|
|
23
46
|
end
|
24
47
|
|
25
48
|
private
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
49
|
+
def load_schema!
|
50
|
+
super
|
51
|
+
attribute_types.each do |name, type|
|
52
|
+
decorated_type = attribute_type_decorations.apply(name, type)
|
53
|
+
define_attribute(name, decorated_type)
|
54
|
+
end
|
31
55
|
end
|
32
|
-
end
|
33
56
|
end
|
34
57
|
|
35
58
|
class TypeDecorator # :nodoc:
|
@@ -51,16 +74,15 @@ module ActiveRecord
|
|
51
74
|
end
|
52
75
|
|
53
76
|
private
|
77
|
+
def decorators_for(name, type)
|
78
|
+
matching(name, type).map(&:last)
|
79
|
+
end
|
54
80
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
def matching(name, type)
|
60
|
-
@decorations.values.select do |(matcher, _)|
|
61
|
-
matcher.call(name, type)
|
81
|
+
def matching(name, type)
|
82
|
+
@decorations.values.select do |(matcher, _)|
|
83
|
+
matcher.call(name, type)
|
84
|
+
end
|
62
85
|
end
|
63
|
-
end
|
64
86
|
end
|
65
87
|
end
|
66
88
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module AttributeMethods
|
3
5
|
# = Active Record Attribute Methods Before Type Cast
|
4
6
|
#
|
5
|
-
#
|
7
|
+
# ActiveRecord::AttributeMethods::BeforeTypeCast provides a way to
|
6
8
|
# read the value of the attributes before typecasting and deserialization.
|
7
9
|
#
|
8
10
|
# class Task < ActiveRecord::Base
|
@@ -44,6 +46,7 @@ module ActiveRecord
|
|
44
46
|
# task.read_attribute_before_type_cast('completed_on') # => "2012-10-21"
|
45
47
|
# task.read_attribute_before_type_cast(:completed_on) # => "2012-10-21"
|
46
48
|
def read_attribute_before_type_cast(attr_name)
|
49
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
47
50
|
@attributes[attr_name.to_s].value_before_type_cast
|
48
51
|
end
|
49
52
|
|
@@ -58,19 +61,20 @@ module ActiveRecord
|
|
58
61
|
# task.attributes_before_type_cast
|
59
62
|
# # => {"id"=>nil, "title"=>nil, "is_done"=>true, "completed_on"=>"2012-10-21", "created_at"=>nil, "updated_at"=>nil}
|
60
63
|
def attributes_before_type_cast
|
64
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
61
65
|
@attributes.values_before_type_cast
|
62
66
|
end
|
63
67
|
|
64
68
|
private
|
69
|
+
# Dispatch target for <tt>*_before_type_cast</tt> attribute methods.
|
70
|
+
def attribute_before_type_cast(attribute_name)
|
71
|
+
read_attribute_before_type_cast(attribute_name)
|
72
|
+
end
|
65
73
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
def attribute_came_from_user?(attribute_name)
|
72
|
-
@attributes[attribute_name].came_from_user?
|
73
|
-
end
|
74
|
+
def attribute_came_from_user?(attribute_name)
|
75
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
76
|
+
@attributes[attribute_name].came_from_user?
|
77
|
+
end
|
74
78
|
end
|
75
79
|
end
|
76
80
|
end
|