activerecord 4.2.11.1 → 6.0.3.5
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 +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,6 +1,10 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            require  
     | 
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "active_record/relation/from_clause"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "active_record/relation/query_attribute"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "active_record/relation/where_clause"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "active_record/relation/where_clause_factory"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "active_model/forbidden_attributes_protection"
         
     | 
| 
       4 
8 
     | 
    
         | 
| 
       5 
9 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       6 
10 
     | 
    
         
             
              module QueryMethods
         
     | 
| 
         @@ -11,6 +15,8 @@ module ActiveRecord 
     | 
|
| 
       11 
15 
     | 
    
         
             
                # WhereChain objects act as placeholder for queries in which #where does not have any parameter.
         
     | 
| 
       12 
16 
     | 
    
         
             
                # In this case, #where must be chained with #not to return a new relation.
         
     | 
| 
       13 
17 
     | 
    
         
             
                class WhereChain
         
     | 
| 
      
 18 
     | 
    
         
            +
                  include ActiveModel::ForbiddenAttributesProtection
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       14 
20 
     | 
    
         
             
                  def initialize(scope)
         
     | 
| 
       15 
21 
     | 
    
         
             
                    @scope = scope
         
     | 
| 
       16 
22 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -18,7 +24,7 @@ module ActiveRecord 
     | 
|
| 
       18 
24 
     | 
    
         
             
                  # Returns a new relation expressing WHERE + NOT condition according to
         
     | 
| 
       19 
25 
     | 
    
         
             
                  # the conditions in the arguments.
         
     | 
| 
       20 
26 
     | 
    
         
             
                  #
         
     | 
| 
       21 
     | 
    
         
            -
                  #  
     | 
| 
      
 27 
     | 
    
         
            +
                  # #not accepts conditions as a string, array, or hash. See QueryMethods#where for
         
     | 
| 
       22 
28 
     | 
    
         
             
                  # more details on each format.
         
     | 
| 
       23 
29 
     | 
    
         
             
                  #
         
     | 
| 
       24 
30 
     | 
    
         
             
                  #    User.where.not("name = 'Jon'")
         
     | 
| 
         @@ -35,77 +41,67 @@ module ActiveRecord 
     | 
|
| 
       35 
41 
     | 
    
         
             
                  #
         
     | 
| 
       36 
42 
     | 
    
         
             
                  #    User.where.not(name: %w(Ko1 Nobu))
         
     | 
| 
       37 
43 
     | 
    
         
             
                  #    # SELECT * FROM users WHERE name NOT IN ('Ko1', 'Nobu')
         
     | 
| 
       38 
     | 
    
         
            -
                  #
         
     | 
| 
       39 
     | 
    
         
            -
                  #    User.where.not(name: "Jon", role: "admin")
         
     | 
| 
       40 
     | 
    
         
            -
                  #    # SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'
         
     | 
| 
       41 
44 
     | 
    
         
             
                  def not(opts, *rest)
         
     | 
| 
       42 
     | 
    
         
            -
                     
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                        raise ArgumentError, 'Invalid argument for .where.not(), got nil.'
         
     | 
| 
       46 
     | 
    
         
            -
                      when Arel::Nodes::In
         
     | 
| 
       47 
     | 
    
         
            -
                        Arel::Nodes::NotIn.new(rel.left, rel.right)
         
     | 
| 
       48 
     | 
    
         
            -
                      when Arel::Nodes::Equality
         
     | 
| 
       49 
     | 
    
         
            -
                        Arel::Nodes::NotEqual.new(rel.left, rel.right)
         
     | 
| 
       50 
     | 
    
         
            -
                      when String
         
     | 
| 
       51 
     | 
    
         
            -
                        Arel::Nodes::Not.new(Arel::Nodes::SqlLiteral.new(rel))
         
     | 
| 
       52 
     | 
    
         
            -
                      else
         
     | 
| 
       53 
     | 
    
         
            -
                        Arel::Nodes::Not.new(rel)
         
     | 
| 
       54 
     | 
    
         
            -
                      end
         
     | 
| 
       55 
     | 
    
         
            -
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                    opts = sanitize_forbidden_attributes(opts)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    where_clause = @scope.send(:where_clause_factory).build(opts, rest)
         
     | 
| 
       56 
48 
     | 
    
         | 
| 
       57 
49 
     | 
    
         
             
                    @scope.references!(PredicateBuilder.references(opts)) if Hash === opts
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    if not_behaves_as_nor?(opts)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      ActiveSupport::Deprecation.warn(<<~MSG.squish)
         
     | 
| 
      
 53 
     | 
    
         
            +
                        NOT conditions will no longer behave as NOR in Rails 6.1.
         
     | 
| 
      
 54 
     | 
    
         
            +
                        To continue using NOR conditions, NOT each condition individually
         
     | 
| 
      
 55 
     | 
    
         
            +
                        (`#{
         
     | 
| 
      
 56 
     | 
    
         
            +
                          opts.flat_map { |key, value|
         
     | 
| 
      
 57 
     | 
    
         
            +
                            if value.is_a?(Hash) && value.size > 1
         
     | 
| 
      
 58 
     | 
    
         
            +
                              value.map { |k, v| ".where.not(#{key.inspect} => { #{k.inspect} => ... })" }
         
     | 
| 
      
 59 
     | 
    
         
            +
                            else
         
     | 
| 
      
 60 
     | 
    
         
            +
                              ".where.not(#{key.inspect} => ...)"
         
     | 
| 
      
 61 
     | 
    
         
            +
                            end
         
     | 
| 
      
 62 
     | 
    
         
            +
                          }.join
         
     | 
| 
      
 63 
     | 
    
         
            +
                        }`).
         
     | 
| 
      
 64 
     | 
    
         
            +
                      MSG
         
     | 
| 
      
 65 
     | 
    
         
            +
                      @scope.where_clause += where_clause.invert(:nor)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    else
         
     | 
| 
      
 67 
     | 
    
         
            +
                      @scope.where_clause += where_clause.invert
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
       59 
70 
     | 
    
         
             
                    @scope
         
     | 
| 
       60 
71 
     | 
    
         
             
                  end
         
     | 
| 
       61 
     | 
    
         
            -
                end
         
     | 
| 
       62 
72 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                     
     | 
| 
       70 
     | 
    
         
            -
                      raise ImmutableRelation if @loaded #   raise ImmutableRelation if @loaded
         
     | 
| 
       71 
     | 
    
         
            -
                      check_cached_relation
         
     | 
