activerecord 4.2.8 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +612 -1583
- data/MIT-LICENSE +4 -2
- data/README.rdoc +13 -12
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record.rb +41 -22
- data/lib/active_record/aggregations.rb +267 -251
- data/lib/active_record/association_relation.rb +11 -6
- data/lib/active_record/associations.rb +1737 -1597
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +125 -58
- data/lib/active_record/associations/association_scope.rb +103 -132
- data/lib/active_record/associations/belongs_to_association.rb +65 -60
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +27 -40
- data/lib/active_record/associations/builder/belongs_to.rb +69 -55
- data/lib/active_record/associations/builder/collection_association.rb +10 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
- data/lib/active_record/associations/builder/has_many.rb +8 -4
- data/lib/active_record/associations/builder/has_one.rb +46 -5
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +134 -286
- data/lib/active_record/associations/collection_proxy.rb +241 -146
- data/lib/active_record/associations/foreign_association.rb +10 -1
- data/lib/active_record/associations/has_many_association.rb +34 -97
- data/lib/active_record/associations/has_many_through_association.rb +60 -87
- data/lib/active_record/associations/has_one_association.rb +61 -49
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +137 -167
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -88
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/preloader.rb +90 -92
- data/lib/active_record/associations/preloader/association.rb +90 -123
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +38 -18
- data/lib/active_record/attribute_assignment.rb +56 -183
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods.rb +120 -135
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
- data/lib/active_record/attribute_methods/dirty.rb +174 -144
- data/lib/active_record/attribute_methods/primary_key.rb +91 -83
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -76
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
- data/lib/active_record/attribute_methods/write.rb +32 -54
- data/lib/active_record/attributes.rb +214 -82
- data/lib/active_record/autosave_association.rb +91 -37
- data/lib/active_record/base.rb +57 -45
- data/lib/active_record/callbacks.rb +100 -74
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -296
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -115
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -244
- data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
- data/lib/active_record/connection_adapters/abstract_adapter.rb +460 -204
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +510 -627
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -188
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -114
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +10 -5
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +551 -356
- data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -345
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +176 -41
- data/lib/active_record/core.rb +251 -231
- data/lib/active_record/counter_cache.rb +67 -49
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +163 -86
- data/lib/active_record/errors.rb +188 -53
- data/lib/active_record/explain.rb +23 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +228 -499
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +158 -112
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +123 -29
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +21 -3
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +87 -96
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +76 -33
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +626 -283
- data/lib/active_record/migration/command_recorder.rb +177 -90
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/model_schema.rb +314 -112
- data/lib/active_record/nested_attributes.rb +264 -222
- data/lib/active_record/no_touching.rb +14 -1
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +557 -125
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +43 -29
- data/lib/active_record/railtie.rb +147 -46
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +330 -197
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +428 -279
- data/lib/active_record/relation.rb +518 -341
- data/lib/active_record/relation/batches.rb +207 -55
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/calculations.rb +267 -253
- data/lib/active_record/relation/delegation.rb +70 -80
- data/lib/active_record/relation/finder_methods.rb +277 -241
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +78 -87
- data/lib/active_record/relation/predicate_builder.rb +114 -119
- data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +575 -394
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -13
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/result.rb +79 -42
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +144 -121
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +112 -93
- data/lib/active_record/schema_migration.rb +24 -17
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/scoping/default.rb +101 -85
- data/lib/active_record/scoping/named.rb +86 -33
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +73 -36
- data/lib/active_record/store.rb +127 -42
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +75 -0
- data/lib/active_record/tasks/database_tasks.rb +308 -99
- data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
- data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +86 -40
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +216 -150
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +78 -23
- data/lib/active_record/type/adapter_specific_registry.rb +129 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +24 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +42 -55
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +51 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration.rb +31 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +164 -60
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -58
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,11 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Through Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Through Association
|
4
6
|
module ThroughAssociation #:nodoc:
|
7
|
+
delegate :source_reflection, to: :reflection
|
8
|
+
|
9
|
+
private
|
10
|
+
def through_reflection
|
11
|
+
@through_reflection ||= begin
|
12
|
+
refl = reflection.through_reflection
|
5
13
|
|
6
|
-
|
14
|
+
while refl.through_reflection?
|
15
|
+
refl = refl.through_reflection
|
16
|
+
end
|
17
|
+
|
18
|
+
refl
|
19
|
+
end
|
20
|
+
end
|
7
21
|
|
8
|
-
|
22
|
+
def through_association
|
23
|
+
@through_association ||= owner.association(through_reflection.name)
|
24
|
+
end
|
9
25
|
|
10
26
|
# We merge in these scopes for two reasons:
|
11
27
|
#
|
@@ -14,7 +30,7 @@ module ActiveRecord
|
|
14
30
|
def target_scope
|
15
31
|
scope = super
|
16
32
|
reflection.chain.drop(1).each do |reflection|
|
17
|
-
relation = reflection.klass.
|
33
|
+
relation = reflection.klass.scope_for_association
|
18
34
|
scope.merge!(
|
19
35
|
relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
|
20
36
|
)
|
@@ -22,12 +38,10 @@ module ActiveRecord
|
|
22
38
|
scope
|
23
39
|
end
|
24
40
|
|
25
|
-
private
|
26
|
-
|
27
41
|
# Construct attributes for :through pointing to owner and associate. This is used by the
|
28
42
|
# methods which create and delete records on the association.
|
29
43
|
#
|
30
|
-
# We only support indirectly modifying through associations which
|
44
|
+
# We only support indirectly modifying through associations which have a belongs_to source.
|
31
45
|
# This is the "has_many :tags, through: :taggings" situation, where the join model
|
32
46
|
# typically has a belongs_to on both side. In other words, associations which could also
|
33
47
|
# be represented as has_and_belongs_to_many associations.
|
@@ -39,24 +53,22 @@ module ActiveRecord
|
|
39
53
|
def construct_join_attributes(*records)
|
40
54
|
ensure_mutable
|
41
55
|
|
42
|
-
|
56
|
+
association_primary_key = source_reflection.association_primary_key(reflection.klass)
|
57
|
+
|
58
|
+
if association_primary_key == reflection.klass.primary_key && !options[:source_type]
|
43
59
|
join_attributes = { source_reflection.name => records }
|
44
60
|
else
|
45
61
|
join_attributes = {
|
46
|
-
source_reflection.foreign_key =>
|
47
|
-
records.map { |record|
|
48
|
-
record.send(source_reflection.association_primary_key(reflection.klass))
|
49
|
-
}
|
62
|
+
source_reflection.foreign_key => records.map(&association_primary_key.to_sym)
|
50
63
|
}
|
51
64
|
end
|
52
65
|
|
53
66
|
if options[:source_type]
|
54
|
-
join_attributes[source_reflection.foreign_type] =
|
55
|
-
records.map { |record| record.class.base_class.name }
|
67
|
+
join_attributes[source_reflection.foreign_type] = [ options[:source_type] ]
|
56
68
|
end
|
57
69
|
|
58
70
|
if records.count == 1
|
59
|
-
|
71
|
+
join_attributes.transform_values!(&:first)
|
60
72
|
else
|
61
73
|
join_attributes
|
62
74
|
end
|
@@ -76,13 +88,21 @@ module ActiveRecord
|
|
76
88
|
|
77
89
|
def ensure_mutable
|
78
90
|
unless source_reflection.belongs_to?
|
79
|
-
|
91
|
+
if reflection.has_one?
|
92
|
+
raise HasOneThroughCantAssociateThroughHasOneOrManyReflection.new(owner, reflection)
|
93
|
+
else
|
94
|
+
raise HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(owner, reflection)
|
95
|
+
end
|
80
96
|
end
|
81
97
|
end
|
82
98
|
|
83
99
|
def ensure_not_nested
|
84
100
|
if reflection.nested?
|
85
|
-
|
101
|
+
if reflection.has_one?
|
102
|
+
raise HasOneThroughNestedAssociationsAreReadonly.new(owner, reflection)
|
103
|
+
else
|
104
|
+
raise HasManyThroughNestedAssociationsAreReadonly.new(owner, reflection)
|
105
|
+
end
|
86
106
|
end
|
87
107
|
end
|
88
108
|
|
@@ -94,7 +114,7 @@ module ActiveRecord
|
|
94
114
|
attributes[inverse.foreign_key] = target.id
|
95
115
|
end
|
96
116
|
|
97
|
-
super
|
117
|
+
super
|
98
118
|
end
|
99
119
|
end
|
100
120
|
end
|
@@ -1,212 +1,85 @@
|
|
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
10
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
if respond_to?("#{k}=")
|
57
|
-
raise
|
58
|
-
else
|
59
|
-
raise UnknownAttributeError.new(self, k)
|
60
|
-
end
|
61
|
-
end
|
11
|
+
def _assign_attributes(attributes)
|
12
|
+
multi_parameter_attributes = {}
|
13
|
+
nested_parameter_attributes = {}
|
62
14
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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)
|
15
|
+
attributes.each do |k, v|
|
16
|
+
if k.include?("(")
|
17
|
+
multi_parameter_attributes[k] = attributes.delete(k)
|
18
|
+
elsif v.is_a?(Hash)
|
19
|
+
nested_parameter_attributes[k] = attributes.delete(k)
|
20
|
+
end
|
87
21
|
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 = {}
|
22
|
+
super(attributes)
|
97
23
|
|
98
|
-
|
99
|
-
|
100
|
-
attributes[attribute_name] ||= {}
|
101
|
-
|
102
|
-
parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
|
103
|
-
attributes[attribute_name][find_parameter_position(multiparameter_name)] ||= parameter_value
|
24
|
+
assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
|
25
|
+
assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
|
104
26
|
end
|
105
27
|
|
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
|
124
|
-
end
|
125
|
-
|
126
|
-
def read_value
|
127
|
-
return if values.values.compact.empty?
|
128
|
-
|
129
|
-
@cast_type = object.type_for_attribute(name)
|
130
|
-
klass = cast_type.klass
|
131
|
-
|
132
|
-
if klass == Time
|
133
|
-
read_time
|
134
|
-
elsif klass == Date
|
135
|
-
read_date
|
136
|
-
else
|
137
|
-
read_other
|
138
|
-
end
|
28
|
+
# Assign any deferred nested attributes after the base attributes have been set.
|
29
|
+
def assign_nested_parameter_attributes(pairs)
|
30
|
+
pairs.each { |k, v| _assign_attribute(k, v) }
|
139
31
|
end
|
140
32
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
33
|
+
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
|
34
|
+
# by calling new on the column type or aggregation type (through composed_of) object with these parameters.
|
35
|
+
# So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
|
36
|
+
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
37
|
+
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
|
38
|
+
# f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
|
39
|
+
def assign_multiparameter_attributes(pairs)
|
40
|
+
execute_callstack_for_multiparameter_attributes(
|
41
|
+
extract_callstack_for_multiparameter_attributes(pairs)
|
42
|
+
)
|
149
43
|
end
|
150
44
|
|
151
|
-
def
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
values
|
45
|
+
def execute_callstack_for_multiparameter_attributes(callstack)
|
46
|
+
errors = []
|
47
|
+
callstack.each do |name, values_with_empty_parameters|
|
48
|
+
if values_with_empty_parameters.each_value.all?(&:nil?)
|
49
|
+
values = nil
|
50
|
+
else
|
51
|
+
values = values_with_empty_parameters
|
158
52
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
# If Date bits were provided but blank, then return nil
|
164
|
-
return if blank_date_parameter?
|
53
|
+
send("#{name}=", values)
|
54
|
+
rescue => ex
|
55
|
+
errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
|
165
56
|
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
|
57
|
+
unless errors.empty?
|
58
|
+
error_descriptions = errors.map(&:message).join(",")
|
59
|
+
raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes [#{error_descriptions}]"
|
181
60
|
end
|
182
61
|
end
|
183
62
|
|
184
|
-
def
|
185
|
-
|
186
|
-
positions = (1..max_position)
|
187
|
-
validate_required_parameters!(positions)
|
63
|
+
def extract_callstack_for_multiparameter_attributes(pairs)
|
64
|
+
attributes = {}
|
188
65
|
|
189
|
-
|
190
|
-
|
66
|
+
pairs.each do |(multiparameter_name, value)|
|
67
|
+
attribute_name = multiparameter_name.split("(").first
|
68
|
+
attributes[attribute_name] ||= {}
|
191
69
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
(1..3).any? { |position| values[position].blank? }
|
70
|
+
parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
|
71
|
+
attributes[attribute_name][find_parameter_position(multiparameter_name)] ||= parameter_value
|
72
|
+
end
|
73
|
+
|
74
|
+
attributes
|
198
75
|
end
|
199
76
|
|
200
|
-
|
201
|
-
|
202
|
-
if missing_parameter = positions.detect { |position| !values.key?(position) }
|
203
|
-
raise ArgumentError.new("Missing Parameter - #{name}(#{missing_parameter})")
|
204
|
-
end
|
77
|
+
def type_cast_attribute_value(multiparameter_name, value)
|
78
|
+
multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
|
205
79
|
end
|
206
80
|
|
207
|
-
def
|
208
|
-
[
|
81
|
+
def find_parameter_position(multiparameter_name)
|
82
|
+
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
|
209
83
|
end
|
210
|
-
end
|
211
84
|
end
|
212
85
|
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
|
@@ -24,12 +47,13 @@ module ActiveRecord
|
|
24
47
|
|
25
48
|
private
|
26
49
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
50
|
+
def load_schema!
|
51
|
+
super
|
52
|
+
attribute_types.each do |name, type|
|
53
|
+
decorated_type = attribute_type_decorations.apply(name, type)
|
54
|
+
define_attribute(name, decorated_type)
|
55
|
+
end
|
31
56
|
end
|
32
|
-
end
|
33
57
|
end
|
34
58
|
|
35
59
|
class TypeDecorator # :nodoc:
|
@@ -52,15 +76,15 @@ module ActiveRecord
|
|
52
76
|
|
53
77
|
private
|
54
78
|
|
55
|
-
|
56
|
-
|
57
|
-
|
79
|
+
def decorators_for(name, type)
|
80
|
+
matching(name, type).map(&:last)
|
81
|
+
end
|
58
82
|
|
59
|
-
|
60
|
-
|
61
|
-
|
83
|
+
def matching(name, type)
|
84
|
+
@decorations.values.select do |(matcher, _)|
|
85
|
+
matcher.call(name, type)
|
86
|
+
end
|
62
87
|
end
|
63
|
-
end
|
64
88
|
end
|
65
89
|
end
|
66
90
|
end
|