activerecord 5.0.7.2 → 6.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +829 -2015
- data/MIT-LICENSE +3 -1
- data/README.rdoc +11 -9
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record.rb +37 -29
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +30 -18
- data/lib/active_record/associations.rb +1714 -1596
- data/lib/active_record/associations/alias_tracker.rb +36 -42
- data/lib/active_record/associations/association.rb +143 -68
- data/lib/active_record/associations/association_scope.rb +98 -94
- data/lib/active_record/associations/belongs_to_association.rb +76 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +27 -28
- data/lib/active_record/associations/builder/belongs_to.rb +52 -60
- data/lib/active_record/associations/builder/collection_association.rb +12 -22
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
- data/lib/active_record/associations/builder/has_many.rb +10 -2
- data/lib/active_record/associations/builder/has_one.rb +35 -2
- data/lib/active_record/associations/builder/singular_association.rb +5 -1
- data/lib/active_record/associations/collection_association.rb +104 -259
- data/lib/active_record/associations/collection_proxy.rb +169 -125
- data/lib/active_record/associations/foreign_association.rb +22 -0
- data/lib/active_record/associations/has_many_association.rb +46 -31
- data/lib/active_record/associations/has_many_through_association.rb +66 -46
- data/lib/active_record/associations/has_one_association.rb +71 -52
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +169 -180
- data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
- 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 +97 -104
- data/lib/active_record/associations/preloader/association.rb +109 -97
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +27 -15
- data/lib/active_record/attribute_assignment.rb +55 -60
- data/lib/active_record/attribute_methods.rb +111 -141
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
- data/lib/active_record/attribute_methods/dirty.rb +172 -112
- data/lib/active_record/attribute_methods/primary_key.rb +88 -91
- data/lib/active_record/attribute_methods/query.rb +6 -8
- data/lib/active_record/attribute_methods/read.rb +18 -50
- data/lib/active_record/attribute_methods/serialization.rb +38 -10
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
- data/lib/active_record/attribute_methods/write.rb +25 -32
- data/lib/active_record/attributes.rb +69 -31
- data/lib/active_record/autosave_association.rb +102 -66
- data/lib/active_record/base.rb +16 -25
- data/lib/active_record/callbacks.rb +202 -43
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +11 -12
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
- data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
- data/lib/active_record/connection_adapters/column.rb +55 -13
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +79 -49
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +20 -12
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +39 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
- 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 +19 -18
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -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/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +98 -38
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +426 -324
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
- data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -6
- 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 +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +287 -45
- data/lib/active_record/core.rb +385 -181
- data/lib/active_record/counter_cache.rb +60 -28
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -87
- data/lib/active_record/enum.rb +122 -47
- data/lib/active_record/errors.rb +153 -22
- data/lib/active_record/explain.rb +13 -8
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +20 -22
- data/lib/active_record/fixture_set/model_metadata.rb +32 -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 +246 -507
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +168 -95
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +114 -25
- data/lib/active_record/internal_metadata.rb +30 -24
- data/lib/active_record/legacy_yaml_adapter.rb +11 -5
- data/lib/active_record/locking/optimistic.rb +81 -85
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +68 -31
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/migration.rb +439 -342
- data/lib/active_record/migration/command_recorder.rb +152 -98
- data/lib/active_record/migration/compatibility.rb +229 -60
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/model_schema.rb +230 -122
- data/lib/active_record/nested_attributes.rb +213 -203
- data/lib/active_record/no_touching.rb +11 -2
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +471 -97
- data/lib/active_record/query_cache.rb +23 -12
- data/lib/active_record/querying.rb +43 -25
- data/lib/active_record/railtie.rb +155 -43
- 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 +507 -195
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +245 -269
- data/lib/active_record/relation.rb +475 -324
- data/lib/active_record/relation/batches.rb +125 -72
- data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
- data/lib/active_record/relation/calculations.rb +267 -171
- data/lib/active_record/relation/delegation.rb +73 -69
- data/lib/active_record/relation/finder_methods.rb +238 -248
- data/lib/active_record/relation/from_clause.rb +7 -9
- data/lib/active_record/relation/merger.rb +95 -77
- data/lib/active_record/relation/predicate_builder.rb +109 -110
- data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +654 -374
- data/lib/active_record/relation/record_fetch_warning.rb +8 -6
- data/lib/active_record/relation/spawn_methods.rb +15 -14
- data/lib/active_record/relation/where_clause.rb +171 -109
- data/lib/active_record/result.rb +88 -51
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +73 -100
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +101 -69
- data/lib/active_record/schema_migration.rb +16 -12
- data/lib/active_record/scoping.rb +20 -20
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +39 -30
- data/lib/active_record/secure_token.rb +19 -9
- data/lib/active_record/serialization.rb +7 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +80 -29
- data/lib/active_record/store.rb +122 -42
- data/lib/active_record/suppressor.rb +6 -3
- data/lib/active_record/table_metadata.rb +51 -39
- data/lib/active_record/tasks/database_tasks.rb +332 -115
- data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
- data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
- data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +246 -0
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +26 -24
- data/lib/active_record/transactions.rb +121 -184
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +29 -17
- data/lib/active_record/type/adapter_specific_registry.rb +44 -48
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +20 -9
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +12 -1
- data/lib/active_record/type/type_map.rb +14 -17
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/type_caster/connection.rb +17 -13
- data/lib/active_record/type_caster/map.rb +10 -6
- data/lib/active_record/validations.rb +8 -5
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +4 -3
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +52 -45
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +54 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -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 +70 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -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 +15 -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 +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -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 +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -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 +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -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 +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -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 +26 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +22 -3
- data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +141 -57
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- 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 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute_decorators.rb +0 -67
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/attribute_set/builder.rb +0 -132
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -263
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -17
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/relation/where_clause_factory.rb +0 -38
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,19 +1,19 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/associations/join_dependency/join_part"
|
4
|
+
require "active_support/core_ext/array/extract"
|
2
5
|
|
3
6
|
module ActiveRecord
|
4
7
|
module Associations
|
5
8
|
class JoinDependency # :nodoc:
|
6
9
|
class JoinAssociation < JoinPart # :nodoc:
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
attr_accessor :tables
|
10
|
+
attr_reader :reflection, :tables
|
11
|
+
attr_accessor :table
|
11
12
|
|
12
13
|
def initialize(reflection, children)
|
13
14
|
super(reflection.klass, children)
|
14
15
|
|
15
|
-
@reflection
|
16
|
-
@tables = nil
|
16
|
+
@reflection = reflection
|
17
17
|
end
|
18
18
|
|
19
19
|
def match?(other)
|
@@ -21,108 +21,82 @@ module ActiveRecord
|
|
21
21
|
super && reflection == other.reflection
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
def join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
|
25
|
+
joins = []
|
26
|
+
chain = []
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
tables = tables.reverse
|
28
|
+
reflection.chain.each do |reflection|
|
29
|
+
table, terminated = yield reflection
|
30
|
+
@table ||= table
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
if terminated
|
33
|
+
foreign_table, foreign_klass = table, reflection.klass
|
34
|
+
break
|
35
|
+
end
|
36
|
+
|
37
|
+
chain << [reflection, table]
|
38
|
+
end
|
33
39
|
|
34
40
|
# The chain starts with the target table, but we want to end with it here (makes
|
35
41
|
# more sense in this context), so we reverse
|
36
|
-
chain.reverse_each do |reflection|
|
37
|
-
table = tables.shift
|
42
|
+
chain.reverse_each do |reflection, table|
|
38
43
|
klass = reflection.klass
|
39
44
|
|
40
|
-
|
41
|
-
key = join_keys.key
|
42
|
-
foreign_key = join_keys.foreign_key
|
45
|
+
scope = reflection.join_scope(table, foreign_table, foreign_klass)
|
43
46
|
|
44
|
-
|
47
|
+
unless scope.references_values.empty?
|
48
|
+
associations = scope.eager_load_values | scope.includes_values
|
45
49
|
|
46
|
-
|
47
|
-
|
48
|
-
if item.is_a?(Relation)
|
49
|
-
item
|
50
|
-
else
|
51
|
-
ActiveRecord::Relation.create(klass, table, predicate_builder)
|
52
|
-
.instance_exec(node, &item)
|
50
|
+
unless associations.empty?
|
51
|
+
scope.joins! scope.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
|
53
52
|
end
|
54
53
|
end
|
55
|
-
scope_chain_index += 1
|
56
54
|
|
57
|
-
|
58
|
-
|
55
|
+
arel = scope.arel(alias_tracker.aliases)
|
56
|
+
nodes = arel.constraints.first
|
59
57
|
|
60
|
-
|
61
|
-
|
62
|
-
relation
|
63
|
-
else
|
64
|
-
klass.send(:build_default_scope, relation)
|
58
|
+
if nodes.is_a?(Arel::Nodes::And)
|
59
|
+
others = nodes.children.extract! do |node|
|
60
|
+
!Arel.fetch_attribute(node) { |attr| attr.relation.name == table.name }
|
65
61
|
end
|
66
|
-
|
67
|
-
rel = scope_chain_items.inject(klass_scope || scope_chain_items.shift, &:merge!)
|
68
|
-
|
69
|
-
if rel && !rel.arel.constraints.empty?
|
70
|
-
binds += rel.bound_attributes
|
71
|
-
constraint = constraint.and rel.arel.constraints
|
72
62
|
end
|
73
63
|
|
74
|
-
|
75
|
-
value = foreign_klass.base_class.name
|
76
|
-
column = klass.columns_hash[reflection.type.to_s]
|
64
|
+
joins << join_type.new(table, Arel::Nodes::On.new(nodes))
|
77
65
|
|
78
|
-
|
79
|
-
|
66
|
+
if others && !others.empty?
|
67
|
+
joins.concat arel.join_sources
|
68
|
+
append_constraints(joins.last, others)
|
80
69
|
end
|
81
70
|
|
82
|
-
joins << table.create_join(table, table.create_on(constraint), join_type)
|
83
|
-
|
84
71
|
# The current table in this iteration becomes the foreign table in the next
|
85
72
|
foreign_table, foreign_klass = table, klass
|
86
73
|
end
|
87
74
|
|
88
|
-
|
75
|
+
joins
|
89
76
|
end
|
90
77
|
|
91
|
-
|
92
|
-
|
93
|
-
# Example:
|
94
|
-
#
|
95
|
-
# class Physician < ActiveRecord::Base
|
96
|
-
# has_many :appointments
|
97
|
-
# end
|
98
|
-
#
|
99
|
-
# If I execute `Physician.joins(:appointments).to_a` then
|
100
|
-
# klass # => Physician
|
101
|
-
# table # => #<Arel::Table @name="appointments" ...>
|
102
|
-
# key # => physician_id
|
103
|
-
# foreign_table # => #<Arel::Table @name="physicians" ...>
|
104
|
-
# foreign_key # => id
|
105
|
-
#
|
106
|
-
def build_constraint(klass, table, key, foreign_table, foreign_key)
|
107
|
-
constraint = table[key].eq(foreign_table[foreign_key])
|
108
|
-
|
109
|
-
if klass.finder_needs_type_condition?
|
110
|
-
constraint = table.create_and([
|
111
|
-
constraint,
|
112
|
-
klass.send(:type_condition, table)
|
113
|
-
])
|
114
|
-
end
|
78
|
+
def readonly?
|
79
|
+
return @readonly if defined?(@readonly)
|
115
80
|
|
116
|
-
|
81
|
+
@readonly = reflection.scope && reflection.scope_for(base_klass.unscoped).readonly_value
|
117
82
|
end
|
118
83
|
|
119
|
-
def
|
120
|
-
|
121
|
-
end
|
84
|
+
def strict_loading?
|
85
|
+
return @strict_loading if defined?(@strict_loading)
|
122
86
|
|
123
|
-
|
124
|
-
table.table_alias || table.name
|
87
|
+
@strict_loading = reflection.scope && reflection.scope_for(base_klass.unscoped).strict_loading_value
|
125
88
|
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def append_constraints(join, constraints)
|
92
|
+
if join.is_a?(Arel::Nodes::StringJoin)
|
93
|
+
join_string = Arel::Nodes::And.new(constraints.unshift join.left)
|
94
|
+
join.left = Arel.sql(base_klass.connection.visitor.compile(join_string))
|
95
|
+
else
|
96
|
+
right = join.right
|
97
|
+
right.expr = Arel::Nodes::And.new(constraints.unshift right.expr)
|
98
|
+
end
|
99
|
+
end
|
126
100
|
end
|
127
101
|
end
|
128
102
|
end
|
@@ -1,20 +1,21 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/associations/join_dependency/join_part"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Associations
|
5
7
|
class JoinDependency # :nodoc:
|
6
8
|
class JoinBase < JoinPart # :nodoc:
|
7
|
-
|
8
|
-
return true if self == other
|
9
|
-
super && base_klass == other.base_klass
|
10
|
-
end
|
9
|
+
attr_reader :table
|
11
10
|
|
12
|
-
def table
|
13
|
-
base_klass
|
11
|
+
def initialize(base_klass, table, children)
|
12
|
+
super(base_klass, children)
|
13
|
+
@table = table
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
16
|
+
def match?(other)
|
17
|
+
return true if self == other
|
18
|
+
super && base_klass == other.base_klass
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class JoinDependency # :nodoc:
|
@@ -15,17 +17,13 @@ module ActiveRecord
|
|
15
17
|
# association.
|
16
18
|
attr_reader :base_klass, :children
|
17
19
|
|
18
|
-
delegate :table_name, :column_names, :primary_key, :to
|
20
|
+
delegate :table_name, :column_names, :primary_key, :attribute_types, to: :base_klass
|
19
21
|
|
20
22
|
def initialize(base_klass, children)
|
21
23
|
@base_klass = base_klass
|
22
24
|
@children = children
|
23
25
|
end
|
24
26
|
|
25
|
-
def name
|
26
|
-
reflection.name
|
27
|
-
end
|
28
|
-
|
29
27
|
def match?(other)
|
30
28
|
self.class == other.class
|
31
29
|
end
|
@@ -35,13 +33,15 @@ module ActiveRecord
|
|
35
33
|
children.each { |child| child.each(&block) }
|
36
34
|
end
|
37
35
|
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
def each_children(&block)
|
37
|
+
children.each do |child|
|
38
|
+
yield self, child
|
39
|
+
child.each_children(&block)
|
40
|
+
end
|
41
41
|
end
|
42
42
|
|
43
|
-
#
|
44
|
-
def
|
43
|
+
# An Arel::Table for the active_record
|
44
|
+
def table
|
45
45
|
raise NotImplementedError
|
46
46
|
end
|
47
47
|
|
@@ -54,16 +54,16 @@ module ActiveRecord
|
|
54
54
|
length = column_names_with_alias.length
|
55
55
|
|
56
56
|
while index < length
|
57
|
-
|
58
|
-
hash[
|
57
|
+
column = column_names_with_alias[index]
|
58
|
+
hash[column.name] = row[column.alias]
|
59
59
|
index += 1
|
60
60
|
end
|
61
61
|
|
62
62
|
hash
|
63
63
|
end
|
64
64
|
|
65
|
-
def instantiate(row, aliases, &block)
|
66
|
-
base_klass.instantiate(extract_record(row, aliases), &block)
|
65
|
+
def instantiate(row, aliases, column_types = {}, &block)
|
66
|
+
base_klass.instantiate(extract_record(row, aliases), column_types, &block)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/enumerable"
|
4
|
+
|
1
5
|
module ActiveRecord
|
2
6
|
module Associations
|
3
7
|
# Implements the details of eager loading of Active Record associations.
|
@@ -42,20 +46,10 @@ module ActiveRecord
|
|
42
46
|
extend ActiveSupport::Autoload
|
43
47
|
|
44
48
|
eager_autoload do
|
45
|
-
autoload :Association,
|
46
|
-
autoload :
|
47
|
-
autoload :CollectionAssociation, 'active_record/associations/preloader/collection_association'
|
48
|
-
autoload :ThroughAssociation, 'active_record/associations/preloader/through_association'
|
49
|
-
|
50
|
-
autoload :HasMany, 'active_record/associations/preloader/has_many'
|
51
|
-
autoload :HasManyThrough, 'active_record/associations/preloader/has_many_through'
|
52
|
-
autoload :HasOne, 'active_record/associations/preloader/has_one'
|
53
|
-
autoload :HasOneThrough, 'active_record/associations/preloader/has_one_through'
|
54
|
-
autoload :BelongsTo, 'active_record/associations/preloader/belongs_to'
|
49
|
+
autoload :Association, "active_record/associations/preloader/association"
|
50
|
+
autoload :ThroughAssociation, "active_record/associations/preloader/through_association"
|
55
51
|
end
|
56
52
|
|
57
|
-
NULL_RELATION = Struct.new(:values, :where_clause, :joins_values).new({}, Relation::WhereClause.empty, [])
|
58
|
-
|
59
53
|
# Eager loads the named associations for the given Active Record record(s).
|
60
54
|
#
|
61
55
|
# In this description, 'association name' shall refer to the name passed
|
@@ -66,7 +60,7 @@ module ActiveRecord
|
|
66
60
|
# == Parameters
|
67
61
|
# +records+ is an array of ActiveRecord::Base. This array needs not be flat,
|
68
62
|
# i.e. +records+ itself may also contain arrays of records. In any case,
|
69
|
-
# +preload_associations+ will preload
|
63
|
+
# +preload_associations+ will preload all associations records by
|
70
64
|
# flattening +records+.
|
71
65
|
#
|
72
66
|
# +associations+ specifies one or more associations that you want to
|
@@ -91,123 +85,122 @@ module ActiveRecord
|
|
91
85
|
# { author: :avatar }
|
92
86
|
# [ :books, { author: :avatar } ]
|
93
87
|
def preload(records, associations, preload_scope = nil)
|
94
|
-
records
|
95
|
-
associations = Array.wrap(associations)
|
96
|
-
preload_scope = preload_scope || NULL_RELATION
|
88
|
+
records = Array.wrap(records).compact
|
97
89
|
|
98
90
|
if records.empty?
|
99
91
|
[]
|
100
92
|
else
|
101
|
-
associations.flat_map { |association|
|
93
|
+
Array.wrap(associations).flat_map { |association|
|
102
94
|
preloaders_on association, records, preload_scope
|
103
95
|
}
|
104
96
|
end
|
105
97
|
end
|
106
98
|
|
107
|
-
|
108
|
-
|
109
|
-
# Loads all the given data into +records+ for the +association+.
|
110
|
-
def preloaders_on(association, records, scope)
|
111
|
-
case association
|
112
|
-
when Hash
|
113
|
-
preloaders_for_hash(association, records, scope)
|
114
|
-
when Symbol
|
115
|
-
preloaders_for_one(association, records, scope)
|
116
|
-
when String
|
117
|
-
preloaders_for_one(association.to_sym, records, scope)
|
118
|
-
else
|
119
|
-
raise ArgumentError, "#{association.inspect} was not recognized for preload"
|
120
|
-
end
|
99
|
+
def initialize(associate_by_default: true)
|
100
|
+
@associate_by_default = associate_by_default
|
121
101
|
end
|
122
102
|
|
123
|
-
|
124
|
-
|
125
|
-
|
103
|
+
private
|
104
|
+
# Loads all the given data into +records+ for the +association+.
|
105
|
+
def preloaders_on(association, records, scope, polymorphic_parent = false)
|
106
|
+
case association
|
107
|
+
when Hash
|
108
|
+
preloaders_for_hash(association, records, scope, polymorphic_parent)
|
109
|
+
when Symbol, String
|
110
|
+
preloaders_for_one(association, records, scope, polymorphic_parent)
|
111
|
+
else
|
112
|
+
raise ArgumentError, "#{association.inspect} was not recognized for preload"
|
113
|
+
end
|
114
|
+
end
|
126
115
|
|
127
|
-
|
128
|
-
|
129
|
-
|
116
|
+
def preloaders_for_hash(association, records, scope, polymorphic_parent)
|
117
|
+
association.flat_map { |parent, child|
|
118
|
+
grouped_records(parent, records, polymorphic_parent).flat_map do |reflection, reflection_records|
|
119
|
+
loaders = preloaders_for_reflection(reflection, reflection_records, scope)
|
120
|
+
recs = loaders.flat_map(&:preloaded_records).uniq
|
121
|
+
child_polymorphic_parent = reflection && reflection.options[:polymorphic]
|
122
|
+
loaders.concat Array.wrap(child).flat_map { |assoc|
|
123
|
+
preloaders_on assoc, recs, scope, child_polymorphic_parent
|
124
|
+
}
|
125
|
+
loaders
|
126
|
+
end
|
130
127
|
}
|
131
|
-
loaders
|
132
|
-
}
|
133
|
-
end
|
134
|
-
|
135
|
-
# Loads all the given data into +records+ for a singular +association+.
|
136
|
-
#
|
137
|
-
# Functions by instantiating a preloader class such as Preloader::HasManyThrough and
|
138
|
-
# call the +run+ method for each passed in class in the +records+ argument.
|
139
|
-
#
|
140
|
-
# Not all records have the same class, so group then preload group on the reflection
|
141
|
-
# itself so that if various subclass share the same association then we do not split
|
142
|
-
# them unnecessarily
|
143
|
-
#
|
144
|
-
# Additionally, polymorphic belongs_to associations can have multiple associated
|
145
|
-
# classes, depending on the polymorphic_type field. So we group by the classes as
|
146
|
-
# well.
|
147
|
-
def preloaders_for_one(association, records, scope)
|
148
|
-
grouped_records(association, records).flat_map do |reflection, klasses|
|
149
|
-
klasses.map do |rhs_klass, rs|
|
150
|
-
loader = preloader_for(reflection, rs, rhs_klass).new(rhs_klass, rs, reflection, scope)
|
151
|
-
loader.run self
|
152
|
-
loader
|
153
|
-
end
|
154
128
|
end
|
155
|
-
end
|
156
129
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
130
|
+
# Loads all the given data into +records+ for a singular +association+.
|
131
|
+
#
|
132
|
+
# Functions by instantiating a preloader class such as Preloader::Association and
|
133
|
+
# call the +run+ method for each passed in class in the +records+ argument.
|
134
|
+
#
|
135
|
+
# Not all records have the same class, so group then preload group on the reflection
|
136
|
+
# itself so that if various subclass share the same association then we do not split
|
137
|
+
# them unnecessarily
|
138
|
+
#
|
139
|
+
# Additionally, polymorphic belongs_to associations can have multiple associated
|
140
|
+
# classes, depending on the polymorphic_type field. So we group by the classes as
|
141
|
+
# well.
|
142
|
+
def preloaders_for_one(association, records, scope, polymorphic_parent)
|
143
|
+
grouped_records(association, records, polymorphic_parent)
|
144
|
+
.flat_map do |reflection, reflection_records|
|
145
|
+
preloaders_for_reflection reflection, reflection_records, scope
|
146
|
+
end
|
164
147
|
end
|
165
|
-
h
|
166
|
-
end
|
167
148
|
|
168
|
-
|
169
|
-
|
149
|
+
def preloaders_for_reflection(reflection, records, scope)
|
150
|
+
records.group_by { |record| record.association(reflection.name).klass }.map do |rhs_klass, rs|
|
151
|
+
preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope, @associate_by_default).run
|
152
|
+
end
|
153
|
+
end
|
170
154
|
|
171
|
-
def
|
172
|
-
|
173
|
-
|
155
|
+
def grouped_records(association, records, polymorphic_parent)
|
156
|
+
h = {}
|
157
|
+
records.each do |record|
|
158
|
+
reflection = record.class._reflect_on_association(association)
|
159
|
+
next if polymorphic_parent && !reflection || !record.association(association).klass
|
160
|
+
(h[reflection] ||= []) << record
|
161
|
+
end
|
162
|
+
h
|
174
163
|
end
|
175
164
|
|
176
|
-
|
165
|
+
class AlreadyLoaded # :nodoc:
|
166
|
+
def initialize(klass, owners, reflection, preload_scope, associate_by_default = true)
|
167
|
+
@owners = owners
|
168
|
+
@reflection = reflection
|
169
|
+
end
|
177
170
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
end
|
171
|
+
def run
|
172
|
+
self
|
173
|
+
end
|
182
174
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
def self.preloaded_records; []; end
|
187
|
-
def self.owners; []; end
|
188
|
-
end
|
175
|
+
def preloaded_records
|
176
|
+
@preloaded_records ||= records_by_owner.flat_map(&:last)
|
177
|
+
end
|
189
178
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
return NullPreloader unless rhs_klass
|
179
|
+
def records_by_owner
|
180
|
+
@records_by_owner ||= owners.index_with do |owner|
|
181
|
+
Array(owner.association(reflection.name).target)
|
182
|
+
end
|
183
|
+
end
|
196
184
|
|
197
|
-
|
198
|
-
|
185
|
+
private
|
186
|
+
attr_reader :owners, :reflection
|
199
187
|
end
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
188
|
+
|
189
|
+
# Returns a class containing the logic needed to load preload the data
|
190
|
+
# and attach it to a relation. The class returned implements a `run` method
|
191
|
+
# that accepts a preloader.
|
192
|
+
def preloader_for(reflection, owners)
|
193
|
+
if owners.all? { |o| o.association(reflection.name).loaded? }
|
194
|
+
return AlreadyLoaded
|
195
|
+
end
|
196
|
+
reflection.check_preloadable!
|
197
|
+
|
198
|
+
if reflection.options[:through]
|
199
|
+
ThroughAssociation
|
200
|
+
else
|
201
|
+
Association
|
202
|
+
end
|
209
203
|
end
|
210
|
-
end
|
211
204
|
end
|
212
205
|
end
|
213
206
|
end
|