activerecord 5.2.8.1 → 6.1.6.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1255 -596
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +9 -8
- data/lib/active_record/association_relation.rb +30 -10
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +100 -41
- data/lib/active_record/associations/association_scope.rb +23 -21
- data/lib/active_record/associations/belongs_to_association.rb +55 -48
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
- data/lib/active_record/associations/builder/association.rb +45 -22
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +8 -17
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +44 -34
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +24 -18
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +69 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +47 -34
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +137 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +46 -9
- data/lib/active_record/autosave_association.rb +57 -42
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
- data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
- data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +293 -33
- data/lib/active_record/core.rb +333 -98
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +273 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +108 -36
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +200 -481
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +28 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +37 -23
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +35 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +145 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +206 -157
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +116 -59
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +411 -80
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +109 -93
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +157 -90
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +64 -39
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +62 -45
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +476 -187
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +115 -62
- data/lib/active_record/relation.rb +379 -115
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +4 -8
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +277 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +62 -118
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +10 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +116 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -7,8 +7,8 @@ module ActiveRecord
|
|
7
7
|
ONE_AS_ONE = "1 AS one"
|
8
8
|
|
9
9
|
# Find by id - This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]).
|
10
|
-
# If one or more records
|
11
|
-
# is an integer, find by id coerces its arguments using +to_i+.
|
10
|
+
# If one or more records cannot be found for the requested ids, then ActiveRecord::RecordNotFound will be raised.
|
11
|
+
# If the primary key is an integer, find by id coerces its arguments by using +to_i+.
|
12
12
|
#
|
13
13
|
# Person.find(1) # returns the object for ID = 1
|
14
14
|
# Person.find("1") # returns the object for ID = 1
|
@@ -79,17 +79,12 @@ module ActiveRecord
|
|
79
79
|
# Post.find_by "published_at < ?", 2.weeks.ago
|
80
80
|
def find_by(arg, *args)
|
81
81
|
where(arg, *args).take
|
82
|
-
rescue ::RangeError
|
83
|
-
nil
|
84
82
|
end
|
85
83
|
|
86
84
|
# Like #find_by, except that if no record is found, raises
|
87
85
|
# an ActiveRecord::RecordNotFound error.
|
88
86
|
def find_by!(arg, *args)
|
89
87
|
where(arg, *args).take!
|
90
|
-
rescue ::RangeError
|
91
|
-
raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value",
|
92
|
-
@klass.name, @klass.primary_key)
|
93
88
|
end
|
94
89
|
|
95
90
|
# Gives a record (or N records if a parameter is supplied) without any implied
|
@@ -119,6 +114,8 @@ module ActiveRecord
|
|
119
114
|
# Person.first(3) # returns the first three objects fetched by SELECT * FROM people ORDER BY people.id LIMIT 3
|
120
115
|
#
|
121
116
|
def first(limit = nil)
|
117
|
+
check_reorder_deprecation unless loaded?
|
118
|
+
|
122
119
|
if limit
|
123
120
|
find_nth_with_limit(0, limit)
|
124
121
|
else
|
@@ -280,9 +277,9 @@ module ActiveRecord
|
|
280
277
|
# * Integer - Finds the record with this primary key.
|
281
278
|
# * String - Finds the record with a primary key corresponding to this
|
282
279
|
# string (such as <tt>'5'</tt>).
|
283
|
-
# * Array - Finds the record that matches these +
|
280
|
+
# * Array - Finds the record that matches these +where+-style conditions
|
284
281
|
# (such as <tt>['name LIKE ?', "%#{query}%"]</tt>).
|
285
|
-
# * Hash - Finds the record that matches these +
|
282
|
+
# * Hash - Finds the record that matches these +where+-style conditions
|
286
283
|
# (such as <tt>{name: 'David'}</tt>).
|
287
284
|
# * +false+ - Returns always +false+.
|
288
285
|
# * No args - Returns +false+ if the relation is empty, +true+ otherwise.
|
@@ -318,12 +315,26 @@ module ActiveRecord
|
|
318
315
|
end
|
319
316
|
|
320
317
|
relation = construct_relation_for_exists(conditions)
|
318
|
+
return false if relation.where_clause.contradiction?
|
319
|
+
|
320
|
+
skip_query_cache_if_necessary { connection.select_rows(relation.arel, "#{name} Exists?").size == 1 }
|
321
|
+
end
|
321
322
|
|
322
|
-
|
323
|
-
|
324
|
-
|
323
|
+
# Returns true if the relation contains the given record or false otherwise.
|
324
|
+
#
|
325
|
+
# No query is performed if the relation is loaded; the given record is
|
326
|
+
# compared to the records in memory. If the relation is unloaded, an
|
327
|
+
# efficient existence query is performed, as in #exists?.
|
328
|
+
def include?(record)
|
329
|
+
if loaded? || offset_value || limit_value || having_clause.any?
|
330
|
+
records.include?(record)
|
331
|
+
else
|
332
|
+
record.is_a?(klass) && exists?(record.id)
|
333
|
+
end
|
325
334
|
end
|
326
335
|
|
336
|
+
alias :member? :include?
|
337
|
+
|
327
338
|
# This method is called whenever no records are found with either a single
|
328
339
|
# id or multiple ids and raises an ActiveRecord::RecordNotFound exception.
|
329
340
|
#
|
@@ -333,19 +344,19 @@ module ActiveRecord
|
|
333
344
|
# the expected number of results should be provided in the +expected_size+
|
334
345
|
# argument.
|
335
346
|
def raise_record_not_found_exception!(ids = nil, result_size = nil, expected_size = nil, key = primary_key, not_found_ids = nil) # :nodoc:
|
336
|
-
conditions = arel.where_sql(
|
337
|
-
|
347
|
+
conditions = " [#{arel.where_sql(klass)}]" unless where_clause.empty?
|
348
|
+
|
338
349
|
name = @klass.name
|
339
350
|
|
340
351
|
if ids.nil?
|
341
|
-
error = "Couldn't find #{name}"
|
352
|
+
error = +"Couldn't find #{name}"
|
342
353
|
error << " with#{conditions}" if conditions
|
343
354
|
raise RecordNotFound.new(error, name, key)
|
344
|
-
elsif Array(ids).size == 1
|
355
|
+
elsif Array.wrap(ids).size == 1
|
345
356
|
error = "Couldn't find #{name} with '#{key}'=#{ids}#{conditions}"
|
346
357
|
raise RecordNotFound.new(error, name, key, ids)
|
347
358
|
else
|
348
|
-
error = "Couldn't find all #{name.pluralize} with '#{key}': "
|
359
|
+
error = +"Couldn't find all #{name.pluralize} with '#{key}': "
|
349
360
|
error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})."
|
350
361
|
error << " Couldn't find #{name.pluralize(not_found_ids.size)} with #{key.to_s.pluralize(not_found_ids.size)} #{not_found_ids.join(', ')}." if not_found_ids
|
351
362
|
raise RecordNotFound.new(error, name, key, ids)
|
@@ -353,12 +364,20 @@ module ActiveRecord
|
|
353
364
|
end
|
354
365
|
|
355
366
|
private
|
356
|
-
|
357
|
-
|
358
|
-
|
367
|
+
def check_reorder_deprecation
|
368
|
+
if !order_values.empty? && order_values.all?(&:blank?)
|
369
|
+
blank_value = order_values.first
|
370
|
+
ActiveSupport::Deprecation.warn(<<~MSG.squish)
|
371
|
+
`.reorder(#{blank_value.inspect})` with `.first` / `.first!` no longer
|
372
|
+
takes non-deterministic result in Rails 7.0.
|
373
|
+
To continue taking non-deterministic result, use `.take` / `.take!` instead.
|
374
|
+
MSG
|
375
|
+
end
|
359
376
|
end
|
360
377
|
|
361
378
|
def construct_relation_for_exists(conditions)
|
379
|
+
conditions = sanitize_forbidden_attributes(conditions)
|
380
|
+
|
362
381
|
if distinct_value && offset_value
|
363
382
|
relation = except(:order).limit!(1)
|
364
383
|
else
|
@@ -375,18 +394,22 @@ module ActiveRecord
|
|
375
394
|
relation
|
376
395
|
end
|
377
396
|
|
378
|
-
def construct_join_dependency
|
379
|
-
including = eager_load_values + includes_values
|
380
|
-
ActiveRecord::Associations::JoinDependency.new(
|
381
|
-
klass, table, including
|
382
|
-
)
|
383
|
-
end
|
384
|
-
|
385
397
|
def apply_join_dependency(eager_loading: group_values.empty?)
|
386
|
-
join_dependency = construct_join_dependency
|
398
|
+
join_dependency = construct_join_dependency(
|
399
|
+
eager_load_values | includes_values, Arel::Nodes::OuterJoin
|
400
|
+
)
|
387
401
|
relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
|
388
402
|
|
389
|
-
if eager_loading && !
|
403
|
+
if eager_loading && !(
|
404
|
+
using_limitable_reflections?(join_dependency.reflections) &&
|
405
|
+
using_limitable_reflections?(
|
406
|
+
construct_join_dependency(
|
407
|
+
select_association_list(joins_values).concat(
|
408
|
+
select_association_list(left_outer_joins_values)
|
409
|
+
), nil
|
410
|
+
).reflections
|
411
|
+
)
|
412
|
+
)
|
390
413
|
if has_limit_or_offset?
|
391
414
|
limited_ids = limited_ids_for(relation)
|
392
415
|
limited_ids.empty? ? relation.none! : relation.where!(primary_key => limited_ids)
|
@@ -403,14 +426,14 @@ module ActiveRecord
|
|
403
426
|
|
404
427
|
def limited_ids_for(relation)
|
405
428
|
values = @klass.connection.columns_for_distinct(
|
406
|
-
connection.
|
429
|
+
connection.visitor.compile(table[primary_key]),
|
407
430
|
relation.order_values
|
408
431
|
)
|
409
432
|
|
410
433
|
relation = relation.except(:select).select(values).distinct!
|
411
434
|
|
412
|
-
id_rows = skip_query_cache_if_necessary { @klass.connection.
|
413
|
-
id_rows.map
|
435
|
+
id_rows = skip_query_cache_if_necessary { @klass.connection.select_rows(relation.arel, "SQL") }
|
436
|
+
id_rows.map(&:last)
|
414
437
|
end
|
415
438
|
|
416
439
|
def using_limitable_reflections?(reflections)
|
@@ -437,9 +460,6 @@ module ActiveRecord
|
|
437
460
|
else
|
438
461
|
find_some(ids)
|
439
462
|
end
|
440
|
-
rescue ::RangeError
|
441
|
-
error_message = "Couldn't find #{model_name} with an out of range ID"
|
442
|
-
raise RecordNotFound.new(error_message, model_name, primary_key, ids)
|
443
463
|
end
|
444
464
|
|
445
465
|
def find_one(id)
|
@@ -514,7 +534,8 @@ module ActiveRecord
|
|
514
534
|
end
|
515
535
|
|
516
536
|
def find_nth(index)
|
517
|
-
@offsets
|
537
|
+
@offsets ||= {}
|
538
|
+
@offsets[index] ||= find_nth_with_limit(index, 1).first
|
518
539
|
end
|
519
540
|
|
520
541
|
def find_nth_with_limit(index, limit)
|
@@ -528,7 +549,7 @@ module ActiveRecord
|
|
528
549
|
end
|
529
550
|
|
530
551
|
if limit > 0
|
531
|
-
relation = relation.offset(
|
552
|
+
relation = relation.offset((offset_value || 0) + index) unless index.zero?
|
532
553
|
relation.limit(limit).to_a
|
533
554
|
else
|
534
555
|
[]
|
@@ -555,8 +576,12 @@ module ActiveRecord
|
|
555
576
|
end
|
556
577
|
|
557
578
|
def ordered_relation
|
558
|
-
if order_values.empty? && primary_key
|
559
|
-
|
579
|
+
if order_values.empty? && (implicit_order_column || primary_key)
|
580
|
+
if implicit_order_column && primary_key && implicit_order_column != primary_key
|
581
|
+
order(table[implicit_order_column].asc, table[primary_key].asc)
|
582
|
+
else
|
583
|
+
order(table[implicit_order_column || primary_key].asc)
|
584
|
+
end
|
560
585
|
else
|
561
586
|
self
|
562
587
|
end
|
@@ -7,15 +7,16 @@ module ActiveRecord
|
|
7
7
|
class HashMerger # :nodoc:
|
8
8
|
attr_reader :relation, :hash
|
9
9
|
|
10
|
-
def initialize(relation, hash)
|
10
|
+
def initialize(relation, hash, rewhere = nil)
|
11
11
|
hash.assert_valid_keys(*Relation::VALUE_METHODS)
|
12
12
|
|
13
13
|
@relation = relation
|
14
14
|
@hash = hash
|
15
|
+
@rewhere = rewhere
|
15
16
|
end
|
16
17
|
|
17
|
-
def merge
|
18
|
-
Merger.new(relation, other).merge
|
18
|
+
def merge
|
19
|
+
Merger.new(relation, other, @rewhere).merge
|
19
20
|
end
|
20
21
|
|
21
22
|
# Applying values to a relation has some side effects. E.g.
|
@@ -28,19 +29,14 @@ module ActiveRecord
|
|
28
29
|
table: relation.table,
|
29
30
|
predicate_builder: relation.predicate_builder
|
30
31
|
)
|
31
|
-
hash.each
|
32
|
-
if k == :
|
33
|
-
|
34
|
-
|
35
|
-
else
|
36
|
-
other.joins!(*v)
|
37
|
-
end
|
38
|
-
elsif k == :select
|
39
|
-
other._select!(v)
|
32
|
+
hash.each do |k, v|
|
33
|
+
k = :_select if k == :select
|
34
|
+
if Array === v
|
35
|
+
other.public_send("#{k}!", *v)
|
40
36
|
else
|
41
|
-
other.
|
37
|
+
other.public_send("#{k}!", v)
|
42
38
|
end
|
43
|
-
|
39
|
+
end
|
44
40
|
other
|
45
41
|
end
|
46
42
|
end
|
@@ -48,10 +44,11 @@ module ActiveRecord
|
|
48
44
|
class Merger # :nodoc:
|
49
45
|
attr_reader :relation, :values, :other
|
50
46
|
|
51
|
-
def initialize(relation, other)
|
47
|
+
def initialize(relation, other, rewhere = nil)
|
52
48
|
@relation = relation
|
53
49
|
@values = other.values
|
54
50
|
@other = other
|
51
|
+
@rewhere = rewhere
|
55
52
|
end
|
56
53
|
|
57
54
|
NORMAL_VALUES = Relation::VALUE_METHODS -
|
@@ -73,7 +70,7 @@ module ActiveRecord
|
|
73
70
|
if name == :select
|
74
71
|
relation._select!(*value)
|
75
72
|
else
|
76
|
-
relation.
|
73
|
+
relation.public_send("#{name}!", *value)
|
77
74
|
end
|
78
75
|
end
|
79
76
|
end
|
@@ -89,13 +86,12 @@ module ActiveRecord
|
|
89
86
|
end
|
90
87
|
|
91
88
|
private
|
92
|
-
|
93
89
|
def merge_preloads
|
94
90
|
return if other.preload_values.empty? && other.includes_values.empty?
|
95
91
|
|
96
92
|
if other.klass == relation.klass
|
97
|
-
relation.
|
98
|
-
relation.
|
93
|
+
relation.preload_values |= other.preload_values unless other.preload_values.empty?
|
94
|
+
relation.includes_values |= other.includes_values unless other.includes_values.empty?
|
99
95
|
else
|
100
96
|
reflection = relation.klass.reflect_on_all_associations.find do |r|
|
101
97
|
r.class_name == other.klass.name
|
@@ -112,44 +108,40 @@ module ActiveRecord
|
|
112
108
|
end
|
113
109
|
|
114
110
|
def merge_joins
|
115
|
-
return if other.joins_values.
|
111
|
+
return if other.joins_values.empty?
|
116
112
|
|
117
113
|
if other.klass == relation.klass
|
118
|
-
relation.
|
114
|
+
relation.joins_values |= other.joins_values
|
119
115
|
else
|
120
|
-
|
116
|
+
associations, others = other.joins_values.partition do |join|
|
121
117
|
case join
|
122
|
-
when Hash, Symbol, Array
|
123
|
-
ActiveRecord::Associations::JoinDependency.new(
|
124
|
-
other.klass, other.table, join
|
125
|
-
)
|
126
|
-
else
|
127
|
-
join
|
118
|
+
when Hash, Symbol, Array; true
|
128
119
|
end
|
129
120
|
end
|
130
121
|
|
131
|
-
|
122
|
+
join_dependency = other.construct_join_dependency(
|
123
|
+
associations, Arel::Nodes::InnerJoin
|
124
|
+
)
|
125
|
+
relation.joins!(join_dependency, *others)
|
132
126
|
end
|
133
127
|
end
|
134
128
|
|
135
129
|
def merge_outer_joins
|
136
|
-
return if other.left_outer_joins_values.
|
130
|
+
return if other.left_outer_joins_values.empty?
|
137
131
|
|
138
132
|
if other.klass == relation.klass
|
139
|
-
relation.
|
133
|
+
relation.left_outer_joins_values |= other.left_outer_joins_values
|
140
134
|
else
|
141
|
-
|
135
|
+
associations, others = other.left_outer_joins_values.partition do |join|
|
142
136
|
case join
|
143
|
-
when Hash, Symbol, Array
|
144
|
-
ActiveRecord::Associations::JoinDependency.new(
|
145
|
-
other.klass, other.table, join
|
146
|
-
)
|
147
|
-
else
|
148
|
-
join
|
137
|
+
when Hash, Symbol, Array; true
|
149
138
|
end
|
150
139
|
end
|
151
140
|
|
152
|
-
|
141
|
+
join_dependency = other.construct_join_dependency(
|
142
|
+
associations, Arel::Nodes::OuterJoin
|
143
|
+
)
|
144
|
+
relation.left_outer_joins!(join_dependency, *others)
|
153
145
|
end
|
154
146
|
end
|
155
147
|
|
@@ -177,7 +169,7 @@ module ActiveRecord
|
|
177
169
|
def merge_clauses
|
178
170
|
relation.from_clause = other.from_clause if replace_from_clause?
|
179
171
|
|
180
|
-
where_clause = relation.where_clause.merge(other.where_clause)
|
172
|
+
where_clause = relation.where_clause.merge(other.where_clause, @rewhere)
|
181
173
|
relation.where_clause = where_clause unless where_clause.empty?
|
182
174
|
|
183
175
|
having_clause = relation.having_clause.merge(other.having_clause)
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/array/extract"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
class PredicateBuilder
|
5
7
|
class ArrayHandler # :nodoc:
|
@@ -11,31 +13,29 @@ module ActiveRecord
|
|
11
13
|
return attribute.in([]) if value.empty?
|
12
14
|
|
13
15
|
values = value.map { |x| x.is_a?(Base) ? x.id : x }
|
14
|
-
nils
|
15
|
-
ranges
|
16
|
+
nils = values.extract!(&:nil?)
|
17
|
+
ranges = values.extract! { |v| v.is_a?(Range) }
|
16
18
|
|
17
19
|
values_predicate =
|
18
20
|
case values.length
|
19
21
|
when 0 then NullPredicate
|
20
22
|
when 1 then predicate_builder.build(attribute, values.first)
|
21
|
-
else
|
22
|
-
values.map! do |v|
|
23
|
-
predicate_builder.build_bind_attribute(attribute.name, v)
|
24
|
-
end
|
25
|
-
values.empty? ? NullPredicate : attribute.in(values)
|
23
|
+
else Arel::Nodes::HomogeneousIn.new(values, attribute, :in)
|
26
24
|
end
|
27
25
|
|
28
26
|
unless nils.empty?
|
29
|
-
values_predicate = values_predicate.or(
|
27
|
+
values_predicate = values_predicate.or(attribute.eq(nil))
|
30
28
|
end
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
if ranges.empty?
|
31
|
+
values_predicate
|
32
|
+
else
|
33
|
+
array_predicates = ranges.map! { |range| predicate_builder.build(attribute, range) }
|
34
|
+
array_predicates.inject(values_predicate, &:or)
|
35
|
+
end
|
35
36
|
end
|
36
37
|
|
37
|
-
|
38
|
-
|
38
|
+
private
|
39
39
|
attr_reader :predicate_builder
|
40
40
|
|
41
41
|
module NullPredicate # :nodoc:
|
@@ -9,15 +9,12 @@ module ActiveRecord
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def queries
|
12
|
-
[associated_table.
|
12
|
+
[ associated_table.join_foreign_key => ids ]
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
17
|
-
protected
|
15
|
+
private
|
18
16
|
attr_reader :associated_table, :value
|
19
17
|
|
20
|
-
private
|
21
18
|
def ids
|
22
19
|
case value
|
23
20
|
when Relation
|
@@ -30,13 +27,12 @@ module ActiveRecord
|
|
30
27
|
end
|
31
28
|
|
32
29
|
def primary_key
|
33
|
-
associated_table.
|
30
|
+
associated_table.join_primary_key
|
34
31
|
end
|
35
32
|
|
36
33
|
def convert_to_id(value)
|
37
|
-
|
38
|
-
|
39
|
-
value._read_attribute(primary_key)
|
34
|
+
if value.respond_to?(primary_key)
|
35
|
+
value.public_send(primary_key)
|
40
36
|
else
|
41
37
|
value
|
42
38
|
end
|
@@ -9,29 +9,28 @@ module ActiveRecord
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def queries
|
12
|
+
return [ associated_table.join_foreign_key => values ] if values.empty?
|
13
|
+
|
12
14
|
type_to_ids_mapping.map do |type, ids|
|
13
|
-
{
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
query = {}
|
16
|
+
query[associated_table.join_foreign_type] = type if type
|
17
|
+
query[associated_table.join_foreign_key] = ids
|
18
|
+
query
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
|
-
|
21
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
22
|
-
protected
|
22
|
+
private
|
23
23
|
attr_reader :associated_table, :values
|
24
24
|
|
25
|
-
private
|
26
25
|
def type_to_ids_mapping
|
27
26
|
default_hash = Hash.new { |hsh, key| hsh[key] = [] }
|
28
27
|
values.each_with_object(default_hash) do |value, hash|
|
29
|
-
hash[klass(value)
|
28
|
+
hash[klass(value)&.polymorphic_name] << convert_to_id(value)
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
33
32
|
def primary_key(value)
|
34
|
-
associated_table.
|
33
|
+
associated_table.join_primary_key(klass(value))
|
35
34
|
end
|
36
35
|
|
37
36
|
def klass(value)
|
@@ -49,6 +48,8 @@ module ActiveRecord
|
|
49
48
|
value._read_attribute(primary_key(value))
|
50
49
|
when Relation
|
51
50
|
value.select(primary_key(value))
|
51
|
+
else
|
52
|
+
value
|
52
53
|
end
|
53
54
|
end
|
54
55
|
end
|
@@ -3,11 +3,7 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
class PredicateBuilder
|
5
5
|
class RangeHandler # :nodoc:
|
6
|
-
|
7
|
-
def exclude_end?
|
8
|
-
false
|
9
|
-
end
|
10
|
-
end
|
6
|
+
RangeWithBinds = Struct.new(:begin, :end, :exclude_end?)
|
11
7
|
|
12
8
|
def initialize(predicate_builder)
|
13
9
|
@predicate_builder = predicate_builder
|
@@ -16,26 +12,10 @@ module ActiveRecord
|
|
16
12
|
def call(attribute, value)
|
17
13
|
begin_bind = predicate_builder.build_bind_attribute(attribute.name, value.begin)
|
18
14
|
end_bind = predicate_builder.build_bind_attribute(attribute.name, value.end)
|
19
|
-
|
20
|
-
if begin_bind.value.infinity?
|
21
|
-
if end_bind.value.infinity?
|
22
|
-
attribute.not_in([])
|
23
|
-
elsif value.exclude_end?
|
24
|
-
attribute.lt(end_bind)
|
25
|
-
else
|
26
|
-
attribute.lteq(end_bind)
|
27
|
-
end
|
28
|
-
elsif end_bind.value.infinity?
|
29
|
-
attribute.gteq(begin_bind)
|
30
|
-
elsif value.exclude_end?
|
31
|
-
attribute.gteq(begin_bind).and(attribute.lt(end_bind))
|
32
|
-
else
|
33
|
-
attribute.between(RangeWithBinds.new(begin_bind, end_bind))
|
34
|
-
end
|
15
|
+
attribute.between(RangeWithBinds.new(begin_bind, end_bind, value.exclude_end?))
|
35
16
|
end
|
36
17
|
|
37
|
-
|
38
|
-
|
18
|
+
private
|
39
19
|
attr_reader :predicate_builder
|
40
20
|
end
|
41
21
|
end
|