| 
       72 
     | 
    
         
            -
                      @values[:#{name}] = values         #   @values[:select] = values
         
     | 
| 
       73 
     | 
    
         
            -
                    end                                  # end
         
     | 
| 
       74 
     | 
    
         
            -
                  CODE
         
     | 
| 
      
 73 
     | 
    
         
            +
                  private
         
     | 
| 
      
 74 
     | 
    
         
            +
                    def not_behaves_as_nor?(opts)
         
     | 
| 
      
 75 
     | 
    
         
            +
                      return false unless opts.is_a?(Hash)
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                      opts.any? { |k, v| v.is_a?(Hash) && v.size > 1 } ||
         
     | 
| 
      
 78 
     | 
    
         
            +
                        opts.size > 1
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
       75 
80 
     | 
    
         
             
                end
         
     | 
| 
       76 
81 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
                 
     | 
| 
      
 82 
     | 
    
         
            +
                FROZEN_EMPTY_ARRAY = [].freeze
         
     | 
| 
      
 83 
     | 
    
         
            +
                FROZEN_EMPTY_HASH = {}.freeze
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                Relation::VALUE_METHODS.each do |name|
         
     | 
| 
      
 86 
     | 
    
         
            +
                  method_name = \
         
     | 
| 
      
 87 
     | 
    
         
            +
                    case name
         
     | 
| 
      
 88 
     | 
    
         
            +
                    when *Relation::MULTI_VALUE_METHODS then "#{name}_values"
         
     | 
| 
      
 89 
     | 
    
         
            +
                    when *Relation::SINGLE_VALUE_METHODS then "#{name}_value"
         
     | 
| 
      
 90 
     | 
    
         
            +
                    when *Relation::CLAUSE_METHODS then "#{name}_clause"
         
     | 
| 
      
 91 
     | 
    
         
            +
                    end
         
     | 
| 
       78 
92 
     | 
    
         
             
                  class_eval <<-CODE, __FILE__, __LINE__ + 1
         
     | 
| 
       79 
     | 
    
         
            -
                    def #{ 
     | 
| 
       80 
     | 
    
         
            -
                       
     | 
| 
      
 93 
     | 
    
         
            +
                    def #{method_name}                   # def includes_values
         
     | 
| 
      
 94 
     | 
    
         
            +
                      default = DEFAULT_VALUES[:#{name}] #   default = DEFAULT_VALUES[:includes]
         
     | 
| 
      
 95 
     | 
    
         
            +
                      @values.fetch(:#{name}, default)   #   @values.fetch(:includes, default)
         
     | 
| 
       81 
96 
     | 
    
         
             
                    end                                  # end
         
     | 
| 
       82 
     | 
    
         
            -
                  CODE
         
     | 
| 
       83 
     | 
    
         
            -
                end
         
     | 
| 
       84 
97 
     | 
    
         | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
                      raise ImmutableRelation if @loaded #   raise ImmutableRelation if @loaded
         
     | 
| 
       89 
     | 
    
         
            -
                      check_cached_relation
         
     | 
| 
       90 
     | 
    
         
            -
                      @values[:#{name}] = value          #   @values[:readonly] = value
         
     | 
| 
      
 98 
     | 
    
         
            +
                    def #{method_name}=(value)           # def includes_values=(value)
         
     | 
| 
      
 99 
     | 
    
         
            +
                      assert_mutability!                 #   assert_mutability!
         
     | 
| 
      
 100 
     | 
    
         
            +
                      @values[:#{name}] = value          #   @values[:includes] = value
         
     | 
| 
       91 
101 
     | 
    
         
             
                    end                                  # end
         
     | 
| 
       92 
102 
     | 
    
         
             
                  CODE
         
     | 
| 
       93 
103 
     | 
    
         
             
                end
         
     | 
| 
       94 
104 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
                def check_cached_relation # :nodoc:
         
     | 
| 
       96 
     | 
    
         
            -
                  if defined?(@arel) && @arel
         
     | 
| 
       97 
     | 
    
         
            -
                    @arel = nil
         
     | 
| 
       98 
     | 
    
         
            -
                    ActiveSupport::Deprecation.warn(<<-MSG.squish)
         
     | 
| 
       99 
     | 
    
         
            -
                      Modifying already cached Relation. The cache will be reset. Use a
         
     | 
| 
       100 
     | 
    
         
            -
                      cloned Relation to prevent this warning.
         
     | 
| 
       101 
     | 
    
         
            -
                    MSG
         
     | 
| 
       102 
     | 
    
         
            -
                  end
         
     | 
| 
       103 
     | 
    
         
            -
                end
         
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
                def create_with_value # :nodoc:
         
     | 
| 
       106 
     | 
    
         
            -
                  @values[:create_with] || {}
         
     | 
| 
       107 
     | 
    
         
            -
                end
         
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
105 
     | 
    
         
             
                alias extensions extending_values
         
     | 
| 
       110 
106 
     | 
    
         | 
| 
       111 
107 
     | 
    
         
             
                # Specify relationships to be included in the result set. For
         
     | 
| 
         @@ -118,7 +114,7 @@ module ActiveRecord 
     | 
|
| 
       118 
114 
     | 
    
         
             
                #
         
     | 
| 
       119 
115 
     | 
    
         
             
                # allows you to access the +address+ attribute of the +User+ model without
         
     | 
| 
       120 
116 
     | 
    
         
             
                # firing an additional query. This will often result in a
         
     | 
| 
       121 
     | 
    
         
            -
                # performance improvement over a simple  
     | 
| 
      
 117 
     | 
    
         
            +
                # performance improvement over a simple join.
         
     | 
| 
       122 
118 
     | 
    
         
             
                #
         
     | 
| 
       123 
119 
     | 
    
         
             
                # You can also specify multiple relationships, like this:
         
     | 
| 
       124 
120 
     | 
    
         
             
                #
         
     | 
| 
         @@ -130,7 +126,7 @@ module ActiveRecord 
     | 
|
| 
       130 
126 
     | 
    
         
             
                #
         
     | 
| 
       131 
127 
     | 
    
         
             
                # === conditions
         
     | 
| 
       132 
128 
     | 
    
         
             
                #
         
     | 
| 
       133 
     | 
    
         
            -
                # If you want to add conditions to your included models you'll have
         
     | 
| 
      
 129 
     | 
    
         
            +
                # If you want to add string conditions to your included models, you'll have
         
     | 
| 
       134 
130 
     | 
    
         
             
                # to explicitly reference them. For example:
         
     | 
| 
       135 
131 
     | 
    
         
             
                #
         
     | 
| 
       136 
132 
     | 
    
         
             
                #   User.includes(:posts).where('posts.name = ?', 'example')
         
     | 
| 
         @@ -139,8 +135,14 @@ module ActiveRecord 
     | 
|
| 
       139 
135 
     | 
    
         
             
                #
         
     | 
| 
       140 
136 
     | 
    
         
             
                #   User.includes(:posts).where('posts.name = ?', 'example').references(:posts)
         
     | 
| 
       141 
137 
     | 
    
         
             
                #
         
     | 
| 
       142 
     | 
    
         
            -
                # Note that  
     | 
| 
      
 138 
     | 
    
         
            +
                # Note that #includes works with association names while #references needs
         
     | 
| 
       143 
139 
     | 
    
         
             
                # the actual table name.
         
     | 
| 
      
 140 
     | 
    
         
            +
                #
         
     | 
| 
      
 141 
     | 
    
         
            +
                # If you pass the conditions via hash, you don't need to call #references
         
     | 
| 
      
 142 
     | 
    
         
            +
                # explicitly, as #where references the tables for you. For example, this
         
     | 
| 
      
 143 
     | 
    
         
            +
                # will work correctly:
         
     | 
| 
      
 144 
     | 
    
         
            +
                #
         
     | 
| 
      
 145 
     | 
    
         
            +
                #   User.includes(:posts).where(posts: { name: 'example' })
         
     | 
| 
       144 
146 
     | 
    
         
             
                def includes(*args)
         
     | 
| 
       145 
147 
     | 
    
         
             
                  check_if_method_has_arguments!(:includes, args)
         
     | 
| 
       146 
148 
     | 
    
         
             
                  spawn.includes!(*args)
         
     | 
| 
         @@ -157,43 +159,56 @@ module ActiveRecord 
     | 
|
| 
       157 
159 
     | 
    
         
             
                # Forces eager loading by performing a LEFT OUTER JOIN on +args+:
         
     | 
| 
       158 
160 
     | 
    
         
             
                #
         
     | 
| 
       159 
161 
     | 
    
         
             
                #   User.eager_load(:posts)
         
     | 
| 
       160 
     | 
    
         
            -
                #    
     | 
| 
       161 
     | 
    
         
            -
                #   FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" =
         
     | 
| 
       162 
     | 
    
         
            -
                #   "users"."id"
         
     | 
| 
      
 162 
     | 
    
         
            +
                #   # SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, ...
         
     | 
| 
      
 163 
     | 
    
         
            +
                #   # FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" =
         
     | 
| 
      
 164 
     | 
    
         
            +
                #   # "users"."id"
         
     | 
| 
       163 
165 
     | 
    
         
             
                def eager_load(*args)
         
     | 
| 
       164 
166 
     | 
    
         
             
                  check_if_method_has_arguments!(:eager_load, args)
         
     | 
| 
       165 
167 
     | 
    
         
             
                  spawn.eager_load!(*args)
         
     | 
| 
       166 
168 
     | 
    
         
             
                end
         
     | 
| 
       167 
169 
     | 
    
         | 
| 
       168 
170 
     | 
    
         
             
                def eager_load!(*args) # :nodoc:
         
     | 
| 
       169 
     | 
    
         
            -
                  self.eager_load_values  
     | 
| 
      
 171 
     | 
    
         
            +
                  self.eager_load_values |= args
         
     | 
| 
       170 
172 
     | 
    
         
             
                  self
         
     | 
| 
       171 
173 
     | 
    
         
             
                end
         
     | 
| 
       172 
174 
     | 
    
         | 
| 
       173 
     | 
    
         
            -
                # Allows preloading of +args+, in the same way that  
     | 
| 
      
 175 
     | 
    
         
            +
                # Allows preloading of +args+, in the same way that #includes does:
         
     | 
| 
       174 
176 
     | 
    
         
             
                #
         
     | 
| 
       175 
177 
     | 
    
         
             
                #   User.preload(:posts)
         
     | 
| 
       176 
     | 
    
         
            -
                #    
     | 
| 
      
 178 
     | 
    
         
            +
                #   # SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (1, 2, 3)
         
     | 
| 
       177 
179 
     | 
    
         
             
                def preload(*args)
         
     | 
| 
       178 
180 
     | 
    
         
             
                  check_if_method_has_arguments!(:preload, args)
         
     | 
| 
       179 
181 
     | 
    
         
             
                  spawn.preload!(*args)
         
     | 
| 
       180 
182 
     | 
    
         
             
                end
         
     | 
| 
       181 
183 
     | 
    
         | 
| 
       182 
184 
     | 
    
         
             
                def preload!(*args) # :nodoc:
         
     | 
| 
       183 
     | 
    
         
            -
                  self.preload_values  
     | 
| 
      
 185 
     | 
    
         
            +
                  self.preload_values |= args
         
     | 
| 
       184 
186 
     | 
    
         
             
                  self
         
     | 
| 
       185 
187 
     | 
    
         
             
                end
         
     | 
| 
       186 
188 
     | 
    
         | 
| 
      
 189 
     | 
    
         
            +
                # Extracts a named +association+ from the relation. The named association is first preloaded,
         
     | 
| 
      
 190 
     | 
    
         
            +
                # then the individual association records are collected from the relation. Like so:
         
     | 
| 
      
 191 
     | 
    
         
            +
                #
         
     | 
| 
      
 192 
     | 
    
         
            +
                #   account.memberships.extract_associated(:user)
         
     | 
| 
      
 193 
     | 
    
         
            +
                #   # => Returns collection of User records
         
     | 
| 
      
 194 
     | 
    
         
            +
                #
         
     | 
| 
      
 195 
     | 
    
         
            +
                # This is short-hand for:
         
     | 
| 
      
 196 
     | 
    
         
            +
                #
         
     | 
| 
      
 197 
     | 
    
         
            +
                #   account.memberships.preload(:user).collect(&:user)
         
     | 
| 
      
 198 
     | 
    
         
            +
                def extract_associated(association)
         
     | 
| 
      
 199 
     | 
    
         
            +
                  preload(association).collect(&association)
         
     | 
| 
      
 200 
     | 
    
         
            +
                end
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
       187 
202 
     | 
    
         
             
                # Use to indicate that the given +table_names+ are referenced by an SQL string,
         
     | 
| 
       188 
203 
     | 
    
         
             
                # and should therefore be JOINed in any query rather than loaded separately.
         
     | 
| 
       189 
     | 
    
         
            -
                # This method only works in conjunction with  
     | 
| 
      
 204 
     | 
    
         
            +
                # This method only works in conjunction with #includes.
         
     | 
| 
       190 
205 
     | 
    
         
             
                # See #includes for more details.
         
     | 
| 
       191 
206 
     | 
    
         
             
                #
         
     | 
| 
       192 
207 
     | 
    
         
             
                #   User.includes(:posts).where("posts.name = 'foo'")
         
     | 
| 
       193 
     | 
    
         
            -
                #   #  
     | 
| 
      
 208 
     | 
    
         
            +
                #   # Doesn't JOIN the posts table, resulting in an error.
         
     | 
| 
       194 
209 
     | 
    
         
             
                #
         
     | 
| 
       195 
210 
     | 
    
         
             
                #   User.includes(:posts).where("posts.name = 'foo'").references(:posts)
         
     | 
| 
       196 
     | 
    
         
            -
                #   #  
     | 
| 
      
 211 
     | 
    
         
            +
                #   # Query now knows the string references posts, so adds a JOIN
         
     | 
| 
       197 
212 
     | 
    
         
             
                def references(*table_names)
         
     | 
| 
       198 
213 
     | 
    
         
             
                  check_if_method_has_arguments!(:references, table_names)
         
     | 
| 
       199 
214 
     | 
    
         
             
                  spawn.references!(*table_names)
         
     | 
| 
         @@ -209,12 +224,13 @@ module ActiveRecord 
     | 
|
| 
       209 
224 
     | 
    
         | 
| 
       210 
225 
     | 
    
         
             
                # Works in two unique ways.
         
     | 
| 
       211 
226 
     | 
    
         
             
                #
         
     | 
| 
       212 
     | 
    
         
            -
                # First: takes a block so it can be used just like Array#select 
     | 
| 
      
 227 
     | 
    
         
            +
                # First: takes a block so it can be used just like <tt>Array#select</tt>.
         
     | 
| 
       213 
228 
     | 
    
         
             
                #
         
     | 
| 
       214 
229 
     | 
    
         
             
                #   Model.all.select { |m| m.field == value }
         
     | 
| 
       215 
230 
     | 
    
         
             
                #
         
     | 
| 
       216 
231 
     | 
    
         
             
                # This will build an array of objects from the database for the scope,
         
     | 
| 
       217 
     | 
    
         
            -
                # converting them into an array and iterating through them using 
     | 
| 
      
 232 
     | 
    
         
            +
                # converting them into an array and iterating through them using
         
     | 
| 
      
 233 
     | 
    
         
            +
                # <tt>Array#select</tt>.
         
     | 
| 
       218 
234 
     | 
    
         
             
                #
         
     | 
| 
       219 
235 
     | 
    
         
             
                # Second: Modifies the SELECT statement for the query so that only certain
         
     | 
| 
       220 
236 
     | 
    
         
             
                # fields are retrieved:
         
     | 
| 
         @@ -242,47 +258,71 @@ module ActiveRecord 
     | 
|
| 
       242 
258 
     | 
    
         
             
                #   # => "value"
         
     | 
| 
       243 
259 
     | 
    
         
             
                #
         
     | 
| 
       244 
260 
     | 
    
         
             
                # Accessing attributes of an object that do not have fields retrieved by a select
         
     | 
| 
       245 
     | 
    
         
            -
                # except +id+ will throw  
     | 
| 
      
 261 
     | 
    
         
            +
                # except +id+ will throw ActiveModel::MissingAttributeError:
         
     | 
| 
       246 
262 
     | 
    
         
             
                #
         
     | 
| 
       247 
263 
     | 
    
         
             
                #   Model.select(:field).first.other_field
         
     | 
| 
       248 
264 
     | 
    
         
             
                #   # => ActiveModel::MissingAttributeError: missing attribute: other_field
         
     | 
| 
       249 
265 
     | 
    
         
             
                def select(*fields)
         
     | 
| 
       250 
266 
     | 
    
         
             
                  if block_given?
         
     | 
| 
       251 
     | 
    
         
            -
                     
     | 
| 
       252 
     | 
    
         
            -
             
     | 
| 
       253 
     | 
    
         
            -
                     
     | 
| 
       254 
     | 
    
         
            -
             
     | 
| 
      
 267 
     | 
    
         
            +
                    if fields.any?
         
     | 
| 
      
 268 
     | 
    
         
            +
                      raise ArgumentError, "`select' with block doesn't take arguments."
         
     | 
| 
      
 269 
     | 
    
         
            +
                    end
         
     | 
| 
      
 270 
     | 
    
         
            +
             
     | 
| 
      
 271 
     | 
    
         
            +
                    return super()
         
     | 
| 
       255 
272 
     | 
    
         
             
                  end
         
     | 
| 
      
 273 
     | 
    
         
            +
             
     | 
| 
      
 274 
     | 
    
         
            +
                  raise ArgumentError, "Call `select' with at least one field" if fields.empty?
         
     | 
| 
      
 275 
     | 
    
         
            +
                  spawn._select!(*fields)
         
     | 
| 
       256 
276 
     | 
    
         
             
                end
         
     | 
| 
       257 
277 
     | 
    
         | 
| 
       258 
278 
     | 
    
         
             
                def _select!(*fields) # :nodoc:
         
     | 
| 
      
 279 
     | 
    
         
            +
                  fields.reject!(&:blank?)
         
     | 
| 
       259 
280 
     | 
    
         
             
                  fields.flatten!
         
     | 
| 
       260 
     | 
    
         
            -
                  fields.map! do |field|
         
     | 
| 
       261 
     | 
    
         
            -
                    klass.attribute_alias?(field) ? klass.attribute_alias(field).to_sym : field
         
     | 
| 
       262 
     | 
    
         
            -
                  end
         
     | 
| 
       263 
281 
     | 
    
         
             
                  self.select_values += fields
         
     | 
| 
       264 
282 
     | 
    
         
             
                  self
         
     | 
| 
       265 
283 
     | 
    
         
             
                end
         
     | 
| 
       266 
284 
     | 
    
         | 
| 
      
 285 
     | 
    
         
            +
                # Allows you to change a previously set select statement.
         
     | 
| 
      
 286 
     | 
    
         
            +
                #
         
     | 
| 
      
 287 
     | 
    
         
            +
                #   Post.select(:title, :body)
         
     | 
| 
      
 288 
     | 
    
         
            +
                #   # SELECT `posts`.`title`, `posts`.`body` FROM `posts`
         
     | 
| 
      
 289 
     | 
    
         
            +
                #
         
     | 
| 
      
 290 
     | 
    
         
            +
                #   Post.select(:title, :body).reselect(:created_at)
         
     | 
| 
      
 291 
     | 
    
         
            +
                #   # SELECT `posts`.`created_at` FROM `posts`
         
     | 
| 
      
 292 
     | 
    
         
            +
                #
         
     | 
| 
      
 293 
     | 
    
         
            +
                # This is short-hand for <tt>unscope(:select).select(fields)</tt>.
         
     | 
| 
      
 294 
     | 
    
         
            +
                # Note that we're unscoping the entire select statement.
         
     | 
| 
      
 295 
     | 
    
         
            +
                def reselect(*args)
         
     | 
| 
      
 296 
     | 
    
         
            +
                  check_if_method_has_arguments!(:reselect, args)
         
     | 
| 
      
 297 
     | 
    
         
            +
                  spawn.reselect!(*args)
         
     | 
| 
      
 298 
     | 
    
         
            +
                end
         
     | 
| 
      
 299 
     | 
    
         
            +
             
     | 
| 
      
 300 
     | 
    
         
            +
                # Same as #reselect but operates on relation in-place instead of copying.
         
     | 
| 
      
 301 
     | 
    
         
            +
                def reselect!(*args) # :nodoc:
         
     | 
| 
      
 302 
     | 
    
         
            +
                  self.select_values = args
         
     | 
| 
      
 303 
     | 
    
         
            +
                  self
         
     | 
| 
      
 304 
     | 
    
         
            +
                end
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
       267 
306 
     | 
    
         
             
                # Allows to specify a group attribute:
         
     | 
| 
       268 
307 
     | 
    
         
             
                #
         
     | 
| 
       269 
308 
     | 
    
         
             
                #   User.group(:name)
         
     | 
| 
       270 
     | 
    
         
            -
                #    
     | 
| 
      
 309 
     | 
    
         
            +
                #   # SELECT "users".* FROM "users" GROUP BY name
         
     | 
| 
       271 
310 
     | 
    
         
             
                #
         
     | 
| 
       272 
311 
     | 
    
         
             
                # Returns an array with distinct records based on the +group+ attribute:
         
     | 
| 
       273 
312 
     | 
    
         
             
                #
         
     | 
| 
       274 
313 
     | 
    
         
             
                #   User.select([:id, :name])
         
     | 
| 
       275 
     | 
    
         
            -
                #   => [#<User id: 1, name: "Oscar">, #<User id: 2, name: "Oscar">, #<User id: 3, name: "Foo">
         
     | 
| 
      
 314 
     | 
    
         
            +
                #   # => [#<User id: 1, name: "Oscar">, #<User id: 2, name: "Oscar">, #<User id: 3, name: "Foo">]
         
     | 
| 
       276 
315 
     | 
    
         
             
                #
         
     | 
| 
       277 
316 
     | 
    
         
             
                #   User.group(:name)
         
     | 
| 
       278 
     | 
    
         
            -
                #   => [#<User id: 3, name: "Foo", ...>, #<User id: 2, name: "Oscar", ...>]
         
     | 
| 
      
 317 
     | 
    
         
            +
                #   # => [#<User id: 3, name: "Foo", ...>, #<User id: 2, name: "Oscar", ...>]
         
     | 
| 
       279 
318 
     | 
    
         
             
                #
         
     | 
| 
       280 
319 
     | 
    
         
             
                #   User.group('name AS grouped_name, age')
         
     | 
| 
       281 
     | 
    
         
            -
                #   => [#<User id: 3, name: "Foo", age: 21, ...>, #<User id: 2, name: "Oscar", age: 21, ...>, #<User id: 5, name: "Foo", age: 23, ...>]
         
     | 
| 
      
 320 
     | 
    
         
            +
                #   # => [#<User id: 3, name: "Foo", age: 21, ...>, #<User id: 2, name: "Oscar", age: 21, ...>, #<User id: 5, name: "Foo", age: 23, ...>]
         
     | 
| 
       282 
321 
     | 
    
         
             
                #
         
     | 
| 
       283 
322 
     | 
    
         
             
                # Passing in an array of attributes to group by is also supported.
         
     | 
| 
      
 323 
     | 
    
         
            +
                #
         
     | 
| 
       284 
324 
     | 
    
         
             
                #   User.select([:id, :first_name]).group(:id, :first_name).first(3)
         
     | 
| 
       285 
     | 
    
         
            -
                #   => [#<User id: 1, first_name: "Bill">, #<User id: 2, first_name: "Earl">, #<User id: 3, first_name: "Beto">]
         
     | 
| 
      
 325 
     | 
    
         
            +
                #   # => [#<User id: 1, first_name: "Bill">, #<User id: 2, first_name: "Earl">, #<User id: 3, first_name: "Beto">]
         
     | 
| 
       286 
326 
     | 
    
         
             
                def group(*args)
         
     | 
| 
       287 
327 
     | 
    
         
             
                  check_if_method_has_arguments!(:group, args)
         
     | 
| 
       288 
328 
     | 
    
         
             
                  spawn.group!(*args)
         
     | 
| 
         @@ -291,34 +331,35 @@ module ActiveRecord 
     | 
|
| 
       291 
331 
     | 
    
         
             
                def group!(*args) # :nodoc:
         
     | 
| 
       292 
332 
     | 
    
         
             
                  args.flatten!
         
     | 
| 
       293 
333 
     | 
    
         | 
| 
       294 
     | 
    
         
            -
                  self.group_values  
     | 
| 
      
 334 
     | 
    
         
            +
                  self.group_values |= args
         
     | 
| 
       295 
335 
     | 
    
         
             
                  self
         
     | 
| 
       296 
336 
     | 
    
         
             
                end
         
     | 
| 
       297 
337 
     | 
    
         | 
| 
       298 
338 
     | 
    
         
             
                # Allows to specify an order attribute:
         
     | 
| 
       299 
339 
     | 
    
         
             
                #
         
     | 
| 
       300 
340 
     | 
    
         
             
                #   User.order(:name)
         
     | 
| 
       301 
     | 
    
         
            -
                #    
     | 
| 
      
 341 
     | 
    
         
            +
                #   # SELECT "users".* FROM "users" ORDER BY "users"."name" ASC
         
     | 
| 
       302 
342 
     | 
    
         
             
                #
         
     | 
| 
       303 
343 
     | 
    
         
             
                #   User.order(email: :desc)
         
     | 
| 
       304 
     | 
    
         
            -
                #    
     | 
| 
      
 344 
     | 
    
         
            +
                #   # SELECT "users".* FROM "users" ORDER BY "users"."email" DESC
         
     | 
| 
       305 
345 
     | 
    
         
             
                #
         
     | 
| 
       306 
346 
     | 
    
         
             
                #   User.order(:name, email: :desc)
         
     | 
| 
       307 
     | 
    
         
            -
                #    
     | 
| 
      
 347 
     | 
    
         
            +
                #   # SELECT "users".* FROM "users" ORDER BY "users"."name" ASC, "users"."email" DESC
         
     | 
| 
       308 
348 
     | 
    
         
             
                #
         
     | 
| 
       309 
349 
     | 
    
         
             
                #   User.order('name')
         
     | 
| 
       310 
     | 
    
         
            -
                #    
     | 
| 
      
 350 
     | 
    
         
            +
                #   # SELECT "users".* FROM "users" ORDER BY name
         
     | 
| 
       311 
351 
     | 
    
         
             
                #
         
     | 
| 
       312 
352 
     | 
    
         
             
                #   User.order('name DESC')
         
     | 
| 
       313 
     | 
    
         
            -
                #    
     | 
| 
      
 353 
     | 
    
         
            +
                #   # SELECT "users".* FROM "users" ORDER BY name DESC
         
     | 
| 
       314 
354 
     | 
    
         
             
                #
         
     | 
| 
       315 
355 
     | 
    
         
             
                #   User.order('name DESC, email')
         
     | 
| 
       316 
     | 
    
         
            -
                #    
     | 
| 
      
 356 
     | 
    
         
            +
                #   # SELECT "users".* FROM "users" ORDER BY name DESC, email
         
     | 
| 
       317 
357 
     | 
    
         
             
                def order(*args)
         
     | 
| 
       318 
358 
     | 
    
         
             
                  check_if_method_has_arguments!(:order, args)
         
     | 
| 
       319 
359 
     | 
    
         
             
                  spawn.order!(*args)
         
     | 
| 
       320 
360 
     | 
    
         
             
                end
         
     | 
| 
       321 
361 
     | 
    
         | 
| 
      
 362 
     | 
    
         
            +
                # Same as #order but operates on relation in-place instead of copying.
         
     | 
| 
       322 
363 
     | 
    
         
             
                def order!(*args) # :nodoc:
         
     | 
| 
       323 
364 
     | 
    
         
             
                  preprocess_order_args(args)
         
     | 
| 
       324 
365 
     | 
    
         | 
| 
         @@ -340,8 +381,9 @@ module ActiveRecord 
     | 
|
| 
       340 
381 
     | 
    
         
             
                  spawn.reorder!(*args)
         
     | 
| 
       341 
382 
     | 
    
         
             
                end
         
     | 
| 
       342 
383 
     | 
    
         | 
| 
      
 384 
     | 
    
         
            +
                # Same as #reorder but operates on relation in-place instead of copying.
         
     | 
| 
       343 
385 
     | 
    
         
             
                def reorder!(*args) # :nodoc:
         
     | 
| 
       344 
     | 
    
         
            -
                  preprocess_order_args(args)
         
     | 
| 
      
 386 
     | 
    
         
            +
                  preprocess_order_args(args) unless args.all?(&:blank?)
         
     | 
| 
       345 
387 
     | 
    
         | 
| 
       346 
388 
     | 
    
         
             
                  self.reordering_value = true
         
     | 
| 
       347 
389 
     | 
    
         
             
                  self.order_values = args
         
     | 
| 
         @@ -349,8 +391,8 @@ module ActiveRecord 
     | 
|
| 
       349 
391 
     | 
    
         
             
                end
         
     | 
| 
       350 
392 
     | 
    
         | 
| 
       351 
393 
     | 
    
         
             
                VALID_UNSCOPING_VALUES = Set.new([:where, :select, :group, :order, :lock,
         
     | 
| 
       352 
     | 
    
         
            -
                                                 :limit, :offset, :joins, : 
     | 
| 
       353 
     | 
    
         
            -
                                                 :readonly, :having])
         
     | 
| 
      
 394 
     | 
    
         
            +
                                                 :limit, :offset, :joins, :left_outer_joins, :annotate,
         
     | 
| 
      
 395 
     | 
    
         
            +
                                                 :includes, :from, :readonly, :having, :optimizer_hints])
         
     | 
| 
       354 
396 
     | 
    
         | 
| 
       355 
397 
     | 
    
         
             
                # Removes an unwanted relation that is already defined on a chain of relations.
         
     | 
| 
       356 
398 
     | 
    
         
             
                # This is useful when passing around chains of relations and would like to
         
     | 
| 
         @@ -365,15 +407,15 @@ module ActiveRecord 
     | 
|
| 
       365 
407 
     | 
    
         
             
                #   User.order('email DESC').select('id').where(name: "John")
         
     | 
| 
       366 
408 
     | 
    
         
             
                #       .unscope(:order, :select, :where) == User.all
         
     | 
| 
       367 
409 
     | 
    
         
             
                #
         
     | 
| 
       368 
     | 
    
         
            -
                # One can additionally pass a hash as an argument to unscope specific  
     | 
| 
      
 410 
     | 
    
         
            +
                # One can additionally pass a hash as an argument to unscope specific +:where+ values.
         
     | 
| 
       369 
411 
     | 
    
         
             
                # This is done by passing a hash with a single key-value pair. The key should be
         
     | 
| 
       370 
     | 
    
         
            -
                #  
     | 
| 
      
 412 
     | 
    
         
            +
                # +:where+ and the value should be the where value to unscope. For example:
         
     | 
| 
       371 
413 
     | 
    
         
             
                #
         
     | 
| 
       372 
414 
     | 
    
         
             
                #   User.where(name: "John", active: true).unscope(where: :name)
         
     | 
| 
       373 
415 
     | 
    
         
             
                #       == User.where(active: true)
         
     | 
| 
       374 
416 
     | 
    
         
             
                #
         
     | 
| 
       375 
     | 
    
         
            -
                # This method is similar to  
     | 
| 
       376 
     | 
    
         
            -
                #  
     | 
| 
      
 417 
     | 
    
         
            +
                # This method is similar to #except, but unlike
         
     | 
| 
      
 418 
     | 
    
         
            +
                # #except, it persists across merges:
         
     | 
| 
       377 
419 
     | 
    
         
             
                #
         
     | 
| 
       378 
420 
     | 
    
         
             
                #   User.order('email').merge(User.except(:order))
         
     | 
| 
       379 
421 
     | 
    
         
             
                #       == User.order('email')
         
     | 
| 
         @@ -383,7 +425,7 @@ module ActiveRecord 
     | 
|
| 
       383 
425 
     | 
    
         
             
                #
         
     | 
| 
       384 
426 
     | 
    
         
             
                # This means it can be used in association definitions:
         
     | 
| 
       385 
427 
     | 
    
         
             
                #
         
     | 
| 
       386 
     | 
    
         
            -
                #   has_many :comments, -> { unscope 
     | 
| 
      
 428 
     | 
    
         
            +
                #   has_many :comments, -> { unscope(where: :trashed) }
         
     | 
| 
       387 
429 
     | 
    
         
             
                #
         
     | 
| 
       388 
430 
     | 
    
         
             
                def unscope(*args)
         
     | 
| 
       389 
431 
     | 
    
         
             
                  check_if_method_has_arguments!(:unscope, args)
         
     | 
| 
         @@ -397,16 +439,20 @@ module ActiveRecord 
     | 
|
| 
       397 
439 
     | 
    
         
             
                  args.each do |scope|
         
     | 
| 
       398 
440 
     | 
    
         
             
                    case scope
         
     | 
| 
       399 
441 
     | 
    
         
             
                    when Symbol
         
     | 
| 
       400 
     | 
    
         
            -
                       
     | 
| 
      
 442 
     | 
    
         
            +
                      scope = :left_outer_joins if scope == :left_joins
         
     | 
| 
      
 443 
     | 
    
         
            +
                      if !VALID_UNSCOPING_VALUES.include?(scope)
         
     | 
| 
      
 444 
     | 
    
         
            +
                        raise ArgumentError, "Called unscope() with invalid unscoping argument ':#{scope}'. Valid arguments are :#{VALID_UNSCOPING_VALUES.to_a.join(", :")}."
         
     | 
| 
      
 445 
     | 
    
         
            +
                      end
         
     | 
| 
      
 446 
     | 
    
         
            +
                      assert_mutability!
         
     | 
| 
      
 447 
     | 
    
         
            +
                      @values[scope] = DEFAULT_VALUES[scope]
         
     | 
| 
       401 
448 
     | 
    
         
             
                    when Hash
         
     | 
| 
       402 
449 
     | 
    
         
             
                      scope.each do |key, target_value|
         
     | 
| 
       403 
450 
     | 
    
         
             
                        if key != :where
         
     | 
| 
       404 
451 
     | 
    
         
             
                          raise ArgumentError, "Hash arguments in .unscope(*args) must have :where as the key."
         
     | 
| 
       405 
452 
     | 
    
         
             
                        end
         
     | 
| 
       406 
453 
     | 
    
         | 
| 
       407 
     | 
    
         
            -
                        Array(target_value). 
     | 
| 
       408 
     | 
    
         
            -
             
     | 
| 
       409 
     | 
    
         
            -
                        end
         
     | 
| 
      
 454 
     | 
    
         
            +
                        target_values = Array(target_value).map(&:to_s)
         
     | 
| 
      
 455 
     | 
    
         
            +
                        self.where_clause = where_clause.except(*target_values)
         
     | 
| 
       410 
456 
     | 
    
         
             
                      end
         
     | 
| 
       411 
457 
     | 
    
         
             
                    else
         
     | 
| 
       412 
458 
     | 
    
         
             
                      raise ArgumentError, "Unrecognized scoping: #{args.inspect}. Use .unscope(where: :attribute_name) or .unscope(:order), for example."
         
     | 
| 
         @@ -416,15 +462,35 @@ module ActiveRecord 
     | 
|
| 
       416 
462 
     | 
    
         
             
                  self
         
     | 
| 
       417 
463 
     | 
    
         
             
                end
         
     | 
| 
       418 
464 
     | 
    
         | 
| 
       419 
     | 
    
         
            -
                # Performs a joins on +args 
     | 
| 
      
 465 
     | 
    
         
            +
                # Performs a joins on +args+. The given symbol(s) should match the name of
         
     | 
| 
      
 466 
     | 
    
         
            +
                # the association(s).
         
     | 
| 
       420 
467 
     | 
    
         
             
                #
         
     | 
| 
       421 
468 
     | 
    
         
             
                #   User.joins(:posts)
         
     | 
| 
       422 
     | 
    
         
            -
                #    
     | 
| 
      
 469 
     | 
    
         
            +
                #   # SELECT "users".*
         
     | 
| 
      
 470 
     | 
    
         
            +
                #   # FROM "users"
         
     | 
| 
      
 471 
     | 
    
         
            +
                #   # INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
         
     | 
| 
      
 472 
     | 
    
         
            +
                #
         
     | 
| 
      
 473 
     | 
    
         
            +
                # Multiple joins:
         
     | 
| 
      
 474 
     | 
    
         
            +
                #
         
     | 
| 
      
 475 
     | 
    
         
            +
                #   User.joins(:posts, :account)
         
     | 
| 
      
 476 
     | 
    
         
            +
                #   # SELECT "users".*
         
     | 
| 
      
 477 
     | 
    
         
            +
                #   # FROM "users"
         
     | 
| 
      
 478 
     | 
    
         
            +
                #   # INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
         
     | 
| 
      
 479 
     | 
    
         
            +
                #   # INNER JOIN "accounts" ON "accounts"."id" = "users"."account_id"
         
     | 
| 
      
 480 
     | 
    
         
            +
                #
         
     | 
| 
      
 481 
     | 
    
         
            +
                # Nested joins:
         
     | 
| 
      
 482 
     | 
    
         
            +
                #
         
     | 
| 
      
 483 
     | 
    
         
            +
                #   User.joins(posts: [:comments])
         
     | 
| 
      
 484 
     | 
    
         
            +
                #   # SELECT "users".*
         
     | 
| 
      
 485 
     | 
    
         
            +
                #   # FROM "users"
         
     | 
| 
      
 486 
     | 
    
         
            +
                #   # INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
         
     | 
| 
      
 487 
     | 
    
         
            +
                #   # INNER JOIN "comments" "comments_posts"
         
     | 
| 
      
 488 
     | 
    
         
            +
                #   #   ON "comments_posts"."post_id" = "posts"."id"
         
     | 
| 
       423 
489 
     | 
    
         
             
                #
         
     | 
| 
       424 
490 
     | 
    
         
             
                # You can use strings in order to customize your joins:
         
     | 
| 
       425 
491 
     | 
    
         
             
                #
         
     | 
| 
       426 
492 
     | 
    
         
             
                #   User.joins("LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id")
         
     | 
| 
       427 
     | 
    
         
            -
                #    
     | 
| 
      
 493 
     | 
    
         
            +
                #   # SELECT "users".* FROM "users" LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id
         
     | 
| 
       428 
494 
     | 
    
         
             
                def joins(*args)
         
     | 
| 
       429 
495 
     | 
    
         
             
                  check_if_method_has_arguments!(:joins, args)
         
     | 
| 
       430 
496 
     | 
    
         
             
                  spawn.joins!(*args)
         
     | 
| 
         @@ -433,16 +499,25 @@ module ActiveRecord 
     | 
|
| 
       433 
499 
     | 
    
         
             
                def joins!(*args) # :nodoc:
         
     | 
| 
       434 
500 
     | 
    
         
             
                  args.compact!
         
     | 
| 
       435 
501 
     | 
    
         
             
                  args.flatten!
         
     | 
| 
       436 
     | 
    
         
            -
                  self.joins_values  
     | 
| 
      
 502 
     | 
    
         
            +
                  self.joins_values |= args
         
     | 
| 
       437 
503 
     | 
    
         
             
                  self
         
     | 
| 
       438 
504 
     | 
    
         
             
                end
         
     | 
| 
       439 
505 
     | 
    
         | 
| 
       440 
     | 
    
         
            -
                 
     | 
| 
       441 
     | 
    
         
            -
             
     | 
| 
      
 506 
     | 
    
         
            +
                # Performs a left outer joins on +args+:
         
     | 
| 
      
 507 
     | 
    
         
            +
                #
         
     | 
| 
      
 508 
     | 
    
         
            +
                #   User.left_outer_joins(:posts)
         
     | 
| 
      
 509 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
         
     | 
| 
      
 510 
     | 
    
         
            +
                #
         
     | 
| 
      
 511 
     | 
    
         
            +
                def left_outer_joins(*args)
         
     | 
| 
      
 512 
     | 
    
         
            +
                  check_if_method_has_arguments!(__callee__, args)
         
     | 
| 
      
 513 
     | 
    
         
            +
                  spawn.left_outer_joins!(*args)
         
     | 
| 
       442 
514 
     | 
    
         
             
                end
         
     | 
| 
      
 515 
     | 
    
         
            +
                alias :left_joins :left_outer_joins
         
     | 
| 
       443 
516 
     | 
    
         | 
| 
       444 
     | 
    
         
            -
                def  
     | 
| 
       445 
     | 
    
         
            -
                   
     | 
| 
      
 517 
     | 
    
         
            +
                def left_outer_joins!(*args) # :nodoc:
         
     | 
| 
      
 518 
     | 
    
         
            +
                  args.compact!
         
     | 
| 
      
 519 
     | 
    
         
            +
                  args.flatten!
         
     | 
| 
      
 520 
     | 
    
         
            +
                  self.left_outer_joins_values |= args
         
     | 
| 
       446 
521 
     | 
    
         
             
                  self
         
     | 
| 
       447 
522 
     | 
    
         
             
                end
         
     | 
| 
       448 
523 
     | 
    
         | 
| 
         @@ -489,7 +564,7 @@ module ActiveRecord 
     | 
|
| 
       489 
564 
     | 
    
         
             
                # than the previous methods; you are responsible for ensuring that the values in the template
         
     | 
| 
       490 
565 
     | 
    
         
             
                # are properly quoted. The values are passed to the connector for quoting, but the caller
         
     | 
| 
       491 
566 
     | 
    
         
             
                # is responsible for ensuring they are enclosed in quotes in the resulting SQL. After quoting,
         
     | 
| 
       492 
     | 
    
         
            -
                # the values are inserted using the same escapes as the Ruby core method  
     | 
| 
      
 567 
     | 
    
         
            +
                # the values are inserted using the same escapes as the Ruby core method +Kernel::sprintf+.
         
     | 
| 
       493 
568 
     | 
    
         
             
                #
         
     | 
| 
       494 
569 
     | 
    
         
             
                #   User.where(["name = '%s' and email = '%s'", "Joe", "joe@example.com"])
         
     | 
| 
       495 
570 
     | 
    
         
             
                #   # SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
         
     | 
| 
         @@ -566,7 +641,7 @@ module ActiveRecord 
     | 
|
| 
       566 
641 
     | 
    
         
             
                # If the condition is any blank-ish object, then #where is a no-op and returns
         
     | 
| 
       567 
642 
     | 
    
         
             
                # the current relation.
         
     | 
| 
       568 
643 
     | 
    
         
             
                def where(opts = :chain, *rest)
         
     | 
| 
       569 
     | 
    
         
            -
                  if  
     | 
| 
      
 644 
     | 
    
         
            +
                  if :chain == opts
         
     | 
| 
       570 
645 
     | 
    
         
             
                    WhereChain.new(spawn)
         
     | 
| 
       571 
646 
     | 
    
         
             
                  elsif opts.blank?
         
     | 
| 
       572 
647 
     | 
    
         
             
                    self
         
     | 
| 
         @@ -576,27 +651,61 @@ module ActiveRecord 
     | 
|
| 
       576 
651 
     | 
    
         
             
                end
         
     | 
| 
       577 
652 
     | 
    
         | 
| 
       578 
653 
     | 
    
         
             
                def where!(opts, *rest) # :nodoc:
         
     | 
| 
       579 
     | 
    
         
            -
                   
     | 
| 
       580 
     | 
    
         
            -
             
     | 
| 
       581 
     | 
    
         
            -
             
     | 
| 
       582 
     | 
    
         
            -
                  end
         
     | 
| 
       583 
     | 
    
         
            -
             
     | 
| 
       584 
     | 
    
         
            -
                  self.where_values += build_where(opts, rest)
         
     | 
| 
      
 654 
     | 
    
         
            +
                  opts = sanitize_forbidden_attributes(opts)
         
     | 
| 
      
 655 
     | 
    
         
            +
                  references!(PredicateBuilder.references(opts)) if Hash === opts
         
     | 
| 
      
 656 
     | 
    
         
            +
                  self.where_clause += where_clause_factory.build(opts, rest)
         
     | 
| 
       585 
657 
     | 
    
         
             
                  self
         
     | 
| 
       586 
658 
     | 
    
         
             
                end
         
     | 
| 
       587 
659 
     | 
    
         | 
| 
       588 
660 
     | 
    
         
             
                # Allows you to change a previously set where condition for a given attribute, instead of appending to that condition.
         
     | 
| 
       589 
661 
     | 
    
         
             
                #
         
     | 
| 
       590 
     | 
    
         
            -
                #   Post.where(trashed: true).where(trashed: false) 
     | 
| 
       591 
     | 
    
         
            -
                #    
     | 
| 
       592 
     | 
    
         
            -
                # 
     | 
| 
      
 662 
     | 
    
         
            +
                #   Post.where(trashed: true).where(trashed: false)
         
     | 
| 
      
 663 
     | 
    
         
            +
                #   # WHERE `trashed` = 1 AND `trashed` = 0
         
     | 
| 
      
 664 
     | 
    
         
            +
                #
         
     | 
| 
      
 665 
     | 
    
         
            +
                #   Post.where(trashed: true).rewhere(trashed: false)
         
     | 
| 
      
 666 
     | 
    
         
            +
                #   # WHERE `trashed` = 0
         
     | 
| 
       593 
667 
     | 
    
         
             
                #
         
     | 
| 
       594 
     | 
    
         
            -
                # 
     | 
| 
       595 
     | 
    
         
            -
                #  
     | 
| 
      
 668 
     | 
    
         
            +
                #   Post.where(active: true).where(trashed: true).rewhere(trashed: false)
         
     | 
| 
      
 669 
     | 
    
         
            +
                #   # WHERE `active` = 1 AND `trashed` = 0
         
     | 
| 
      
 670 
     | 
    
         
            +
                #
         
     | 
| 
      
 671 
     | 
    
         
            +
                # This is short-hand for <tt>unscope(where: conditions.keys).where(conditions)</tt>.
         
     | 
| 
      
 672 
     | 
    
         
            +
                # Note that unlike reorder, we're only unscoping the named conditions -- not the entire where statement.
         
     | 
| 
       596 
673 
     | 
    
         
             
                def rewhere(conditions)
         
     | 
| 
       597 
674 
     | 
    
         
             
                  unscope(where: conditions.keys).where(conditions)
         
     | 
| 
       598 
675 
     | 
    
         
             
                end
         
     | 
| 
       599 
676 
     | 
    
         | 
| 
      
 677 
     | 
    
         
            +
                # Returns a new relation, which is the logical union of this relation and the one passed as an
         
     | 
| 
      
 678 
     | 
    
         
            +
                # argument.
         
     | 
| 
      
 679 
     | 
    
         
            +
                #
         
     | 
| 
      
 680 
     | 
    
         
            +
                # The two relations must be structurally compatible: they must be scoping the same model, and
         
     | 
| 
      
 681 
     | 
    
         
            +
                # they must differ only by #where (if no #group has been defined) or #having (if a #group is
         
     | 
| 
      
 682 
     | 
    
         
            +
                # present). Neither relation may have a #limit, #offset, or #distinct set.
         
     | 
| 
      
 683 
     | 
    
         
            +
                #
         
     | 
| 
      
 684 
     | 
    
         
            +
                #    Post.where("id = 1").or(Post.where("author_id = 3"))
         
     | 
| 
      
 685 
     | 
    
         
            +
                #    # SELECT `posts`.* FROM `posts` WHERE ((id = 1) OR (author_id = 3))
         
     | 
| 
      
 686 
     | 
    
         
            +
                #
         
     | 
| 
      
 687 
     | 
    
         
            +
                def or(other)
         
     | 
| 
      
 688 
     | 
    
         
            +
                  unless other.is_a? Relation
         
     | 
| 
      
 689 
     | 
    
         
            +
                    raise ArgumentError, "You have passed #{other.class.name} object to #or. Pass an ActiveRecord::Relation object instead."
         
     | 
| 
      
 690 
     | 
    
         
            +
                  end
         
     | 
| 
      
 691 
     | 
    
         
            +
             
     | 
| 
      
 692 
     | 
    
         
            +
                  spawn.or!(other)
         
     | 
| 
      
 693 
     | 
    
         
            +
                end
         
     | 
| 
      
 694 
     | 
    
         
            +
             
     | 
| 
      
 695 
     | 
    
         
            +
                def or!(other) # :nodoc:
         
     | 
| 
      
 696 
     | 
    
         
            +
                  incompatible_values = structurally_incompatible_values_for_or(other)
         
     | 
| 
      
 697 
     | 
    
         
            +
             
     | 
| 
      
 698 
     | 
    
         
            +
                  unless incompatible_values.empty?
         
     | 
| 
      
 699 
     | 
    
         
            +
                    raise ArgumentError, "Relation passed to #or must be structurally compatible. Incompatible values: #{incompatible_values}"
         
     | 
| 
      
 700 
     | 
    
         
            +
                  end
         
     | 
| 
      
 701 
     | 
    
         
            +
             
     | 
| 
      
 702 
     | 
    
         
            +
                  self.where_clause = self.where_clause.or(other.where_clause)
         
     | 
| 
      
 703 
     | 
    
         
            +
                  self.having_clause = having_clause.or(other.having_clause)
         
     | 
| 
      
 704 
     | 
    
         
            +
                  self.references_values += other.references_values
         
     | 
| 
      
 705 
     | 
    
         
            +
             
     | 
| 
      
 706 
     | 
    
         
            +
                  self
         
     | 
| 
      
 707 
     | 
    
         
            +
                end
         
     | 
| 
      
 708 
     | 
    
         
            +
             
     | 
| 
       600 
709 
     | 
    
         
             
                # Allows to specify a HAVING clause. Note that you can't use HAVING
         
     | 
| 
       601 
710 
     | 
    
         
             
                # without also specifying a GROUP clause.
         
     | 
| 
       602 
711 
     | 
    
         
             
                #
         
     | 
| 
         @@ -606,9 +715,10 @@ module ActiveRecord 
     | 
|
| 
       606 
715 
     | 
    
         
             
                end
         
     | 
| 
       607 
716 
     | 
    
         | 
| 
       608 
717 
     | 
    
         
             
                def having!(opts, *rest) # :nodoc:
         
     | 
| 
      
 718 
     | 
    
         
            +
                  opts = sanitize_forbidden_attributes(opts)
         
     | 
| 
       609 
719 
     | 
    
         
             
                  references!(PredicateBuilder.references(opts)) if Hash === opts
         
     | 
| 
       610 
720 
     | 
    
         | 
| 
       611 
     | 
    
         
            -
                  self. 
     | 
| 
      
 721 
     | 
    
         
            +
                  self.having_clause += having_clause_factory.build(opts, rest)
         
     | 
| 
       612 
722 
     | 
    
         
             
                  self
         
     | 
| 
       613 
723 
     | 
    
         
             
                end
         
     | 
| 
       614 
724 
     | 
    
         | 
| 
         @@ -643,7 +753,7 @@ module ActiveRecord 
     | 
|
| 
       643 
753 
     | 
    
         
             
                end
         
     | 
| 
       644 
754 
     | 
    
         | 
| 
       645 
755 
     | 
    
         
             
                # Specifies locking settings (default to +true+). For more information
         
     | 
| 
       646 
     | 
    
         
            -
                # on locking, please see  
     | 
| 
      
 756 
     | 
    
         
            +
                # on locking, please see ActiveRecord::Locking.
         
     | 
| 
       647 
757 
     | 
    
         
             
                def lock(locks = true)
         
     | 
| 
       648 
758 
     | 
    
         
             
                  spawn.lock!(locks)
         
     | 
| 
       649 
759 
     | 
    
         
             
                end
         
     | 
| 
         @@ -674,7 +784,7 @@ module ActiveRecord 
     | 
|
| 
       674 
784 
     | 
    
         
             
                # For example:
         
     | 
| 
       675 
785 
     | 
    
         
             
                #
         
     | 
| 
       676 
786 
     | 
    
         
             
                #   @posts = current_user.visible_posts.where(name: params[:name])
         
     | 
| 
       677 
     | 
    
         
            -
                #   #  
     | 
| 
      
 787 
     | 
    
         
            +
                #   # the visible_posts method is expected to return a chainable Relation
         
     | 
| 
       678 
788 
     | 
    
         
             
                #
         
     | 
| 
       679 
789 
     | 
    
         
             
                #   def visible_posts
         
     | 
| 
       680 
790 
     | 
    
         
             
                #     case role
         
     | 
| 
         @@ -688,7 +798,7 @@ module ActiveRecord 
     | 
|
| 
       688 
798 
     | 
    
         
             
                #   end
         
     | 
| 
       689 
799 
     | 
    
         
             
                #
         
     | 
| 
       690 
800 
     | 
    
         
             
                def none
         
     | 
| 
       691 
     | 
    
         
            -
                   
     | 
| 
      
 801 
     | 
    
         
            +
                  spawn.none!
         
     | 
| 
       692 
802 
     | 
    
         
             
                end
         
     | 
| 
       693 
803 
     | 
    
         | 
| 
       694 
804 
     | 
    
         
             
                def none! # :nodoc:
         
     | 
| 
         @@ -700,7 +810,7 @@ module ActiveRecord 
     | 
|
| 
       700 
810 
     | 
    
         
             
                #
         
     | 
| 
       701 
811 
     | 
    
         
             
                #   users = User.readonly
         
     | 
| 
       702 
812 
     | 
    
         
             
                #   users.first.save
         
     | 
| 
       703 
     | 
    
         
            -
                #   => ActiveRecord::ReadOnlyRecord:  
     | 
| 
      
 813 
     | 
    
         
            +
                #   => ActiveRecord::ReadOnlyRecord: User is marked as readonly
         
     | 
| 
       704 
814 
     | 
    
         
             
                def readonly(value = true)
         
     | 
| 
       705 
815 
     | 
    
         
             
                  spawn.readonly!(value)
         
     | 
| 
       706 
816 
     | 
    
         
             
                end
         
     | 
| 
         @@ -719,7 +829,7 @@ module ActiveRecord 
     | 
|
| 
       719 
829 
     | 
    
         
             
                #   users = users.create_with(name: 'DHH')
         
     | 
| 
       720 
830 
     | 
    
         
             
                #   users.new.name # => 'DHH'
         
     | 
| 
       721 
831 
     | 
    
         
             
                #
         
     | 
| 
       722 
     | 
    
         
            -
                # You can pass +nil+ to  
     | 
| 
      
 832 
     | 
    
         
            +
                # You can pass +nil+ to #create_with to reset attributes:
         
     | 
| 
       723 
833 
     | 
    
         
             
                #
         
     | 
| 
       724 
834 
     | 
    
         
             
                #   users = users.create_with(nil)
         
     | 
| 
       725 
835 
     | 
    
         
             
                #   users.new.name # => 'Oscar'
         
     | 
| 
         @@ -732,7 +842,7 @@ module ActiveRecord 
     | 
|
| 
       732 
842 
     | 
    
         
             
                    value = sanitize_forbidden_attributes(value)
         
     | 
| 
       733 
843 
     | 
    
         
             
                    self.create_with_value = create_with_value.merge(value)
         
     | 
| 
       734 
844 
     | 
    
         
             
                  else
         
     | 
| 
       735 
     | 
    
         
            -
                    self.create_with_value =  
     | 
| 
      
 845 
     | 
    
         
            +
                    self.create_with_value = FROZEN_EMPTY_HASH
         
     | 
| 
       736 
846 
     | 
    
         
             
                  end
         
     | 
| 
       737 
847 
     | 
    
         | 
| 
       738 
848 
     | 
    
         
             
                  self
         
     | 
| 
         @@ -741,49 +851,44 @@ module ActiveRecord 
     | 
|
| 
       741 
851 
     | 
    
         
             
                # Specifies table from which the records will be fetched. For example:
         
     | 
| 
       742 
852 
     | 
    
         
             
                #
         
     | 
| 
       743 
853 
     | 
    
         
             
                #   Topic.select('title').from('posts')
         
     | 
| 
       744 
     | 
    
         
            -
                #   #  
     | 
| 
      
 854 
     | 
    
         
            +
                #   # SELECT title FROM posts
         
     | 
| 
       745 
855 
     | 
    
         
             
                #
         
     | 
| 
       746 
856 
     | 
    
         
             
                # Can accept other relation objects. For example:
         
     | 
| 
       747 
857 
     | 
    
         
             
                #
         
     | 
| 
       748 
858 
     | 
    
         
             
                #   Topic.select('title').from(Topic.approved)
         
     | 
| 
       749 
     | 
    
         
            -
                #   #  
     | 
| 
      
 859 
     | 
    
         
            +
                #   # SELECT title FROM (SELECT * FROM topics WHERE approved = 't') subquery
         
     | 
| 
       750 
860 
     | 
    
         
             
                #
         
     | 
| 
       751 
861 
     | 
    
         
             
                #   Topic.select('a.title').from(Topic.approved, :a)
         
     | 
| 
       752 
     | 
    
         
            -
                #   #  
     | 
| 
      
 862 
     | 
    
         
            +
                #   # SELECT a.title FROM (SELECT * FROM topics WHERE approved = 't') a
         
     | 
| 
       753 
863 
     | 
    
         
             
                #
         
     | 
| 
       754 
864 
     | 
    
         
             
                def from(value, subquery_name = nil)
         
     | 
| 
       755 
865 
     | 
    
         
             
                  spawn.from!(value, subquery_name)
         
     | 
| 
       756 
866 
     | 
    
         
             
                end
         
     | 
| 
       757 
867 
     | 
    
         | 
| 
       758 
868 
     | 
    
         
             
                def from!(value, subquery_name = nil) # :nodoc:
         
     | 
| 
       759 
     | 
    
         
            -
                  self. 
     | 
| 
       760 
     | 
    
         
            -
                  if value.is_a? Relation
         
     | 
| 
       761 
     | 
    
         
            -
                    self.bind_values = value.arel.bind_values + value.bind_values + bind_values
         
     | 
| 
       762 
     | 
    
         
            -
                  end
         
     | 
| 
      
 869 
     | 
    
         
            +
                  self.from_clause = Relation::FromClause.new(value, subquery_name)
         
     | 
| 
       763 
870 
     | 
    
         
             
                  self
         
     | 
| 
       764 
871 
     | 
    
         
             
                end
         
     | 
| 
       765 
872 
     | 
    
         | 
| 
       766 
873 
     | 
    
         
             
                # Specifies whether the records should be unique or not. For example:
         
     | 
| 
       767 
874 
     | 
    
         
             
                #
         
     | 
| 
       768 
875 
     | 
    
         
             
                #   User.select(:name)
         
     | 
| 
       769 
     | 
    
         
            -
                #   #  
     | 
| 
      
 876 
     | 
    
         
            +
                #   # Might return two records with the same name
         
     | 
| 
       770 
877 
     | 
    
         
             
                #
         
     | 
| 
       771 
878 
     | 
    
         
             
                #   User.select(:name).distinct
         
     | 
| 
       772 
     | 
    
         
            -
                #   #  
     | 
| 
      
 879 
     | 
    
         
            +
                #   # Returns 1 record per distinct name
         
     | 
| 
       773 
880 
     | 
    
         
             
                #
         
     | 
| 
       774 
881 
     | 
    
         
             
                #   User.select(:name).distinct.distinct(false)
         
     | 
| 
       775 
     | 
    
         
            -
                #   #  
     | 
| 
      
 882 
     | 
    
         
            +
                #   # You can also remove the uniqueness
         
     | 
| 
       776 
883 
     | 
    
         
             
                def distinct(value = true)
         
     | 
| 
       777 
884 
     | 
    
         
             
                  spawn.distinct!(value)
         
     | 
| 
       778 
885 
     | 
    
         
             
                end
         
     | 
| 
       779 
     | 
    
         
            -
                alias uniq distinct
         
     | 
| 
       780 
886 
     | 
    
         | 
| 
       781 
887 
     | 
    
         
             
                # Like #distinct, but modifies relation in place.
         
     | 
| 
       782 
888 
     | 
    
         
             
                def distinct!(value = true) # :nodoc:
         
     | 
| 
       783 
889 
     | 
    
         
             
                  self.distinct_value = value
         
     | 
| 
       784 
890 
     | 
    
         
             
                  self
         
     | 
| 
       785 
891 
     | 
    
         
             
                end
         
     | 
| 
       786 
     | 
    
         
            -
                alias uniq! distinct!
         
     | 
| 
       787 
892 
     | 
    
         | 
| 
       788 
893 
     | 
    
         
             
                # Used to extend a scope with additional methods, either through
         
     | 
| 
       789 
894 
     | 
    
         
             
                # a module or through a block provided.
         
     | 
| 
         @@ -839,6 +944,29 @@ module ActiveRecord 
     | 
|
| 
       839 
944 
     | 
    
         
             
                  self
         
     | 
| 
       840 
945 
     | 
    
         
             
                end
         
     | 
| 
       841 
946 
     | 
    
         | 
| 
      
 947 
     | 
    
         
            +
                # Specify optimizer hints to be used in the SELECT statement.
         
     | 
| 
      
 948 
     | 
    
         
            +
                #
         
     | 
| 
      
 949 
     | 
    
         
            +
                # Example (for MySQL):
         
     | 
| 
      
 950 
     | 
    
         
            +
                #
         
     | 
| 
      
 951 
     | 
    
         
            +
                #   Topic.optimizer_hints("MAX_EXECUTION_TIME(50000)", "NO_INDEX_MERGE(topics)")
         
     | 
| 
      
 952 
     | 
    
         
            +
                #   # SELECT /*+ MAX_EXECUTION_TIME(50000) NO_INDEX_MERGE(topics) */ `topics`.* FROM `topics`
         
     | 
| 
      
 953 
     | 
    
         
            +
                #
         
     | 
| 
      
 954 
     | 
    
         
            +
                # Example (for PostgreSQL with pg_hint_plan):
         
     | 
| 
      
 955 
     | 
    
         
            +
                #
         
     | 
| 
      
 956 
     | 
    
         
            +
                #   Topic.optimizer_hints("SeqScan(topics)", "Parallel(topics 8)")
         
     | 
| 
      
 957 
     | 
    
         
            +
                #   # SELECT /*+ SeqScan(topics) Parallel(topics 8) */ "topics".* FROM "topics"
         
     | 
| 
      
 958 
     | 
    
         
            +
                def optimizer_hints(*args)
         
     | 
| 
      
 959 
     | 
    
         
            +
                  check_if_method_has_arguments!(:optimizer_hints, args)
         
     | 
| 
      
 960 
     | 
    
         
            +
                  spawn.optimizer_hints!(*args)
         
     | 
| 
      
 961 
     | 
    
         
            +
                end
         
     | 
| 
      
 962 
     | 
    
         
            +
             
     | 
| 
      
 963 
     | 
    
         
            +
                def optimizer_hints!(*args) # :nodoc:
         
     | 
| 
      
 964 
     | 
    
         
            +
                  args.flatten!
         
     | 
| 
      
 965 
     | 
    
         
            +
             
     | 
| 
      
 966 
     | 
    
         
            +
                  self.optimizer_hints_values |= args
         
     | 
| 
      
 967 
     | 
    
         
            +
                  self
         
     | 
| 
      
 968 
     | 
    
         
            +
                end
         
     | 
| 
      
 969 
     | 
    
         
            +
             
     | 
| 
       842 
970 
     | 
    
         
             
                # Reverse the existing order clause on the relation.
         
     | 
| 
       843 
971 
     | 
    
         
             
                #
         
     | 
| 
       844 
972 
     | 
    
         
             
                #   User.order('name ASC').reverse_order # generated SQL has 'ORDER BY name DESC'
         
     | 
| 
         @@ -853,326 +981,404 @@ module ActiveRecord 
     | 
|
| 
       853 
981 
     | 
    
         
             
                  self
         
     | 
| 
       854 
982 
     | 
    
         
             
                end
         
     | 
| 
       855 
983 
     | 
    
         | 
| 
       856 
     | 
    
         
            -
                 
     | 
| 
       857 
     | 
    
         
            -
             
     | 
| 
       858 
     | 
    
         
            -
                   
     | 
| 
      
 984 
     | 
    
         
            +
                def skip_query_cache!(value = true) # :nodoc:
         
     | 
| 
      
 985 
     | 
    
         
            +
                  self.skip_query_cache_value = value
         
     | 
| 
      
 986 
     | 
    
         
            +
                  self
         
     | 
| 
       859 
987 
     | 
    
         
             
                end
         
     | 
| 
       860 
988 
     | 
    
         | 
| 
       861 
     | 
    
         
            -
                 
     | 
| 
      
 989 
     | 
    
         
            +
                def skip_preloading! # :nodoc:
         
     | 
| 
      
 990 
     | 
    
         
            +
                  self.skip_preloading_value = true
         
     | 
| 
      
 991 
     | 
    
         
            +
                  self
         
     | 
| 
      
 992 
     | 
    
         
            +
                end
         
     | 
| 
       862 
993 
     | 
    
         | 
| 
       863 
     | 
    
         
            -
                 
     | 
| 
       864 
     | 
    
         
            -
             
     | 
| 
      
 994 
     | 
    
         
            +
                # Adds an SQL comment to queries generated from this relation. For example:
         
     | 
| 
      
 995 
     | 
    
         
            +
                #
         
     | 
| 
      
 996 
     | 
    
         
            +
                #   User.annotate("selecting user names").select(:name)
         
     | 
| 
      
 997 
     | 
    
         
            +
                #   # SELECT "users"."name" FROM "users" /* selecting user names */
         
     | 
| 
      
 998 
     | 
    
         
            +
                #
         
     | 
| 
      
 999 
     | 
    
         
            +
                #   User.annotate("selecting", "user", "names").select(:name)
         
     | 
| 
      
 1000 
     | 
    
         
            +
                #   # SELECT "users"."name" FROM "users" /* selecting */ /* user */ /* names */
         
     | 
| 
      
 1001 
     | 
    
         
            +
                #
         
     | 
| 
      
 1002 
     | 
    
         
            +
                # The SQL block comment delimiters, "/*" and "*/", will be added automatically.
         
     | 
| 
      
 1003 
     | 
    
         
            +
                def annotate(*args)
         
     | 
| 
      
 1004 
     | 
    
         
            +
                  check_if_method_has_arguments!(:annotate, args)
         
     | 
| 
      
 1005 
     | 
    
         
            +
                  spawn.annotate!(*args)
         
     | 
| 
      
 1006 
     | 
    
         
            +
                end
         
     | 
| 
       865 
1007 
     | 
    
         | 
| 
       866 
     | 
    
         
            -
             
     | 
| 
      
 1008 
     | 
    
         
            +
                # Like #annotate, but modifies relation in place.
         
     | 
| 
      
 1009 
     | 
    
         
            +
                def annotate!(*args) # :nodoc:
         
     | 
| 
      
 1010 
     | 
    
         
            +
                  self.annotate_values += args
         
     | 
| 
      
 1011 
     | 
    
         
            +
                  self
         
     | 
| 
      
 1012 
     | 
    
         
            +
                end
         
     | 
| 
       867 
1013 
     | 
    
         | 
| 
       868 
     | 
    
         
            -
             
     | 
| 
      
 1014 
     | 
    
         
            +
                # Returns the Arel object associated with the relation.
         
     | 
| 
      
 1015 
     | 
    
         
            +
                def arel(aliases = nil) # :nodoc:
         
     | 
| 
      
 1016 
     | 
    
         
            +
                  @arel ||= build_arel(aliases)
         
     | 
| 
      
 1017 
     | 
    
         
            +
                end
         
     | 
| 
       869 
1018 
     | 
    
         | 
| 
       870 
     | 
    
         
            -
             
     | 
| 
      
 1019 
     | 
    
         
            +
                def construct_join_dependency(associations, join_type) # :nodoc:
         
     | 
| 
      
 1020 
     | 
    
         
            +
                  ActiveRecord::Associations::JoinDependency.new(
         
     | 
| 
      
 1021 
     | 
    
         
            +
                    klass, table, associations, join_type
         
     | 
| 
      
 1022 
     | 
    
         
            +
                  )
         
     | 
| 
      
 1023 
     | 
    
         
            +
                end
         
     | 
| 
       871 
1024 
     | 
    
         | 
| 
       872 
     | 
    
         
            -
             
     | 
| 
       873 
     | 
    
         
            -
                   
     | 
| 
       874 
     | 
    
         
            -
             
     | 
| 
      
 1025 
     | 
    
         
            +
                protected
         
     | 
| 
      
 1026 
     | 
    
         
            +
                  def build_subquery(subquery_alias, select_value) # :nodoc:
         
     | 
| 
      
 1027 
     | 
    
         
            +
                    subquery = except(:optimizer_hints).arel.as(subquery_alias)
         
     | 
| 
       875 
1028 
     | 
    
         | 
| 
       876 
     | 
    
         
            -
             
     | 
| 
      
 1029 
     | 
    
         
            +
                    Arel::SelectManager.new(subquery).project(select_value).tap do |arel|
         
     | 
| 
      
 1030 
     | 
    
         
            +
                      arel.optimizer_hints(*optimizer_hints_values) unless optimizer_hints_values.empty?
         
     | 
| 
      
 1031 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1032 
     | 
    
         
            +
                  end
         
     | 
| 
       877 
1033 
     | 
    
         | 
| 
       878 
     | 
    
         
            -
             
     | 
| 
      
 1034 
     | 
    
         
            +
                private
         
     | 
| 
      
 1035 
     | 
    
         
            +
                  def assert_mutability!
         
     | 
| 
      
 1036 
     | 
    
         
            +
                    raise ImmutableRelation if @loaded
         
     | 
| 
      
 1037 
     | 
    
         
            +
                    raise ImmutableRelation if defined?(@arel) && @arel
         
     | 
| 
      
 1038 
     | 
    
         
            +
                  end
         
     | 
| 
       879 
1039 
     | 
    
         | 
| 
       880 
     | 
    
         
            -
                   
     | 
| 
       881 
     | 
    
         
            -
             
     | 
| 
       882 
     | 
    
         
            -
                  arel.lock(lock_value) if lock_value
         
     | 
| 
      
 1040 
     | 
    
         
            +
                  def build_arel(aliases)
         
     | 
| 
      
 1041 
     | 
    
         
            +
                    arel = Arel::SelectManager.new(table)
         
     | 
| 
       883 
1042 
     | 
    
         | 
| 
       884 
     | 
    
         
            -
             
     | 
| 
       885 
     | 
    
         
            -
             
     | 
| 
      
 1043 
     | 
    
         
            +
                    if !joins_values.empty?
         
     | 
| 
      
 1044 
     | 
    
         
            +
                      build_joins(arel, joins_values.flatten, aliases)
         
     | 
| 
      
 1045 
     | 
    
         
            +
                    elsif !left_outer_joins_values.empty?
         
     | 
| 
      
 1046 
     | 
    
         
            +
                      build_left_outer_joins(arel, left_outer_joins_values.flatten, aliases)
         
     | 
| 
      
 1047 
     | 
    
         
            +
                    end
         
     | 
| 
       886 
1048 
     | 
    
         | 
| 
       887 
     | 
    
         
            -
             
     | 
| 
       888 
     | 
    
         
            -
             
     | 
| 
       889 
     | 
    
         
            -
                     
     | 
| 
       890 
     | 
    
         
            -
             
     | 
| 
      
 1049 
     | 
    
         
            +
                    arel.where(where_clause.ast) unless where_clause.empty?
         
     | 
| 
      
 1050 
     | 
    
         
            +
                    arel.having(having_clause.ast) unless having_clause.empty?
         
     | 
| 
      
 1051 
     | 
    
         
            +
                    if limit_value
         
     | 
| 
      
 1052 
     | 
    
         
            +
                      limit_attribute = ActiveModel::Attribute.with_cast_value(
         
     | 
| 
      
 1053 
     | 
    
         
            +
                        "LIMIT",
         
     | 
| 
      
 1054 
     | 
    
         
            +
                        connection.sanitize_limit(limit_value),
         
     | 
| 
      
 1055 
     | 
    
         
            +
                        Type.default_value,
         
     | 
| 
      
 1056 
     | 
    
         
            +
                      )
         
     | 
| 
      
 1057 
     | 
    
         
            +
                      arel.take(Arel::Nodes::BindParam.new(limit_attribute))
         
     | 
| 
      
 1058 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1059 
     | 
    
         
            +
                    if offset_value
         
     | 
| 
      
 1060 
     | 
    
         
            +
                      offset_attribute = ActiveModel::Attribute.with_cast_value(
         
     | 
| 
      
 1061 
     | 
    
         
            +
                        "OFFSET",
         
     | 
| 
      
 1062 
     | 
    
         
            +
                        offset_value.to_i,
         
     | 
| 
      
 1063 
     | 
    
         
            +
                        Type.default_value,
         
     | 
| 
      
 1064 
     | 
    
         
            +
                      )
         
     | 
| 
      
 1065 
     | 
    
         
            +
                      arel.skip(Arel::Nodes::BindParam.new(offset_attribute))
         
     | 
| 
      
 1066 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1067 
     | 
    
         
            +
                    arel.group(*arel_columns(group_values.uniq.reject(&:blank?))) unless group_values.empty?
         
     | 
| 
       891 
1068 
     | 
    
         | 
| 
       892 
     | 
    
         
            -
             
     | 
| 
       893 
     | 
    
         
            -
                  unscope_code = "#{scope}_value#{'s' unless single_val_method}="
         
     | 
| 
      
 1069 
     | 
    
         
            +
                    build_order(arel)
         
     | 
| 
       894 
1070 
     | 
    
         | 
| 
       895 
     | 
    
         
            -
             
     | 
| 
       896 
     | 
    
         
            -
                  when :order
         
     | 
| 
       897 
     | 
    
         
            -
                    result = []
         
     | 
| 
       898 
     | 
    
         
            -
                  when :where
         
     | 
| 
       899 
     | 
    
         
            -
                    self.bind_values = []
         
     | 
| 
       900 
     | 
    
         
            -
                  else
         
     | 
| 
       901 
     | 
    
         
            -
                    result = [] unless single_val_method
         
     | 
| 
       902 
     | 
    
         
            -
                  end
         
     | 
| 
      
 1071 
     | 
    
         
            +
                    build_select(arel)
         
     | 
| 
       903 
1072 
     | 
    
         | 
| 
       904 
     | 
    
         
            -
             
     | 
| 
       905 
     | 
    
         
            -
             
     | 
| 
      
 1073 
     | 
    
         
            +
                    arel.optimizer_hints(*optimizer_hints_values) unless optimizer_hints_values.empty?
         
     | 
| 
      
 1074 
     | 
    
         
            +
                    arel.distinct(distinct_value)
         
     | 
| 
      
 1075 
     | 
    
         
            +
                    arel.from(build_from) unless from_clause.empty?
         
     | 
| 
      
 1076 
     | 
    
         
            +
                    arel.lock(lock_value) if lock_value
         
     | 
| 
      
 1077 
     | 
    
         
            +
                    arel.comment(*annotate_values) unless annotate_values.empty?
         
     | 
| 
       906 
1078 
     | 
    
         | 
| 
       907 
     | 
    
         
            -
             
     | 
| 
       908 
     | 
    
         
            -
                   
     | 
| 
      
 1079 
     | 
    
         
            +
                    arel
         
     | 
| 
      
 1080 
     | 
    
         
            +
                  end
         
     | 
| 
       909 
1081 
     | 
    
         | 
| 
       910 
     | 
    
         
            -
                   
     | 
| 
       911 
     | 
    
         
            -
                     
     | 
| 
       912 
     | 
    
         
            -
                     
     | 
| 
       913 
     | 
    
         
            -
             
     | 
| 
       914 
     | 
    
         
            -
             
     | 
| 
      
 1082 
     | 
    
         
            +
                  def build_from
         
     | 
| 
      
 1083 
     | 
    
         
            +
                    opts = from_clause.value
         
     | 
| 
      
 1084 
     | 
    
         
            +
                    name = from_clause.name
         
     | 
| 
      
 1085 
     | 
    
         
            +
                    case opts
         
     | 
| 
      
 1086 
     | 
    
         
            +
                    when Relation
         
     | 
| 
      
 1087 
     | 
    
         
            +
                      if opts.eager_loading?
         
     | 
| 
      
 1088 
     | 
    
         
            +
                        opts = opts.send(:apply_join_dependency)
         
     | 
| 
      
 1089 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1090 
     | 
    
         
            +
                      name ||= "subquery"
         
     | 
| 
      
 1091 
     | 
    
         
            +
                      opts.arel.as(name.to_s)
         
     | 
| 
      
 1092 
     | 
    
         
            +
                    else
         
     | 
| 
      
 1093 
     | 
    
         
            +
                      opts
         
     | 
| 
       915 
1094 
     | 
    
         
             
                    end
         
     | 
| 
       916 
1095 
     | 
    
         
             
                  end
         
     | 
| 
       917 
1096 
     | 
    
         | 
| 
       918 
     | 
    
         
            -
                   
     | 
| 
       919 
     | 
    
         
            -
             
     | 
| 
       920 
     | 
    
         
            -
             
     | 
| 
       921 
     | 
    
         
            -
             
     | 
| 
       922 
     | 
    
         
            -
             
     | 
| 
       923 
     | 
    
         
            -
             
     | 
| 
       924 
     | 
    
         
            -
             
     | 
| 
      
 1097 
     | 
    
         
            +
                  def select_association_list(associations)
         
     | 
| 
      
 1098 
     | 
    
         
            +
                    result = []
         
     | 
| 
      
 1099 
     | 
    
         
            +
                    associations.each do |association|
         
     | 
| 
      
 1100 
     | 
    
         
            +
                      case association
         
     | 
| 
      
 1101 
     | 
    
         
            +
                      when Hash, Symbol, Array
         
     | 
| 
      
 1102 
     | 
    
         
            +
                        result << association
         
     | 
| 
      
 1103 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1104 
     | 
    
         
            +
                        yield if block_given?
         
     | 
| 
      
 1105 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1107 
     | 
    
         
            +
                    result
         
     | 
| 
      
 1108 
     | 
    
         
            +
                  end
         
     | 
| 
       925 
1109 
     | 
    
         | 
| 
       926 
     | 
    
         
            -
                   
     | 
| 
       927 
     | 
    
         
            -
                     
     | 
| 
       928 
     | 
    
         
            -
             
     | 
| 
       929 
     | 
    
         
            -
                      join = Arel.sql(join.join(' ')) if array_of_strings?(join)
         
     | 
| 
       930 
     | 
    
         
            -
                    when String
         
     | 
| 
       931 
     | 
    
         
            -
                      join = Arel.sql(join)
         
     | 
| 
      
 1110 
     | 
    
         
            +
                  def valid_association_list(associations)
         
     | 
| 
      
 1111 
     | 
    
         
            +
                    select_association_list(associations) do
         
     | 
| 
      
 1112 
     | 
    
         
            +
                      raise ArgumentError, "only Hash, Symbol and Array are allowed"
         
     | 
| 
       932 
1113 
     | 
    
         
             
                    end
         
     | 
| 
       933 
     | 
    
         
            -
                    table.create_string_join(join)
         
     | 
| 
       934 
1114 
     | 
    
         
             
                  end
         
     | 
| 
       935 
     | 
    
         
            -
                end
         
     | 
| 
       936 
1115 
     | 
    
         | 
| 
       937 
     | 
    
         
            -
             
     | 
| 
       938 
     | 
    
         
            -
             
     | 
| 
       939 
     | 
    
         
            -
                     
     | 
| 
       940 
     | 
    
         
            -
                     
     | 
| 
       941 
     | 
    
         
            -
                    Arel::Nodes::Grouping.new(where)
         
     | 
| 
      
 1116 
     | 
    
         
            +
                  def build_left_outer_joins(manager, outer_joins, aliases)
         
     | 
| 
      
 1117 
     | 
    
         
            +
                    buckets = Hash.new { |h, k| h[k] = [] }
         
     | 
| 
      
 1118 
     | 
    
         
            +
                    buckets[:association_join] = valid_association_list(outer_joins)
         
     | 
| 
      
 1119 
     | 
    
         
            +
                    build_join_query(manager, buckets, Arel::Nodes::OuterJoin, aliases)
         
     | 
| 
       942 
1120 
     | 
    
         
             
                  end
         
     | 
| 
       943 
1121 
     | 
    
         | 
| 
       944 
     | 
    
         
            -
                   
     | 
| 
       945 
     | 
    
         
            -
             
     | 
| 
      
 1122 
     | 
    
         
            +
                  def build_joins(manager, joins, aliases)
         
     | 
| 
      
 1123 
     | 
    
         
            +
                    buckets = Hash.new { |h, k| h[k] = [] }
         
     | 
| 
       946 
1124 
     | 
    
         | 
| 
       947 
     | 
    
         
            -
             
     | 
| 
       948 
     | 
    
         
            -
             
     | 
| 
       949 
     | 
    
         
            -
             
     | 
| 
       950 
     | 
    
         
            -
                     
     | 
| 
       951 
     | 
    
         
            -
                  when Hash
         
     | 
| 
       952 
     | 
    
         
            -
                    opts = PredicateBuilder.resolve_column_aliases(klass, opts)
         
     | 
| 
      
 1125 
     | 
    
         
            +
                    unless left_outer_joins_values.empty?
         
     | 
| 
      
 1126 
     | 
    
         
            +
                      left_joins = valid_association_list(left_outer_joins_values.flatten)
         
     | 
| 
      
 1127 
     | 
    
         
            +
                      buckets[:stashed_join] << construct_join_dependency(left_joins, Arel::Nodes::OuterJoin)
         
     | 
| 
      
 1128 
     | 
    
         
            +
                    end
         
     | 
| 
       953 
1129 
     | 
    
         | 
| 
       954 
     | 
    
         
            -
                     
     | 
| 
       955 
     | 
    
         
            -
             
     | 
| 
      
 1130 
     | 
    
         
            +
                    if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
         
     | 
| 
      
 1131 
     | 
    
         
            +
                      buckets[:stashed_join] << joins.pop if joins.last.base_klass == klass
         
     | 
| 
      
 1132 
     | 
    
         
            +
                    end
         
     | 
| 
       956 
1133 
     | 
    
         | 
| 
       957 
     | 
    
         
            -
                     
     | 
| 
       958 
     | 
    
         
            -
             
     | 
| 
      
 1134 
     | 
    
         
            +
                    joins.map! do |join|
         
     | 
| 
      
 1135 
     | 
    
         
            +
                      if join.is_a?(String)
         
     | 
| 
      
 1136 
     | 
    
         
            +
                        table.create_string_join(Arel.sql(join.strip)) unless join.blank?
         
     | 
| 
      
 1137 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1138 
     | 
    
         
            +
                        join
         
     | 
| 
      
 1139 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1140 
     | 
    
         
            +
                    end.delete_if(&:blank?).uniq!
         
     | 
| 
       959 
1141 
     | 
    
         | 
| 
       960 
     | 
    
         
            -
                     
     | 
| 
       961 
     | 
    
         
            -
             
     | 
| 
       962 
     | 
    
         
            -
             
     | 
| 
       963 
     | 
    
         
            -
             
     | 
| 
       964 
     | 
    
         
            -
             
     | 
| 
      
 1142 
     | 
    
         
            +
                    while joins.first.is_a?(Arel::Nodes::Join)
         
     | 
| 
      
 1143 
     | 
    
         
            +
                      join_node = joins.shift
         
     | 
| 
      
 1144 
     | 
    
         
            +
                      if join_node.is_a?(Arel::Nodes::StringJoin) && !buckets[:stashed_join].empty?
         
     | 
| 
      
 1145 
     | 
    
         
            +
                        buckets[:join_node] << join_node
         
     | 
| 
      
 1146 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1147 
     | 
    
         
            +
                        buckets[:leading_join] << join_node
         
     | 
| 
      
 1148 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1149 
     | 
    
         
            +
                    end
         
     | 
| 
       965 
1150 
     | 
    
         | 
| 
       966 
     | 
    
         
            -
             
     | 
| 
       967 
     | 
    
         
            -
             
     | 
| 
       968 
     | 
    
         
            -
             
     | 
| 
       969 
     | 
    
         
            -
             
     | 
| 
       970 
     | 
    
         
            -
                       
     | 
| 
       971 
     | 
    
         
            -
             
     | 
| 
      
 1151 
     | 
    
         
            +
                    joins.each do |join|
         
     | 
| 
      
 1152 
     | 
    
         
            +
                      case join
         
     | 
| 
      
 1153 
     | 
    
         
            +
                      when Hash, Symbol, Array
         
     | 
| 
      
 1154 
     | 
    
         
            +
                        buckets[:association_join] << join
         
     | 
| 
      
 1155 
     | 
    
         
            +
                      when ActiveRecord::Associations::JoinDependency
         
     | 
| 
      
 1156 
     | 
    
         
            +
                        buckets[:stashed_join] << join
         
     | 
| 
      
 1157 
     | 
    
         
            +
                      when Arel::Nodes::Join
         
     | 
| 
      
 1158 
     | 
    
         
            +
                        buckets[:join_node] << join
         
     | 
| 
      
 1159 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1160 
     | 
    
         
            +
                        raise "unknown class: %s" % join.class.name
         
     | 
| 
      
 1161 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1162 
     | 
    
         
            +
                    end
         
     | 
| 
       972 
1163 
     | 
    
         | 
| 
       973 
     | 
    
         
            -
             
     | 
| 
       974 
     | 
    
         
            -
                    value.is_a?(Hash) && association_for_table(column)
         
     | 
| 
      
 1164 
     | 
    
         
            +
                    build_join_query(manager, buckets, Arel::Nodes::InnerJoin, aliases)
         
     | 
| 
       975 
1165 
     | 
    
         
             
                  end
         
     | 
| 
       976 
1166 
     | 
    
         | 
| 
       977 
     | 
    
         
            -
                   
     | 
| 
       978 
     | 
    
         
            -
             
     | 
| 
      
 1167 
     | 
    
         
            +
                  def build_join_query(manager, buckets, join_type, aliases)
         
     | 
| 
      
 1168 
     | 
    
         
            +
                    association_joins = buckets[:association_join]
         
     | 
| 
      
 1169 
     | 
    
         
            +
                    stashed_joins     = buckets[:stashed_join]
         
     | 
| 
      
 1170 
     | 
    
         
            +
                    leading_joins     = buckets[:leading_join]
         
     | 
| 
      
 1171 
     | 
    
         
            +
                    join_nodes        = buckets[:join_node]
         
     | 
| 
       979 
1172 
     | 
    
         | 
| 
       980 
     | 
    
         
            -
             
     | 
| 
      
 1173 
     | 
    
         
            +
                    join_sources = manager.join_sources
         
     | 
| 
      
 1174 
     | 
    
         
            +
                    join_sources.concat(leading_joins) unless leading_joins.empty?
         
     | 
| 
       981 
1175 
     | 
    
         | 
| 
       982 
     | 
    
         
            -
             
     | 
| 
       983 
     | 
    
         
            -
             
     | 
| 
       984 
     | 
    
         
            -
             
     | 
| 
       985 
     | 
    
         
            -
             
     | 
| 
      
 1176 
     | 
    
         
            +
                    unless association_joins.empty? && stashed_joins.empty?
         
     | 
| 
      
 1177 
     | 
    
         
            +
                      alias_tracker = alias_tracker(leading_joins + join_nodes, aliases)
         
     | 
| 
      
 1178 
     | 
    
         
            +
                      join_dependency = construct_join_dependency(association_joins, join_type)
         
     | 
| 
      
 1179 
     | 
    
         
            +
                      join_sources.concat(join_dependency.join_constraints(stashed_joins, alias_tracker))
         
     | 
| 
      
 1180 
     | 
    
         
            +
                    end
         
     | 
| 
       986 
1181 
     | 
    
         | 
| 
       987 
     | 
    
         
            -
             
     | 
| 
       988 
     | 
    
         
            -
                    association_relation = association_for_table(column).klass.send(:relation)
         
     | 
| 
       989 
     | 
    
         
            -
                    association_new_opts, association_bind = association_relation.send(:create_binds, value)
         
     | 
| 
       990 
     | 
    
         
            -
                    new_opts[column] = association_new_opts
         
     | 
| 
       991 
     | 
    
         
            -
                    binds += association_bind
         
     | 
| 
      
 1182 
     | 
    
         
            +
                    join_sources.concat(join_nodes) unless join_nodes.empty?
         
     | 
| 
       992 
1183 
     | 
    
         
             
                  end
         
     | 
| 
       993 
1184 
     | 
    
         | 
| 
       994 
     | 
    
         
            -
                   
     | 
| 
       995 
     | 
    
         
            -
             
     | 
| 
       996 
     | 
    
         
            -
             
     | 
| 
       997 
     | 
    
         
            -
             
     | 
| 
       998 
     | 
    
         
            -
             
     | 
| 
       999 
     | 
    
         
            -
             
     | 
| 
       1000 
     | 
    
         
            -
             
     | 
| 
       1001 
     | 
    
         
            -
             
     | 
| 
       1002 
     | 
    
         
            -
             
     | 
| 
       1003 
     | 
    
         
            -
                end
         
     | 
| 
      
 1185 
     | 
    
         
            +
                  def build_select(arel)
         
     | 
| 
      
 1186 
     | 
    
         
            +
                    if select_values.any?
         
     | 
| 
      
 1187 
     | 
    
         
            +
                      arel.project(*arel_columns(select_values.uniq))
         
     | 
| 
      
 1188 
     | 
    
         
            +
                    elsif klass.ignored_columns.any?
         
     | 
| 
      
 1189 
     | 
    
         
            +
                      arel.project(*klass.column_names.map { |field| arel_attribute(field) })
         
     | 
| 
      
 1190 
     | 
    
         
            +
                    else
         
     | 
| 
      
 1191 
     | 
    
         
            +
                      arel.project(table[Arel.star])
         
     | 
| 
      
 1192 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1193 
     | 
    
         
            +
                  end
         
     | 
| 
       1004 
1194 
     | 
    
         | 
| 
       1005 
     | 
    
         
            -
             
     | 
| 
       1006 
     | 
    
         
            -
             
     | 
| 
       1007 
     | 
    
         
            -
             
     | 
| 
       1008 
     | 
    
         
            -
             
     | 
| 
       1009 
     | 
    
         
            -
             
     | 
| 
       1010 
     | 
    
         
            -
             
     | 
| 
       1011 
     | 
    
         
            -
             
     | 
| 
       1012 
     | 
    
         
            -
             
     | 
| 
      
 1195 
     | 
    
         
            +
                  def arel_columns(columns)
         
     | 
| 
      
 1196 
     | 
    
         
            +
                    columns.flat_map do |field|
         
     | 
| 
      
 1197 
     | 
    
         
            +
                      case field
         
     | 
| 
      
 1198 
     | 
    
         
            +
                      when Symbol
         
     | 
| 
      
 1199 
     | 
    
         
            +
                        arel_column(field.to_s) do |attr_name|
         
     | 
| 
      
 1200 
     | 
    
         
            +
                          connection.quote_table_name(attr_name)
         
     | 
| 
      
 1201 
     | 
    
         
            +
                        end
         
     | 
| 
      
 1202 
     | 
    
         
            +
                      when String
         
     | 
| 
      
 1203 
     | 
    
         
            +
                        arel_column(field, &:itself)
         
     | 
| 
      
 1204 
     | 
    
         
            +
                      when Proc
         
     | 
| 
      
 1205 
     | 
    
         
            +
                        field.call
         
     | 
| 
      
 1206 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1207 
     | 
    
         
            +
                        field
         
     | 
| 
      
 1208 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1209 
     | 
    
         
            +
                    end
         
     | 
| 
       1013 
1210 
     | 
    
         
             
                  end
         
     | 
| 
       1014 
     | 
    
         
            -
                end
         
     | 
| 
       1015 
1211 
     | 
    
         | 
| 
       1016 
     | 
    
         
            -
             
     | 
| 
       1017 
     | 
    
         
            -
             
     | 
| 
       1018 
     | 
    
         
            -
                     
     | 
| 
       1019 
     | 
    
         
            -
             
     | 
| 
       1020 
     | 
    
         
            -
             
     | 
| 
       1021 
     | 
    
         
            -
             
     | 
| 
       1022 
     | 
    
         
            -
                      :association_join
         
     | 
| 
       1023 
     | 
    
         
            -
                    when ActiveRecord::Associations::JoinDependency
         
     | 
| 
       1024 
     | 
    
         
            -
                      :stashed_join
         
     | 
| 
       1025 
     | 
    
         
            -
                    when Arel::Nodes::Join
         
     | 
| 
       1026 
     | 
    
         
            -
                      :join_node
         
     | 
| 
      
 1212 
     | 
    
         
            +
                  def arel_column(field)
         
     | 
| 
      
 1213 
     | 
    
         
            +
                    field = klass.attribute_aliases[field] || field
         
     | 
| 
      
 1214 
     | 
    
         
            +
                    from = from_clause.name || from_clause.value
         
     | 
| 
      
 1215 
     | 
    
         
            +
             
     | 
| 
      
 1216 
     | 
    
         
            +
                    if klass.columns_hash.key?(field) && (!from || table_name_matches?(from))
         
     | 
| 
      
 1217 
     | 
    
         
            +
                      arel_attribute(field)
         
     | 
| 
       1027 
1218 
     | 
    
         
             
                    else
         
     | 
| 
       1028 
     | 
    
         
            -
                       
     | 
| 
      
 1219 
     | 
    
         
            +
                      yield field
         
     | 
| 
       1029 
1220 
     | 
    
         
             
                    end
         
     | 
| 
       1030 
1221 
     | 
    
         
             
                  end
         
     | 
| 
       1031 
1222 
     | 
    
         | 
| 
       1032 
     | 
    
         
            -
                   
     | 
| 
       1033 
     | 
    
         
            -
             
     | 
| 
       1034 
     | 
    
         
            -
             
     | 
| 
       1035 
     | 
    
         
            -
             
     | 
| 
      
 1223 
     | 
    
         
            +
                  def table_name_matches?(from)
         
     | 
| 
      
 1224 
     | 
    
         
            +
                    table_name = Regexp.escape(table.name)
         
     | 
| 
      
 1225 
     | 
    
         
            +
                    quoted_table_name = Regexp.escape(connection.quote_table_name(table.name))
         
     | 
| 
      
 1226 
     | 
    
         
            +
                    /(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
         
     | 
| 
      
 1227 
     | 
    
         
            +
                  end
         
     | 
| 
       1036 
1228 
     | 
    
         | 
| 
       1037 
     | 
    
         
            -
                   
     | 
| 
      
 1229 
     | 
    
         
            +
                  def reverse_sql_order(order_query)
         
     | 
| 
      
 1230 
     | 
    
         
            +
                    if order_query.empty?
         
     | 
| 
      
 1231 
     | 
    
         
            +
                      return [arel_attribute(primary_key).desc] if primary_key
         
     | 
| 
      
 1232 
     | 
    
         
            +
                      raise IrreversibleOrderError,
         
     | 
| 
      
 1233 
     | 
    
         
            +
                        "Relation has no current order and table has no primary key to be used as default order"
         
     | 
| 
      
 1234 
     | 
    
         
            +
                    end
         
     | 
| 
       1038 
1235 
     | 
    
         | 
| 
       1039 
     | 
    
         
            -
             
     | 
| 
       1040 
     | 
    
         
            -
             
     | 
| 
       1041 
     | 
    
         
            -
             
     | 
| 
       1042 
     | 
    
         
            -
             
     | 
| 
       1043 
     | 
    
         
            -
             
     | 
| 
      
 1236 
     | 
    
         
            +
                    order_query.flat_map do |o|
         
     | 
| 
      
 1237 
     | 
    
         
            +
                      case o
         
     | 
| 
      
 1238 
     | 
    
         
            +
                      when Arel::Attribute
         
     | 
| 
      
 1239 
     | 
    
         
            +
                        o.desc
         
     | 
| 
      
 1240 
     | 
    
         
            +
                      when Arel::Nodes::Ordering
         
     | 
| 
      
 1241 
     | 
    
         
            +
                        o.reverse
         
     | 
| 
      
 1242 
     | 
    
         
            +
                      when String
         
     | 
| 
      
 1243 
     | 
    
         
            +
                        if does_not_support_reverse?(o)
         
     | 
| 
      
 1244 
     | 
    
         
            +
                          raise IrreversibleOrderError, "Order #{o.inspect} cannot be reversed automatically"
         
     | 
| 
      
 1245 
     | 
    
         
            +
                        end
         
     | 
| 
      
 1246 
     | 
    
         
            +
                        o.split(",").map! do |s|
         
     | 
| 
      
 1247 
     | 
    
         
            +
                          s.strip!
         
     | 
| 
      
 1248 
     | 
    
         
            +
                          s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || (s << " DESC")
         
     | 
| 
      
 1249 
     | 
    
         
            +
                        end
         
     | 
| 
      
 1250 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1251 
     | 
    
         
            +
                        o
         
     | 
| 
      
 1252 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1253 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1254 
     | 
    
         
            +
                  end
         
     | 
| 
       1044 
1255 
     | 
    
         | 
| 
       1045 
     | 
    
         
            -
                   
     | 
| 
      
 1256 
     | 
    
         
            +
                  def does_not_support_reverse?(order)
         
     | 
| 
      
 1257 
     | 
    
         
            +
                    # Account for String subclasses like Arel::Nodes::SqlLiteral that
         
     | 
| 
      
 1258 
     | 
    
         
            +
                    # override methods like #count.
         
     | 
| 
      
 1259 
     | 
    
         
            +
                    order = String.new(order) unless order.instance_of?(String)
         
     | 
| 
       1046 
1260 
     | 
    
         | 
| 
       1047 
     | 
    
         
            -
             
     | 
| 
       1048 
     | 
    
         
            -
                     
     | 
| 
       1049 
     | 
    
         
            -
             
     | 
| 
      
 1261 
     | 
    
         
            +
                    # Uses SQL function with multiple arguments.
         
     | 
| 
      
 1262 
     | 
    
         
            +
                    (order.include?(",") && order.split(",").find { |section| section.count("(") != section.count(")") }) ||
         
     | 
| 
      
 1263 
     | 
    
         
            +
                      # Uses "nulls first" like construction.
         
     | 
| 
      
 1264 
     | 
    
         
            +
                      /\bnulls\s+(?:first|last)\b/i.match?(order)
         
     | 
| 
       1050 
1265 
     | 
    
         
             
                  end
         
     | 
| 
       1051 
1266 
     | 
    
         | 
| 
       1052 
     | 
    
         
            -
                   
     | 
| 
      
 1267 
     | 
    
         
            +
                  def build_order(arel)
         
     | 
| 
      
 1268 
     | 
    
         
            +
                    orders = order_values.uniq
         
     | 
| 
      
 1269 
     | 
    
         
            +
                    orders.reject!(&:blank?)
         
     | 
| 
       1053 
1270 
     | 
    
         | 
| 
       1054 
     | 
    
         
            -
             
     | 
| 
       1055 
     | 
    
         
            -
             
     | 
| 
      
 1271 
     | 
    
         
            +
                    arel.order(*orders) unless orders.empty?
         
     | 
| 
      
 1272 
     | 
    
         
            +
                  end
         
     | 
| 
       1056 
1273 
     | 
    
         | 
| 
       1057 
     | 
    
         
            -
             
     | 
| 
       1058 
     | 
    
         
            -
             
     | 
| 
       1059 
     | 
    
         
            -
             
     | 
| 
       1060 
     | 
    
         
            -
                   
     | 
| 
       1061 
     | 
    
         
            -
                     
     | 
| 
      
 1274 
     | 
    
         
            +
                  VALID_DIRECTIONS = [:asc, :desc, :ASC, :DESC,
         
     | 
| 
      
 1275 
     | 
    
         
            +
                                      "asc", "desc", "ASC", "DESC"].to_set # :nodoc:
         
     | 
| 
      
 1276 
     | 
    
         
            +
             
     | 
| 
      
 1277 
     | 
    
         
            +
                  def validate_order_args(args)
         
     | 
| 
      
 1278 
     | 
    
         
            +
                    args.each do |arg|
         
     | 
| 
      
 1279 
     | 
    
         
            +
                      next unless arg.is_a?(Hash)
         
     | 
| 
      
 1280 
     | 
    
         
            +
                      arg.each do |_key, value|
         
     | 
| 
      
 1281 
     | 
    
         
            +
                        unless VALID_DIRECTIONS.include?(value)
         
     | 
| 
      
 1282 
     | 
    
         
            +
                          raise ArgumentError,
         
     | 
| 
      
 1283 
     | 
    
         
            +
                            "Direction \"#{value}\" is invalid. Valid directions are: #{VALID_DIRECTIONS.to_a.inspect}"
         
     | 
| 
      
 1284 
     | 
    
         
            +
                        end
         
     | 
| 
      
 1285 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1286 
     | 
    
         
            +
                    end
         
     | 
| 
       1062 
1287 
     | 
    
         
             
                  end
         
     | 
| 
       1063 
     | 
    
         
            -
                end
         
     | 
| 
       1064 
1288 
     | 
    
         | 
| 
       1065 
     | 
    
         
            -
             
     | 
| 
       1066 
     | 
    
         
            -
             
     | 
| 
       1067 
     | 
    
         
            -
                     
     | 
| 
       1068 
     | 
    
         
            -
                       
     | 
| 
       1069 
     | 
    
         
            -
                    elsif Symbol === field
         
     | 
| 
       1070 
     | 
    
         
            -
                      connection.quote_table_name(field.to_s)
         
     | 
| 
       1071 
     | 
    
         
            -
                    else
         
     | 
| 
       1072 
     | 
    
         
            -
                      field
         
     | 
| 
      
 1289 
     | 
    
         
            +
                  def preprocess_order_args(order_args)
         
     | 
| 
      
 1290 
     | 
    
         
            +
                    order_args.reject!(&:blank?)
         
     | 
| 
      
 1291 
     | 
    
         
            +
                    order_args.map! do |arg|
         
     | 
| 
      
 1292 
     | 
    
         
            +
                      klass.sanitize_sql_for_order(arg)
         
     | 
| 
       1073 
1293 
     | 
    
         
             
                    end
         
     | 
| 
      
 1294 
     | 
    
         
            +
                    order_args.flatten!
         
     | 
| 
      
 1295 
     | 
    
         
            +
             
     | 
| 
      
 1296 
     | 
    
         
            +
                    @klass.disallow_raw_sql!(
         
     | 
| 
      
 1297 
     | 
    
         
            +
                      order_args.flat_map { |a| a.is_a?(Hash) ? a.keys : a },
         
     | 
| 
      
 1298 
     | 
    
         
            +
                      permit: connection.column_name_with_order_matcher
         
     | 
| 
      
 1299 
     | 
    
         
            +
                    )
         
     | 
| 
      
 1300 
     | 
    
         
            +
             
     | 
| 
      
 1301 
     | 
    
         
            +
                    validate_order_args(order_args)
         
     | 
| 
      
 1302 
     | 
    
         
            +
             
     | 
| 
      
 1303 
     | 
    
         
            +
                    references = order_args.grep(String)
         
     | 
| 
      
 1304 
     | 
    
         
            +
                    references.map! { |arg| arg =~ /^\W?(\w+)\W?\./ && $1 }.compact!
         
     | 
| 
      
 1305 
     | 
    
         
            +
                    references!(references) if references.any?
         
     | 
| 
      
 1306 
     | 
    
         
            +
             
     | 
| 
      
 1307 
     | 
    
         
            +
                    # if a symbol is given we prepend the quoted table name
         
     | 
| 
      
 1308 
     | 
    
         
            +
                    order_args.map! do |arg|
         
     | 
| 
      
 1309 
     | 
    
         
            +
                      case arg
         
     | 
| 
      
 1310 
     | 
    
         
            +
                      when Symbol
         
     | 
| 
      
 1311 
     | 
    
         
            +
                        order_column(arg.to_s).asc
         
     | 
| 
      
 1312 
     | 
    
         
            +
                      when Hash
         
     | 
| 
      
 1313 
     | 
    
         
            +
                        arg.map { |field, dir|
         
     | 
| 
      
 1314 
     | 
    
         
            +
                          case field
         
     | 
| 
      
 1315 
     | 
    
         
            +
                          when Arel::Nodes::SqlLiteral
         
     | 
| 
      
 1316 
     | 
    
         
            +
                            field.send(dir.downcase)
         
     | 
| 
      
 1317 
     | 
    
         
            +
                          else
         
     | 
| 
      
 1318 
     | 
    
         
            +
                            order_column(field.to_s).send(dir.downcase)
         
     | 
| 
      
 1319 
     | 
    
         
            +
                          end
         
     | 
| 
      
 1320 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1321 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1322 
     | 
    
         
            +
                        arg
         
     | 
| 
      
 1323 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1324 
     | 
    
         
            +
                    end.flatten!
         
     | 
| 
       1074 
1325 
     | 
    
         
             
                  end
         
     | 
| 
       1075 
     | 
    
         
            -
                end
         
     | 
| 
       1076 
1326 
     | 
    
         | 
| 
       1077 
     | 
    
         
            -
             
     | 
| 
       1078 
     | 
    
         
            -
             
     | 
| 
       1079 
     | 
    
         
            -
             
     | 
| 
       1080 
     | 
    
         
            -
             
     | 
| 
       1081 
     | 
    
         
            -
             
     | 
| 
       1082 
     | 
    
         
            -
             
     | 
| 
       1083 
     | 
    
         
            -
                      o.reverse
         
     | 
| 
       1084 
     | 
    
         
            -
                    when String
         
     | 
| 
       1085 
     | 
    
         
            -
                      o.to_s.split(',').map! do |s|
         
     | 
| 
       1086 
     | 
    
         
            -
                        s.strip!
         
     | 
| 
       1087 
     | 
    
         
            -
                        s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
         
     | 
| 
      
 1327 
     | 
    
         
            +
                  def order_column(field)
         
     | 
| 
      
 1328 
     | 
    
         
            +
                    arel_column(field) do |attr_name|
         
     | 
| 
      
 1329 
     | 
    
         
            +
                      if attr_name == "count" && !group_values.empty?
         
     | 
| 
      
 1330 
     | 
    
         
            +
                        arel_attribute(attr_name)
         
     | 
| 
      
 1331 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1332 
     | 
    
         
            +
                        Arel.sql(connection.quote_table_name(attr_name))
         
     | 
| 
       1088 
1333 
     | 
    
         
             
                      end
         
     | 
| 
       1089 
     | 
    
         
            -
                    else
         
     | 
| 
       1090 
     | 
    
         
            -
                      o
         
     | 
| 
       1091 
1334 
     | 
    
         
             
                    end
         
     | 
| 
       1092 
1335 
     | 
    
         
             
                  end
         
     | 
| 
       1093 
     | 
    
         
            -
                end
         
     | 
| 
       1094 
1336 
     | 
    
         | 
| 
       1095 
     | 
    
         
            -
             
     | 
| 
       1096 
     | 
    
         
            -
                   
     | 
| 
       1097 
     | 
    
         
            -
             
     | 
| 
       1098 
     | 
    
         
            -
             
     | 
| 
       1099 
     | 
    
         
            -
             
     | 
| 
       1100 
     | 
    
         
            -
                   
     | 
| 
       1101 
     | 
    
         
            -
                   
     | 
| 
       1102 
     | 
    
         
            -
             
     | 
| 
       1103 
     | 
    
         
            -
                   
     | 
| 
       1104 
     | 
    
         
            -
             
     | 
| 
       1105 
     | 
    
         
            -
             
     | 
| 
       1106 
     | 
    
         
            -
             
     | 
| 
       1107 
     | 
    
         
            -
             
     | 
| 
       1108 
     | 
    
         
            -
             
     | 
| 
       1109 
     | 
    
         
            -
             
     | 
| 
       1110 
     | 
    
         
            -
                   
     | 
| 
       1111 
     | 
    
         
            -
             
     | 
| 
       1112 
     | 
    
         
            -
                     
     | 
| 
       1113 
     | 
    
         
            -
                      raise ArgumentError, " 
     | 
| 
       1114 
     | 
    
         
            -
                                           "directions are: #{VALID_DIRECTIONS.inspect}" unless VALID_DIRECTIONS.include?(value)
         
     | 
| 
      
 1337 
     | 
    
         
            +
                  # Checks to make sure that the arguments are not blank. Note that if some
         
     | 
| 
      
 1338 
     | 
    
         
            +
                  # blank-like object were initially passed into the query method, then this
         
     | 
| 
      
 1339 
     | 
    
         
            +
                  # method will not raise an error.
         
     | 
| 
      
 1340 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1341 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 1342 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1343 
     | 
    
         
            +
                  #    Post.references()   # raises an error
         
     | 
| 
      
 1344 
     | 
    
         
            +
                  #    Post.references([]) # does not raise an error
         
     | 
| 
      
 1345 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1346 
     | 
    
         
            +
                  # This particular method should be called with a method_name and the args
         
     | 
| 
      
 1347 
     | 
    
         
            +
                  # passed into that method as an input. For example:
         
     | 
| 
      
 1348 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1349 
     | 
    
         
            +
                  # def references(*args)
         
     | 
| 
      
 1350 
     | 
    
         
            +
                  #   check_if_method_has_arguments!("references", args)
         
     | 
| 
      
 1351 
     | 
    
         
            +
                  #   ...
         
     | 
| 
      
 1352 
     | 
    
         
            +
                  # end
         
     | 
| 
      
 1353 
     | 
    
         
            +
                  def check_if_method_has_arguments!(method_name, args)
         
     | 
| 
      
 1354 
     | 
    
         
            +
                    if args.blank?
         
     | 
| 
      
 1355 
     | 
    
         
            +
                      raise ArgumentError, "The method .#{method_name}() must contain arguments."
         
     | 
| 
       1115 
1356 
     | 
    
         
             
                    end
         
     | 
| 
       1116 
1357 
     | 
    
         
             
                  end
         
     | 
| 
       1117 
     | 
    
         
            -
                end
         
     | 
| 
       1118 
     | 
    
         
            -
             
     | 
| 
       1119 
     | 
    
         
            -
                def preprocess_order_args(order_args)
         
     | 
| 
       1120 
     | 
    
         
            -
                  order_args.flatten!
         
     | 
| 
       1121 
     | 
    
         
            -
                  validate_order_args(order_args)
         
     | 
| 
       1122 
1358 
     | 
    
         | 
| 
       1123 
     | 
    
         
            -
                   
     | 
| 
       1124 
     | 
    
         
            -
                   
     | 
| 
       1125 
     | 
    
         
            -
             
     | 
| 
       1126 
     | 
    
         
            -
             
     | 
| 
       1127 
     | 
    
         
            -
             
     | 
| 
       1128 
     | 
    
         
            -
             
     | 
| 
       1129 
     | 
    
         
            -
                    case arg
         
     | 
| 
       1130 
     | 
    
         
            -
                    when Symbol
         
     | 
| 
       1131 
     | 
    
         
            -
                      arg = klass.attribute_alias(arg) if klass.attribute_alias?(arg)
         
     | 
| 
       1132 
     | 
    
         
            -
                      table[arg].asc
         
     | 
| 
       1133 
     | 
    
         
            -
                    when Hash
         
     | 
| 
       1134 
     | 
    
         
            -
                      arg.map { |field, dir|
         
     | 
| 
       1135 
     | 
    
         
            -
                        field = klass.attribute_alias(field) if klass.attribute_alias?(field)
         
     | 
| 
       1136 
     | 
    
         
            -
                        table[field].send(dir.downcase)
         
     | 
| 
       1137 
     | 
    
         
            -
                      }
         
     | 
| 
       1138 
     | 
    
         
            -
                    else
         
     | 
| 
       1139 
     | 
    
         
            -
                      arg
         
     | 
| 
      
 1359 
     | 
    
         
            +
                  STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references]
         
     | 
| 
      
 1360 
     | 
    
         
            +
                  def structurally_incompatible_values_for_or(other)
         
     | 
| 
      
 1361 
     | 
    
         
            +
                    values = other.values
         
     | 
| 
      
 1362 
     | 
    
         
            +
                    STRUCTURAL_OR_METHODS.reject do |method|
         
     | 
| 
      
 1363 
     | 
    
         
            +
                      default = DEFAULT_VALUES[method]
         
     | 
| 
      
 1364 
     | 
    
         
            +
                      @values.fetch(method, default) == values.fetch(method, default)
         
     | 
| 
       1140 
1365 
     | 
    
         
             
                    end
         
     | 
| 
       1141 
     | 
    
         
            -
                  end 
     | 
| 
       1142 
     | 
    
         
            -
                end
         
     | 
| 
      
 1366 
     | 
    
         
            +
                  end
         
     | 
| 
       1143 
1367 
     | 
    
         | 
| 
       1144 
     | 
    
         
            -
             
     | 
| 
       1145 
     | 
    
         
            -
             
     | 
| 
       1146 
     | 
    
         
            -
                # method will not raise an error.
         
     | 
| 
       1147 
     | 
    
         
            -
                #
         
     | 
| 
       1148 
     | 
    
         
            -
                # Example:
         
     | 
| 
       1149 
     | 
    
         
            -
                #
         
     | 
| 
       1150 
     | 
    
         
            -
                #    Post.references()   # => raises an error
         
     | 
| 
       1151 
     | 
    
         
            -
                #    Post.references([]) # => does not raise an error
         
     | 
| 
       1152 
     | 
    
         
            -
                #
         
     | 
| 
       1153 
     | 
    
         
            -
                # This particular method should be called with a method_name and the args
         
     | 
| 
       1154 
     | 
    
         
            -
                # passed into that method as an input. For example:
         
     | 
| 
       1155 
     | 
    
         
            -
                #
         
     | 
| 
       1156 
     | 
    
         
            -
                # def references(*args)
         
     | 
| 
       1157 
     | 
    
         
            -
                #   check_if_method_has_arguments!("references", args)
         
     | 
| 
       1158 
     | 
    
         
            -
                #   ...
         
     | 
| 
       1159 
     | 
    
         
            -
                # end
         
     | 
| 
       1160 
     | 
    
         
            -
                def check_if_method_has_arguments!(method_name, args)
         
     | 
| 
       1161 
     | 
    
         
            -
                  if args.blank?
         
     | 
| 
       1162 
     | 
    
         
            -
                    raise ArgumentError, "The method .#{method_name}() must contain arguments."
         
     | 
| 
      
 1368 
     | 
    
         
            +
                  def where_clause_factory
         
     | 
| 
      
 1369 
     | 
    
         
            +
                    @where_clause_factory ||= Relation::WhereClauseFactory.new(klass, predicate_builder)
         
     | 
| 
       1163 
1370 
     | 
    
         
             
                  end
         
     | 
| 
       1164 
     | 
    
         
            -
             
     | 
| 
      
 1371 
     | 
    
         
            +
                  alias having_clause_factory where_clause_factory
         
     | 
| 
       1165 
1372 
     | 
    
         | 
| 
       1166 
     | 
    
         
            -
             
     | 
| 
       1167 
     | 
    
         
            -
             
     | 
| 
       1168 
     | 
    
         
            -
                     
     | 
| 
       1169 
     | 
    
         
            -
             
     | 
| 
       1170 
     | 
    
         
            -
             
     | 
| 
       1171 
     | 
    
         
            -
             
     | 
| 
       1172 
     | 
    
         
            -
             
     | 
| 
       1173 
     | 
    
         
            -
             
     | 
| 
       1174 
     | 
    
         
            -
                     
     | 
| 
      
 1373 
     | 
    
         
            +
                  DEFAULT_VALUES = {
         
     | 
| 
      
 1374 
     | 
    
         
            +
                    create_with: FROZEN_EMPTY_HASH,
         
     | 
| 
      
 1375 
     | 
    
         
            +
                    where: Relation::WhereClause.empty,
         
     | 
| 
      
 1376 
     | 
    
         
            +
                    having: Relation::WhereClause.empty,
         
     | 
| 
      
 1377 
     | 
    
         
            +
                    from: Relation::FromClause.empty
         
     | 
| 
      
 1378 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1379 
     | 
    
         
            +
             
     | 
| 
      
 1380 
     | 
    
         
            +
                  Relation::MULTI_VALUE_METHODS.each do |value|
         
     | 
| 
      
 1381 
     | 
    
         
            +
                    DEFAULT_VALUES[value] ||= FROZEN_EMPTY_ARRAY
         
     | 
| 
       1175 
1382 
     | 
    
         
             
                  end
         
     | 
| 
       1176 
     | 
    
         
            -
                end
         
     | 
| 
       1177 
1383 
     | 
    
         
             
              end
         
     | 
| 
       1178 
1384 
     | 
    
         
             
            end
         
     |