activerecord 5.2.4.5 → 6.0.0.beta1
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 +299 -739
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +2 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/associations/association.rb +35 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +15 -20
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +15 -16
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +76 -43
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +184 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +74 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration.rb +38 -37
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- data/lib/active_record/model_schema.rb +30 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -42
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -6
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +38 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/arel.rb +44 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +67 -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/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 +63 -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 +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.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +104 -26
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
Copyright (c) 2004-
|
1
|
+
Copyright (c) 2004-2019 David Heinemeier Hansson
|
2
|
+
|
3
|
+
Arel originally copyright (c) 2007-2016 Nick Kallen, Bryan Helmkamp, Emilio Tagua, Aaron Patterson
|
2
4
|
|
3
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
6
|
a copy of this software and associated documentation files (the
|
data/README.rdoc
CHANGED
@@ -192,7 +192,7 @@ The latest version of Active Record can be installed with RubyGems:
|
|
192
192
|
|
193
193
|
Source code can be downloaded as part of the Rails project on GitHub:
|
194
194
|
|
195
|
-
* https://github.com/rails/rails/tree/
|
195
|
+
* https://github.com/rails/rails/tree/master/activerecord
|
196
196
|
|
197
197
|
|
198
198
|
== License
|
data/examples/performance.rb
CHANGED
data/lib/active_record.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2004-
|
4
|
+
# Copyright (c) 2004-2019 David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -163,6 +163,7 @@ module ActiveRecord
|
|
163
163
|
"active_record/tasks/postgresql_database_tasks"
|
164
164
|
end
|
165
165
|
|
166
|
+
autoload :TestDatabases, "active_record/test_databases"
|
166
167
|
autoload :TestFixtures, "active_record/fixtures"
|
167
168
|
|
168
169
|
def self.eager_load!
|
@@ -3,8 +3,6 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
# See ActiveRecord::Aggregations::ClassMethods for documentation
|
5
5
|
module Aggregations
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
6
|
def initialize_dup(*) # :nodoc:
|
9
7
|
@aggregation_cache = {}
|
10
8
|
super
|
@@ -225,6 +223,10 @@ module ActiveRecord
|
|
225
223
|
def composed_of(part_id, options = {})
|
226
224
|
options.assert_valid_keys(:class_name, :mapping, :allow_nil, :constructor, :converter)
|
227
225
|
|
226
|
+
unless self < Aggregations
|
227
|
+
include Aggregations
|
228
|
+
end
|
229
|
+
|
228
230
|
name = part_id.id2name
|
229
231
|
class_name = options[:class_name] || name.camelize
|
230
232
|
mapping = options[:mapping] || [ name, name ]
|
@@ -292,13 +292,13 @@ module ActiveRecord
|
|
292
292
|
#
|
293
293
|
# The project class now has the following methods (and more) to ease the traversal and
|
294
294
|
# manipulation of its relationships:
|
295
|
-
# * <tt>Project#portfolio
|
296
|
-
# * <tt>Project#project_manager
|
297
|
-
# * <tt>Project#milestones.empty
|
298
|
-
# <tt>Project#milestones.delete(milestone)
|
299
|
-
# <tt>Project#milestones.build
|
300
|
-
# * <tt>Project#categories.empty
|
301
|
-
# <tt>Project#categories.delete(category1)
|
295
|
+
# * <tt>Project#portfolio</tt>, <tt>Project#portfolio=(portfolio)</tt>, <tt>Project#reload_portfolio</tt>
|
296
|
+
# * <tt>Project#project_manager</tt>, <tt>Project#project_manager=(project_manager)</tt>, <tt>Project#reload_project_manager</tt>
|
297
|
+
# * <tt>Project#milestones.empty?</tt>, <tt>Project#milestones.size</tt>, <tt>Project#milestones</tt>, <tt>Project#milestones<<(milestone)</tt>,
|
298
|
+
# <tt>Project#milestones.delete(milestone)</tt>, <tt>Project#milestones.destroy(milestone)</tt>, <tt>Project#milestones.find(milestone_id)</tt>,
|
299
|
+
# <tt>Project#milestones.build</tt>, <tt>Project#milestones.create</tt>
|
300
|
+
# * <tt>Project#categories.empty?</tt>, <tt>Project#categories.size</tt>, <tt>Project#categories</tt>, <tt>Project#categories<<(category1)</tt>,
|
301
|
+
# <tt>Project#categories.delete(category1)</tt>, <tt>Project#categories.destroy(category1)</tt>
|
302
302
|
#
|
303
303
|
# === A word of warning
|
304
304
|
#
|
@@ -1293,8 +1293,9 @@ module ActiveRecord
|
|
1293
1293
|
#
|
1294
1294
|
# * <tt>:destroy</tt> causes all the associated objects to also be destroyed.
|
1295
1295
|
# * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
|
1296
|
-
# * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+.
|
1297
|
-
#
|
1296
|
+
# * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Polymorphic type will also be nullified
|
1297
|
+
# on polymorphic associations. Callbacks are not executed.
|
1298
|
+
# * <tt>:restrict_with_exception</tt> causes an <tt>ActiveRecord::DeleteRestrictionError</tt> exception to be raised if there are any associated records.
|
1298
1299
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
|
1299
1300
|
#
|
1300
1301
|
# If using with the <tt>:through</tt> option, the association on the join model must be
|
@@ -1436,8 +1437,9 @@ module ActiveRecord
|
|
1436
1437
|
#
|
1437
1438
|
# * <tt>:destroy</tt> causes the associated object to also be destroyed
|
1438
1439
|
# * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
|
1439
|
-
# * <tt>:nullify</tt> causes the foreign key to be set to +NULL+.
|
1440
|
-
#
|
1440
|
+
# * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Polymorphic type column is also nullified
|
1441
|
+
# on polymorphic associations. Callbacks are not executed.
|
1442
|
+
# * <tt>:restrict_with_exception</tt> causes an <tt>ActiveRecord::DeleteRestrictionError</tt> exception to be raised if there is an associated record
|
1441
1443
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
|
1442
1444
|
#
|
1443
1445
|
# Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
|
@@ -1524,6 +1526,7 @@ module ActiveRecord
|
|
1524
1526
|
# Returns the associated object. +nil+ is returned if none is found.
|
1525
1527
|
# [association=(associate)]
|
1526
1528
|
# Assigns the associate object, extracts the primary key, and sets it as the foreign key.
|
1529
|
+
# No modification or deletion of existing records takes place.
|
1527
1530
|
# [build_association(attributes = {})]
|
1528
1531
|
# Returns a new object of the associated type that has been instantiated
|
1529
1532
|
# with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
|
@@ -1581,7 +1584,7 @@ module ActiveRecord
|
|
1581
1584
|
# association will use "taggable_type" as the default <tt>:foreign_type</tt>.
|
1582
1585
|
# [:primary_key]
|
1583
1586
|
# Specify the method that returns the primary key of associated object used for the association.
|
1584
|
-
# By default this is id
|
1587
|
+
# By default this is +id+.
|
1585
1588
|
# [:dependent]
|
1586
1589
|
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
1587
1590
|
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
|
@@ -1761,6 +1764,7 @@ module ActiveRecord
|
|
1761
1764
|
# has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
|
1762
1765
|
# has_and_belongs_to_many :categories, ->(post) {
|
1763
1766
|
# where("default_category = ?", post.default_category)
|
1767
|
+
# }
|
1764
1768
|
#
|
1765
1769
|
# === Extensions
|
1766
1770
|
#
|
@@ -40,7 +40,9 @@ module ActiveRecord
|
|
40
40
|
end
|
41
41
|
|
42
42
|
# Reloads the \target and returns +self+ on success.
|
43
|
-
|
43
|
+
# The QueryCache is cleared if +force+ is true.
|
44
|
+
def reload(force = false)
|
45
|
+
klass.connection.clear_query_cache if force && klass
|
44
46
|
reset
|
45
47
|
reset_scope
|
46
48
|
load_target
|
@@ -79,18 +81,6 @@ module ActiveRecord
|
|
79
81
|
target_scope.merge!(association_scope)
|
80
82
|
end
|
81
83
|
|
82
|
-
# The scope for this association.
|
83
|
-
#
|
84
|
-
# Note that the association_scope is merged into the target_scope only when the
|
85
|
-
# scope method is called. This is because at that point the call may be surrounded
|
86
|
-
# by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
|
87
|
-
# actually gets built.
|
88
|
-
def association_scope
|
89
|
-
if klass
|
90
|
-
@association_scope ||= AssociationScope.scope(self)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
84
|
def reset_scope
|
95
85
|
@association_scope = nil
|
96
86
|
end
|
@@ -129,12 +119,6 @@ module ActiveRecord
|
|
129
119
|
reflection.klass
|
130
120
|
end
|
131
121
|
|
132
|
-
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
133
|
-
# through association's scope)
|
134
|
-
def target_scope
|
135
|
-
AssociationRelation.create(klass, self).merge!(klass.all)
|
136
|
-
end
|
137
|
-
|
138
122
|
def extensions
|
139
123
|
extensions = klass.default_extensions | reflection.extensions
|
140
124
|
|
@@ -195,6 +179,38 @@ module ActiveRecord
|
|
195
179
|
end
|
196
180
|
|
197
181
|
private
|
182
|
+
def find_target
|
183
|
+
scope = self.scope
|
184
|
+
return scope.to_a if skip_statement_cache?(scope)
|
185
|
+
|
186
|
+
conn = klass.connection
|
187
|
+
sc = reflection.association_scope_cache(conn, owner) do |params|
|
188
|
+
as = AssociationScope.create { params.bind }
|
189
|
+
target_scope.merge!(as.scope(self))
|
190
|
+
end
|
191
|
+
|
192
|
+
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
193
|
+
sc.execute(binds, conn) { |record| set_inverse_instance(record) } || []
|
194
|
+
end
|
195
|
+
|
196
|
+
# The scope for this association.
|
197
|
+
#
|
198
|
+
# Note that the association_scope is merged into the target_scope only when the
|
199
|
+
# scope method is called. This is because at that point the call may be surrounded
|
200
|
+
# by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
|
201
|
+
# actually gets built.
|
202
|
+
def association_scope
|
203
|
+
if klass
|
204
|
+
@association_scope ||= AssociationScope.scope(self)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
209
|
+
# through association's scope)
|
210
|
+
def target_scope
|
211
|
+
AssociationRelation.create(klass, self).merge!(klass.all)
|
212
|
+
end
|
213
|
+
|
198
214
|
def scope_for_create
|
199
215
|
scope.scope_for_create
|
200
216
|
end
|
@@ -26,7 +26,9 @@ module ActiveRecord
|
|
26
26
|
chain = get_chain(reflection, association, scope.alias_tracker)
|
27
27
|
|
28
28
|
scope.extending! reflection.extensions
|
29
|
-
add_constraints(scope, owner, chain)
|
29
|
+
scope = add_constraints(scope, owner, chain)
|
30
|
+
scope.limit!(1) unless reflection.collection?
|
31
|
+
scope
|
30
32
|
end
|
31
33
|
|
32
34
|
def self.get_bind_values(owner, chain)
|
@@ -46,13 +48,9 @@ module ActiveRecord
|
|
46
48
|
binds
|
47
49
|
end
|
48
50
|
|
49
|
-
|
50
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
51
|
-
protected
|
52
|
-
|
51
|
+
private
|
53
52
|
attr_reader :value_transformation
|
54
53
|
|
55
|
-
private
|
56
54
|
def join(table, constraint)
|
57
55
|
table.create_join(table, table.create_on(constraint))
|
58
56
|
end
|
@@ -16,21 +16,6 @@ module ActiveRecord
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def replace(record)
|
20
|
-
if record
|
21
|
-
raise_on_type_mismatch!(record)
|
22
|
-
update_counters_on_replace(record)
|
23
|
-
set_inverse_instance(record)
|
24
|
-
@updated = true
|
25
|
-
else
|
26
|
-
decrement_counters
|
27
|
-
end
|
28
|
-
|
29
|
-
replace_keys(record)
|
30
|
-
|
31
|
-
self.target = record
|
32
|
-
end
|
33
|
-
|
34
19
|
def inversed_from(record)
|
35
20
|
replace_keys(record)
|
36
21
|
super
|
@@ -49,30 +34,60 @@ module ActiveRecord
|
|
49
34
|
@updated
|
50
35
|
end
|
51
36
|
|
52
|
-
def decrement_counters
|
37
|
+
def decrement_counters
|
53
38
|
update_counters(-1)
|
54
39
|
end
|
55
40
|
|
56
|
-
def increment_counters
|
41
|
+
def increment_counters
|
57
42
|
update_counters(1)
|
58
43
|
end
|
59
44
|
|
45
|
+
def decrement_counters_before_last_save
|
46
|
+
if reflection.polymorphic?
|
47
|
+
model_was = owner.attribute_before_last_save(reflection.foreign_type).try(:constantize)
|
48
|
+
else
|
49
|
+
model_was = klass
|
50
|
+
end
|
51
|
+
|
52
|
+
foreign_key_was = owner.attribute_before_last_save(reflection.foreign_key)
|
53
|
+
|
54
|
+
if foreign_key_was && model_was < ActiveRecord::Base
|
55
|
+
update_counters_via_scope(model_was, foreign_key_was, -1)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
60
59
|
def target_changed?
|
61
60
|
owner.saved_change_to_attribute?(reflection.foreign_key)
|
62
61
|
end
|
63
62
|
|
64
63
|
private
|
64
|
+
def replace(record)
|
65
|
+
if record
|
66
|
+
raise_on_type_mismatch!(record)
|
67
|
+
set_inverse_instance(record)
|
68
|
+
@updated = true
|
69
|
+
end
|
70
|
+
|
71
|
+
replace_keys(record)
|
72
|
+
|
73
|
+
self.target = record
|
74
|
+
end
|
65
75
|
|
66
76
|
def update_counters(by)
|
67
77
|
if require_counter_update? && foreign_key_present?
|
68
78
|
if target && !stale_target?
|
69
79
|
target.increment!(reflection.counter_cache_column, by, touch: reflection.options[:touch])
|
70
80
|
else
|
71
|
-
klass.
|
81
|
+
update_counters_via_scope(klass, owner._read_attribute(reflection.foreign_key), by)
|
72
82
|
end
|
73
83
|
end
|
74
84
|
end
|
75
85
|
|
86
|
+
def update_counters_via_scope(klass, foreign_key, by)
|
87
|
+
scope = klass.unscoped.where!(primary_key(klass) => foreign_key)
|
88
|
+
scope.update_counters(reflection.counter_cache_column => by, touch: reflection.options[:touch])
|
89
|
+
end
|
90
|
+
|
76
91
|
def find_target?
|
77
92
|
!loaded? && foreign_key_present? && klass
|
78
93
|
end
|
@@ -81,25 +96,12 @@ module ActiveRecord
|
|
81
96
|
reflection.counter_cache_column && owner.persisted?
|
82
97
|
end
|
83
98
|
|
84
|
-
def update_counters_on_replace(record)
|
85
|
-
if require_counter_update? && different_target?(record)
|
86
|
-
owner.instance_variable_set :@_after_replace_counter_called, true
|
87
|
-
record.increment!(reflection.counter_cache_column, touch: reflection.options[:touch])
|
88
|
-
decrement_counters
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Checks whether record is different to the current target, without loading it
|
93
|
-
def different_target?(record)
|
94
|
-
record._read_attribute(primary_key(record)) != owner._read_attribute(reflection.foreign_key)
|
95
|
-
end
|
96
|
-
|
97
99
|
def replace_keys(record)
|
98
|
-
owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record)) : nil
|
100
|
+
owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record.class)) : nil
|
99
101
|
end
|
100
102
|
|
101
|
-
def primary_key(
|
102
|
-
reflection.association_primary_key(
|
103
|
+
def primary_key(klass)
|
104
|
+
reflection.association_primary_key(klass)
|
103
105
|
end
|
104
106
|
|
105
107
|
def foreign_key_present?
|
@@ -113,14 +115,6 @@ module ActiveRecord
|
|
113
115
|
inverse && inverse.has_one?
|
114
116
|
end
|
115
117
|
|
116
|
-
def target_id
|
117
|
-
if options[:primary_key]
|
118
|
-
owner.send(reflection.name).try(:id)
|
119
|
-
else
|
120
|
-
owner._read_attribute(reflection.foreign_key)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
118
|
def stale_state
|
125
119
|
result = owner._read_attribute(reflection.foreign_key) { |n| owner.send(:missing_attribute, n, caller) }
|
126
120
|
result && result.to_s
|
@@ -19,10 +19,6 @@ module ActiveRecord
|
|
19
19
|
owner[reflection.foreign_type] = record ? record.class.polymorphic_name : nil
|
20
20
|
end
|
21
21
|
|
22
|
-
def different_target?(record)
|
23
|
-
super || record.class != klass
|
24
|
-
end
|
25
|
-
|
26
22
|
def inverse_reflection_for(record)
|
27
23
|
reflection.polymorphic_inverse_of(record.class)
|
28
24
|
end
|
@@ -21,58 +21,16 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
21
21
|
add_default_callbacks(model, reflection) if reflection.options[:default]
|
22
22
|
end
|
23
23
|
|
24
|
-
def self.define_accessors(mixin, reflection)
|
25
|
-
super
|
26
|
-
add_counter_cache_methods mixin
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.add_counter_cache_methods(mixin)
|
30
|
-
return if mixin.method_defined? :belongs_to_counter_cache_after_update
|
31
|
-
|
32
|
-
mixin.class_eval do
|
33
|
-
def belongs_to_counter_cache_after_update(reflection)
|
34
|
-
foreign_key = reflection.foreign_key
|
35
|
-
cache_column = reflection.counter_cache_column
|
36
|
-
|
37
|
-
if (@_after_replace_counter_called ||= false)
|
38
|
-
@_after_replace_counter_called = false
|
39
|
-
elsif association(reflection.name).target_changed?
|
40
|
-
if reflection.polymorphic?
|
41
|
-
model = attribute_in_database(reflection.foreign_type).try(:constantize)
|
42
|
-
model_was = attribute_before_last_save(reflection.foreign_type).try(:constantize)
|
43
|
-
else
|
44
|
-
model = reflection.klass
|
45
|
-
model_was = reflection.klass
|
46
|
-
end
|
47
|
-
|
48
|
-
foreign_key_was = attribute_before_last_save foreign_key
|
49
|
-
foreign_key = attribute_in_database foreign_key
|
50
|
-
|
51
|
-
if foreign_key && model.respond_to?(:increment_counter)
|
52
|
-
foreign_key = counter_cache_target(reflection, model, foreign_key)
|
53
|
-
model.increment_counter(cache_column, foreign_key)
|
54
|
-
end
|
55
|
-
|
56
|
-
if foreign_key_was && model_was.respond_to?(:decrement_counter)
|
57
|
-
foreign_key_was = counter_cache_target(reflection, model_was, foreign_key_was)
|
58
|
-
model_was.decrement_counter(cache_column, foreign_key_was)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
def counter_cache_target(reflection, model, foreign_key)
|
65
|
-
primary_key = reflection.association_primary_key(model)
|
66
|
-
model.unscoped.where!(primary_key => foreign_key)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
24
|
def self.add_counter_cache_callbacks(model, reflection)
|
72
25
|
cache_column = reflection.counter_cache_column
|
73
26
|
|
74
27
|
model.after_update lambda { |record|
|
75
|
-
|
28
|
+
association = association(reflection.name)
|
29
|
+
|
30
|
+
if association.target_changed?
|
31
|
+
association.increment_counters
|
32
|
+
association.decrement_counters_before_last_save
|
33
|
+
end
|
76
34
|
}
|
77
35
|
|
78
36
|
klass = reflection.class_name.safe_constantize
|
@@ -123,12 +81,18 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
123
81
|
BelongsTo.touch_record(record, record.send(changes_method), foreign_key, n, touch, belongs_to_touch_method)
|
124
82
|
}}
|
125
83
|
|
126
|
-
|
84
|
+
if reflection.counter_cache_column
|
85
|
+
touch_callback = callback.(:saved_changes)
|
86
|
+
update_callback = lambda { |record|
|
87
|
+
instance_exec(record, &touch_callback) unless association(reflection.name).target_changed?
|
88
|
+
}
|
89
|
+
model.after_update update_callback, if: :saved_changes?
|
90
|
+
else
|
127
91
|
model.after_create callback.(:saved_changes), if: :saved_changes?
|
92
|
+
model.after_update callback.(:saved_changes), if: :saved_changes?
|
128
93
|
model.after_destroy callback.(:changes_to_save)
|
129
94
|
end
|
130
95
|
|
131
|
-
model.after_update callback.(:saved_changes), if: :saved_changes?
|
132
96
|
model.after_touch callback.(:changes_to_save)
|
133
97
|
end
|
134
98
|
|