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,165 +1,132 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class Preloader
|
4
6
|
class Association #:nodoc:
|
5
|
-
attr_reader :owners, :reflection, :preload_scope, :model, :klass
|
6
|
-
attr_reader :preloaded_records
|
7
|
-
|
8
7
|
def initialize(klass, owners, reflection, preload_scope)
|
9
8
|
@klass = klass
|
10
9
|
@owners = owners
|
11
10
|
@reflection = reflection
|
12
11
|
@preload_scope = preload_scope
|
13
12
|
@model = owners.first && owners.first.class
|
14
|
-
@scope = nil
|
15
|
-
@owners_by_key = nil
|
16
|
-
@preloaded_records = []
|
17
|
-
end
|
18
|
-
|
19
|
-
def run(preloader)
|
20
|
-
preload(preloader)
|
21
13
|
end
|
22
14
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
def query_scope(ids)
|
36
|
-
scope.where(association_key.in(ids))
|
37
|
-
end
|
38
|
-
|
39
|
-
def table
|
40
|
-
klass.arel_table
|
41
|
-
end
|
42
|
-
|
43
|
-
# The name of the key on the associated records
|
44
|
-
def association_key_name
|
45
|
-
raise NotImplementedError
|
46
|
-
end
|
47
|
-
|
48
|
-
# This is overridden by HABTM as the condition should be on the foreign_key column in
|
49
|
-
# the join table
|
50
|
-
def association_key
|
51
|
-
table[association_key_name]
|
52
|
-
end
|
53
|
-
|
54
|
-
# The name of the key on the model which declares the association
|
55
|
-
def owner_key_name
|
56
|
-
raise NotImplementedError
|
15
|
+
def run
|
16
|
+
if !preload_scope || preload_scope.empty_scope?
|
17
|
+
owners.each do |owner|
|
18
|
+
associate_records_to_owner(owner, records_by_owner[owner] || [])
|
19
|
+
end
|
20
|
+
else
|
21
|
+
# Custom preload scope is used and
|
22
|
+
# the association can not be marked as loaded
|
23
|
+
# Loading into a Hash instead
|
24
|
+
records_by_owner
|
25
|
+
end
|
26
|
+
self
|
57
27
|
end
|
58
28
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
end
|
29
|
+
def records_by_owner
|
30
|
+
# owners can be duplicated when a relation has a collection association join
|
31
|
+
# #compare_by_identity makes such owners different hash keys
|
32
|
+
@records_by_owner ||= preloaded_records.each_with_object({}.compare_by_identity) do |record, result|
|
33
|
+
owners_by_key[convert_key(record[association_key_name])].each do |owner|
|
34
|
+
(result[owner] ||= []) << record
|
35
|
+
end
|
36
|
+
end
|
69
37
|
end
|
70
38
|
|
71
|
-
def
|
72
|
-
|
39
|
+
def preloaded_records
|
40
|
+
return @preloaded_records if defined?(@preloaded_records)
|
41
|
+
@preloaded_records = owner_keys.empty? ? [] : records_for(owner_keys)
|
73
42
|
end
|
74
43
|
|
75
44
|
private
|
45
|
+
attr_reader :owners, :reflection, :preload_scope, :model, :klass
|
76
46
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
# Each record may have multiple owners, and vice-versa
|
82
|
-
records_by_owner = owners.each_with_object({}) do |owner,h|
|
83
|
-
h[owner] = []
|
47
|
+
# The name of the key on the associated records
|
48
|
+
def association_key_name
|
49
|
+
reflection.join_primary_key(klass)
|
84
50
|
end
|
85
51
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
52
|
+
# The name of the key on the model which declares the association
|
53
|
+
def owner_key_name
|
54
|
+
reflection.join_foreign_key
|
55
|
+
end
|
90
56
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
57
|
+
def associate_records_to_owner(owner, records)
|
58
|
+
association = owner.association(reflection.name)
|
59
|
+
if reflection.collection?
|
60
|
+
association.target = records
|
61
|
+
else
|
62
|
+
association.target = records.first
|
96
63
|
end
|
97
64
|
end
|
98
65
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
def key_conversion_required?
|
103
|
-
association_key_type != owner_key_type
|
104
|
-
end
|
105
|
-
|
106
|
-
def association_key_type
|
107
|
-
@klass.type_for_attribute(association_key_name.to_s).type
|
108
|
-
end
|
109
|
-
|
110
|
-
def owner_key_type
|
111
|
-
@model.type_for_attribute(owner_key_name.to_s).type
|
112
|
-
end
|
113
|
-
|
114
|
-
def load_slices(slices)
|
115
|
-
@preloaded_records = slices.flat_map { |slice|
|
116
|
-
records_for(slice)
|
117
|
-
}
|
118
|
-
|
119
|
-
@preloaded_records.map { |record|
|
120
|
-
key = record[association_key_name]
|
121
|
-
key = key.to_s if key_conversion_required?
|
66
|
+
def owner_keys
|
67
|
+
@owner_keys ||= owners_by_key.keys
|
68
|
+
end
|
122
69
|
|
123
|
-
|
124
|
-
|
125
|
-
|
70
|
+
def owners_by_key
|
71
|
+
@owners_by_key ||= owners.each_with_object({}) do |owner, result|
|
72
|
+
key = convert_key(owner[owner_key_name])
|
73
|
+
(result[key] ||= []) << owner if key
|
74
|
+
end
|
75
|
+
end
|
126
76
|
|
127
|
-
|
128
|
-
|
129
|
-
|
77
|
+
def key_conversion_required?
|
78
|
+
unless defined?(@key_conversion_required)
|
79
|
+
@key_conversion_required = (association_key_type != owner_key_type)
|
80
|
+
end
|
130
81
|
|
131
|
-
|
132
|
-
|
82
|
+
@key_conversion_required
|
83
|
+
end
|
133
84
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
85
|
+
def convert_key(key)
|
86
|
+
if key_conversion_required?
|
87
|
+
key.to_s
|
88
|
+
else
|
89
|
+
key
|
90
|
+
end
|
91
|
+
end
|
138
92
|
|
139
|
-
|
140
|
-
|
141
|
-
|
93
|
+
def association_key_type
|
94
|
+
@klass.type_for_attribute(association_key_name).type
|
95
|
+
end
|
142
96
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
scope.order! preload_values[:order] || values[:order]
|
97
|
+
def owner_key_type
|
98
|
+
@model.type_for_attribute(owner_key_name).type
|
99
|
+
end
|
147
100
|
|
148
|
-
|
149
|
-
scope.
|
101
|
+
def records_for(ids)
|
102
|
+
scope.where(association_key_name => ids).load do |record|
|
103
|
+
# Processing only the first owner
|
104
|
+
# because the record is modified but not an owner
|
105
|
+
owner = owners_by_key[convert_key(record[association_key_name])].first
|
106
|
+
association = owner.association(reflection.name)
|
107
|
+
association.set_inverse_instance(record)
|
108
|
+
end
|
150
109
|
end
|
151
110
|
|
152
|
-
|
153
|
-
scope
|
111
|
+
def scope
|
112
|
+
@scope ||= build_scope
|
154
113
|
end
|
155
114
|
|
156
|
-
|
157
|
-
|
115
|
+
def reflection_scope
|
116
|
+
@reflection_scope ||= reflection.scope ? reflection.scope_for(klass.unscoped) : klass.unscoped
|
158
117
|
end
|
159
118
|
|
160
|
-
|
161
|
-
|
162
|
-
|
119
|
+
def build_scope
|
120
|
+
scope = klass.scope_for_association
|
121
|
+
|
122
|
+
if reflection.type && !reflection.through_reflection?
|
123
|
+
scope.where!(reflection.type => model.polymorphic_name)
|
124
|
+
end
|
125
|
+
|
126
|
+
scope.merge!(reflection_scope) if reflection.scope
|
127
|
+
scope.merge!(preload_scope) if preload_scope
|
128
|
+
scope
|
129
|
+
end
|
163
130
|
end
|
164
131
|
end
|
165
132
|
end
|
@@ -1,95 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class Preloader
|
4
|
-
|
5
|
-
|
6
|
-
reflection.through_reflection
|
7
|
-
end
|
6
|
+
class ThroughAssociation < Association # :nodoc:
|
7
|
+
PRELOADER = ActiveRecord::Associations::Preloader.new
|
8
8
|
|
9
|
-
def
|
10
|
-
|
9
|
+
def initialize(*)
|
10
|
+
super
|
11
|
+
@already_loaded = owners.first.association(through_reflection.name).loaded?
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
through_scope)
|
17
|
-
|
18
|
-
through_records = owners.map do |owner|
|
19
|
-
association = owner.association through_reflection.name
|
14
|
+
def preloaded_records
|
15
|
+
@preloaded_records ||= source_preloaders.flat_map(&:preloaded_records)
|
16
|
+
end
|
20
17
|
|
21
|
-
|
22
|
-
|
18
|
+
def records_by_owner
|
19
|
+
return @records_by_owner if defined?(@records_by_owner)
|
20
|
+
source_records_by_owner = source_preloaders.map(&:records_by_owner).reduce(:merge)
|
21
|
+
through_records_by_owner = through_preloaders.map(&:records_by_owner).reduce(:merge)
|
23
22
|
|
24
|
-
|
23
|
+
@records_by_owner = owners.each_with_object({}) do |owner, result|
|
24
|
+
through_records = through_records_by_owner[owner] || []
|
25
25
|
|
26
|
-
|
26
|
+
if @already_loaded
|
27
|
+
if source_type = reflection.options[:source_type]
|
28
|
+
through_records = through_records.select do |record|
|
29
|
+
record[reflection.foreign_type] == source_type
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
|
34
|
+
records = through_records.flat_map do |record|
|
35
|
+
source_records_by_owner[record]
|
36
|
+
end
|
31
37
|
|
32
|
-
|
38
|
+
records.compact!
|
39
|
+
records.sort_by! { |rhs| preload_index[rhs] } if scope.order_values.any?
|
40
|
+
records.uniq! if scope.distinct_value
|
41
|
+
result[owner] = records
|
42
|
+
end
|
43
|
+
end
|
33
44
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
}
|
45
|
+
private
|
46
|
+
def source_preloaders
|
47
|
+
@source_preloaders ||= PRELOADER.preload(middle_records, source_reflection.name, scope)
|
38
48
|
end
|
39
49
|
|
40
|
-
|
41
|
-
|
42
|
-
record_offset[record] = i
|
50
|
+
def middle_records
|
51
|
+
through_preloaders.flat_map(&:preloaded_records)
|
43
52
|
end
|
44
53
|
|
45
|
-
|
46
|
-
|
54
|
+
def through_preloaders
|
55
|
+
@through_preloaders ||= PRELOADER.preload(owners, through_reflection.name, through_scope)
|
56
|
+
end
|
47
57
|
|
48
|
-
|
49
|
-
|
50
|
-
|
58
|
+
def through_reflection
|
59
|
+
reflection.through_reflection
|
60
|
+
end
|
51
61
|
|
52
|
-
|
53
|
-
|
62
|
+
def source_reflection
|
63
|
+
reflection.source_reflection
|
64
|
+
end
|
54
65
|
|
55
|
-
|
66
|
+
def preload_index
|
67
|
+
@preload_index ||= preloaded_records.each_with_object({}).with_index do |(record, result), index|
|
68
|
+
result[record] = index
|
56
69
|
end
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
|
62
|
-
def reset_association(owners, association_name)
|
63
|
-
should_reset = (through_scope != through_reflection.klass.unscoped) ||
|
64
|
-
(reflection.options[:source_type] && through_reflection.collection?)
|
65
|
-
|
66
|
-
# Don't cache the association - we would only be caching a subset
|
67
|
-
if should_reset
|
68
|
-
owners.each { |owner|
|
69
|
-
owner.association(association_name).reset
|
70
|
-
}
|
71
70
|
end
|
72
|
-
end
|
73
71
|
|
72
|
+
def through_scope
|
73
|
+
scope = through_reflection.klass.unscoped
|
74
|
+
options = reflection.options
|
74
75
|
|
75
|
-
|
76
|
-
|
76
|
+
values = reflection_scope.values
|
77
|
+
if annotations = values[:annotate]
|
78
|
+
scope.annotate!(*annotations)
|
79
|
+
end
|
77
80
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
if options[:source_type]
|
82
|
+
scope.where! reflection.foreign_type => options[:source_type]
|
83
|
+
elsif !reflection_scope.where_clause.empty?
|
84
|
+
scope.where_clause = reflection_scope.where_clause
|
85
|
+
|
86
|
+
if includes = values[:includes]
|
87
|
+
scope.includes!(source_reflection.name => includes)
|
88
|
+
else
|
89
|
+
scope.includes!(source_reflection.name)
|
90
|
+
end
|
91
|
+
|
92
|
+
if values[:references] && !values[:references].empty?
|
93
|
+
scope.references!(values[:references])
|
94
|
+
else
|
95
|
+
scope.references!(source_reflection.table_name)
|
96
|
+
end
|
97
|
+
|
98
|
+
if joins = values[:joins]
|
99
|
+
scope.joins!(source_reflection.name => joins)
|
100
|
+
end
|
101
|
+
|
102
|
+
if left_outer_joins = values[:left_outer_joins]
|
103
|
+
scope.left_outer_joins!(source_reflection.name => left_outer_joins)
|
104
|
+
end
|
105
|
+
|
106
|
+
if scope.eager_loading? && order_values = values[:order]
|
107
|
+
scope = scope.order(order_values)
|
108
|
+
end
|
85
109
|
end
|
86
110
|
|
87
|
-
scope
|
88
|
-
scope = scope.order reflection_scope.values[:order] if scope.eager_loading?
|
111
|
+
scope
|
89
112
|
end
|
90
|
-
|
91
|
-
scope
|
92
|
-
end
|
93
113
|
end
|
94
114
|
end
|
95
115
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
# Implements the details of eager loading of Active Record associations.
|
@@ -42,16 +44,8 @@ module ActiveRecord
|
|
42
44
|
extend ActiveSupport::Autoload
|
43
45
|
|
44
46
|
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'
|
47
|
+
autoload :Association, "active_record/associations/preloader/association"
|
48
|
+
autoload :ThroughAssociation, "active_record/associations/preloader/through_association"
|
55
49
|
end
|
56
50
|
|
57
51
|
# Eager loads the named associations for the given Active Record record(s).
|
@@ -88,116 +82,119 @@ module ActiveRecord
|
|
88
82
|
# [ :books, :author ]
|
89
83
|
# { author: :avatar }
|
90
84
|
# [ :books, { author: :avatar } ]
|
91
|
-
|
92
|
-
NULL_RELATION = Struct.new(:values, :bind_values).new({}, [])
|
93
|
-
|
94
85
|
def preload(records, associations, preload_scope = nil)
|
95
|
-
records
|
96
|
-
associations = Array.wrap(associations)
|
97
|
-
preload_scope = preload_scope || NULL_RELATION
|
86
|
+
records = Array.wrap(records).compact
|
98
87
|
|
99
88
|
if records.empty?
|
100
89
|
[]
|
101
90
|
else
|
102
|
-
associations.flat_map { |association|
|
91
|
+
Array.wrap(associations).flat_map { |association|
|
103
92
|
preloaders_on association, records, preload_scope
|
104
93
|
}
|
105
94
|
end
|
106
95
|
end
|
107
96
|
|
108
97
|
private
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
raise ArgumentError, "#{association.inspect} was not recognised for preload"
|
98
|
+
# Loads all the given data into +records+ for the +association+.
|
99
|
+
def preloaders_on(association, records, scope, polymorphic_parent = false)
|
100
|
+
case association
|
101
|
+
when Hash
|
102
|
+
preloaders_for_hash(association, records, scope, polymorphic_parent)
|
103
|
+
when Symbol, String
|
104
|
+
preloaders_for_one(association, records, scope, polymorphic_parent)
|
105
|
+
else
|
106
|
+
raise ArgumentError, "#{association.inspect} was not recognized for preload"
|
107
|
+
end
|
120
108
|
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def preloaders_for_hash(association, records, scope)
|
124
|
-
association.flat_map { |parent, child|
|
125
|
-
loaders = preloaders_for_one parent, records, scope
|
126
109
|
|
127
|
-
|
128
|
-
|
129
|
-
|
110
|
+
def preloaders_for_hash(association, records, scope, polymorphic_parent)
|
111
|
+
association.flat_map { |parent, child|
|
112
|
+
grouped_records(parent, records, polymorphic_parent).flat_map do |reflection, reflection_records|
|
113
|
+
loaders = preloaders_for_reflection(reflection, reflection_records, scope)
|
114
|
+
recs = loaders.flat_map(&:preloaded_records).uniq
|
115
|
+
child_polymorphic_parent = reflection && reflection.options[:polymorphic]
|
116
|
+
loaders.concat Array.wrap(child).flat_map { |assoc|
|
117
|
+
preloaders_on assoc, recs, scope, child_polymorphic_parent
|
118
|
+
}
|
119
|
+
loaders
|
120
|
+
end
|
130
121
|
}
|
131
|
-
loaders
|
132
|
-
}
|
133
|
-
end
|
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)
|
143
|
-
grouped_records(association, records).flat_map do |reflection, klasses|
|
144
|
-
klasses.map do |rhs_klass, rs|
|
145
|
-
loader = preloader_for(reflection, rs, rhs_klass).new(rhs_klass, rs, reflection, scope)
|
146
|
-
loader.run self
|
147
|
-
loader
|
148
|
-
end
|
149
122
|
end
|
150
|
-
end
|
151
123
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
124
|
+
# Loads all the given data into +records+ for a singular +association+.
|
125
|
+
#
|
126
|
+
# Functions by instantiating a preloader class such as Preloader::Association and
|
127
|
+
# call the +run+ method for each passed in class in the +records+ argument.
|
128
|
+
#
|
129
|
+
# Not all records have the same class, so group then preload group on the reflection
|
130
|
+
# itself so that if various subclass share the same association then we do not split
|
131
|
+
# them unnecessarily
|
132
|
+
#
|
133
|
+
# Additionally, polymorphic belongs_to associations can have multiple associated
|
134
|
+
# classes, depending on the polymorphic_type field. So we group by the classes as
|
135
|
+
# well.
|
136
|
+
def preloaders_for_one(association, records, scope, polymorphic_parent)
|
137
|
+
grouped_records(association, records, polymorphic_parent)
|
138
|
+
.flat_map do |reflection, reflection_records|
|
139
|
+
preloaders_for_reflection reflection, reflection_records, scope
|
140
|
+
end
|
159
141
|
end
|
160
|
-
h
|
161
|
-
end
|
162
142
|
|
163
|
-
|
164
|
-
|
143
|
+
def preloaders_for_reflection(reflection, records, scope)
|
144
|
+
records.group_by { |record| record.association(reflection.name).klass }.map do |rhs_klass, rs|
|
145
|
+
preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope).run
|
146
|
+
end
|
147
|
+
end
|
165
148
|
|
166
|
-
def
|
167
|
-
|
168
|
-
|
149
|
+
def grouped_records(association, records, polymorphic_parent)
|
150
|
+
h = {}
|
151
|
+
records.each do |record|
|
152
|
+
reflection = record.class._reflect_on_association(association)
|
153
|
+
next if polymorphic_parent && !reflection || !record.association(association).klass
|
154
|
+
(h[reflection] ||= []) << record
|
155
|
+
end
|
156
|
+
h
|
169
157
|
end
|
170
158
|
|
171
|
-
|
159
|
+
class AlreadyLoaded # :nodoc:
|
160
|
+
def initialize(klass, owners, reflection, preload_scope)
|
161
|
+
@owners = owners
|
162
|
+
@reflection = reflection
|
163
|
+
end
|
172
164
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
end
|
165
|
+
def run
|
166
|
+
self
|
167
|
+
end
|
177
168
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
def self.preloaded_records; []; end
|
182
|
-
end
|
169
|
+
def preloaded_records
|
170
|
+
@preloaded_records ||= records_by_owner.flat_map(&:last)
|
171
|
+
end
|
183
172
|
|
184
|
-
|
185
|
-
|
173
|
+
def records_by_owner
|
174
|
+
@records_by_owner ||= owners.each_with_object({}) do |owner, result|
|
175
|
+
result[owner] = Array(owner.association(reflection.name).target)
|
176
|
+
end
|
177
|
+
end
|
186
178
|
|
187
|
-
|
188
|
-
|
179
|
+
private
|
180
|
+
attr_reader :owners, :reflection
|
189
181
|
end
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
182
|
+
|
183
|
+
# Returns a class containing the logic needed to load preload the data
|
184
|
+
# and attach it to a relation. The class returned implements a `run` method
|
185
|
+
# that accepts a preloader.
|
186
|
+
def preloader_for(reflection, owners)
|
187
|
+
if owners.all? { |o| o.association(reflection.name).loaded? }
|
188
|
+
return AlreadyLoaded
|
189
|
+
end
|
190
|
+
reflection.check_preloadable!
|
191
|
+
|
192
|
+
if reflection.options[:through]
|
193
|
+
ThroughAssociation
|
194
|
+
else
|
195
|
+
Association
|
196
|
+
end
|
199
197
|
end
|
200
|
-
end
|
201
198
|
end
|
202
199
|
end
|
203
200
|
end
|