activerecord 5.1.7 → 5.2.8.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 +629 -661
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +41 -37
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +27 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +12 -4
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +59 -47
- data/lib/active_record/associations/collection_proxy.rb +20 -49
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +12 -1
- data/lib/active_record/associations/has_many_through_association.rb +36 -30
- data/lib/active_record/associations/has_one_association.rb +12 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/join_dependency.rb +48 -93
- data/lib/active_record/associations/preloader/association.rb +45 -61
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/preloader.rb +18 -38
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/associations.rb +40 -63
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +30 -214
- data/lib/active_record/attribute_methods/primary_key.rb +7 -6
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +9 -3
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +21 -9
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attributes.rb +6 -5
- data/lib/active_record/autosave_association.rb +35 -19
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +8 -6
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +15 -1
- data/lib/active_record/collection_cache_key.rb +12 -8
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +139 -41
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -31
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
- data/lib/active_record/connection_adapters/column.rb +3 -1
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +233 -111
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -73
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +81 -94
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +51 -61
- data/lib/active_record/counter_cache.rb +10 -3
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -13
- data/lib/active_record/errors.rb +42 -3
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +67 -60
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +49 -19
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +14 -17
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +43 -0
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +47 -9
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/model_schema.rb +16 -21
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +167 -16
- data/lib/active_record/query_cache.rb +6 -8
- data/lib/active_record/querying.rb +4 -2
- data/lib/active_record/railtie.rb +80 -6
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +46 -36
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +108 -194
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/calculations.rb +45 -19
- data/lib/active_record/relation/delegation.rb +45 -27
- data/lib/active_record/relation/finder_methods.rb +75 -76
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +60 -79
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +128 -99
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- data/lib/active_record/relation/where_clause.rb +65 -68
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/relation.rb +120 -214
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping/default.rb +8 -9
- data/lib/active_record/scoping/named.rb +23 -7
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +23 -13
- data/lib/active_record/store.rb +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +25 -14
- data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
- data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +6 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +33 -28
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +2 -0
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +35 -5
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/version.rb +2 -0
- data/lib/active_record.rb +11 -4
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +3 -1
- metadata +26 -39
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute_mutation_tracker.rb +0 -122
- data/lib/active_record/attribute_set/builder.rb +0 -126
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,6 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "active_support/core_ext/string/filters"
|
3
|
-
require "
|
4
|
+
require "concurrent/map"
|
4
5
|
|
5
6
|
module ActiveRecord
|
6
7
|
# = Active Record Reflection
|
@@ -8,10 +9,8 @@ module ActiveRecord
|
|
8
9
|
extend ActiveSupport::Concern
|
9
10
|
|
10
11
|
included do
|
11
|
-
class_attribute :_reflections, instance_writer: false
|
12
|
-
class_attribute :aggregate_reflections, instance_writer: false
|
13
|
-
self._reflections = {}
|
14
|
-
self.aggregate_reflections = {}
|
12
|
+
class_attribute :_reflections, instance_writer: false, default: {}
|
13
|
+
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
15
14
|
end
|
16
15
|
|
17
16
|
def self.create(macro, name, scope, options, ar)
|
@@ -139,7 +138,7 @@ module ActiveRecord
|
|
139
138
|
# HasAndBelongsToManyReflection
|
140
139
|
# ThroughReflection
|
141
140
|
# PolymorphicReflection
|
142
|
-
#
|
141
|
+
# RuntimeReflection
|
143
142
|
class AbstractReflection # :nodoc:
|
144
143
|
def through_reflection?
|
145
144
|
false
|
@@ -155,14 +154,6 @@ module ActiveRecord
|
|
155
154
|
klass.new(attributes, &block)
|
156
155
|
end
|
157
156
|
|
158
|
-
def quoted_table_name
|
159
|
-
klass.quoted_table_name
|
160
|
-
end
|
161
|
-
|
162
|
-
def primary_key_type
|
163
|
-
klass.type_for_attribute(klass.primary_key)
|
164
|
-
end
|
165
|
-
|
166
157
|
# Returns the class name for the macro.
|
167
158
|
#
|
168
159
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
|
@@ -174,7 +165,7 @@ module ActiveRecord
|
|
174
165
|
JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
|
175
166
|
|
176
167
|
def join_keys
|
177
|
-
get_join_keys
|
168
|
+
@join_keys ||= get_join_keys(klass)
|
178
169
|
end
|
179
170
|
|
180
171
|
# Returns a list of scopes that should be applied for this Reflection
|
@@ -183,22 +174,30 @@ module ActiveRecord
|
|
183
174
|
scope ? [scope] : []
|
184
175
|
end
|
185
176
|
|
186
|
-
def
|
187
|
-
chain.map(&:scopes)
|
188
|
-
end
|
189
|
-
deprecate :scope_chain
|
190
|
-
|
191
|
-
def join_scope(table)
|
177
|
+
def join_scope(table, foreign_table, foreign_klass)
|
192
178
|
predicate_builder = predicate_builder(table)
|
193
179
|
scope_chain_items = join_scopes(table, predicate_builder)
|
194
180
|
klass_scope = klass_join_scope(table, predicate_builder)
|
195
181
|
|
196
|
-
|
182
|
+
key = join_keys.key
|
183
|
+
foreign_key = join_keys.foreign_key
|
184
|
+
|
185
|
+
klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
|
186
|
+
|
187
|
+
if type
|
188
|
+
klass_scope.where!(type => foreign_klass.polymorphic_name)
|
189
|
+
end
|
190
|
+
|
191
|
+
if klass.finder_needs_type_condition?
|
192
|
+
klass_scope.where!(klass.send(:type_condition, table))
|
193
|
+
end
|
194
|
+
|
195
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
197
196
|
end
|
198
197
|
|
199
198
|
def join_scopes(table, predicate_builder) # :nodoc:
|
200
199
|
if scope
|
201
|
-
[build_scope(table, predicate_builder)
|
200
|
+
[scope_for(build_scope(table, predicate_builder))]
|
202
201
|
else
|
203
202
|
[]
|
204
203
|
end
|
@@ -210,7 +209,7 @@ module ActiveRecord
|
|
210
209
|
end
|
211
210
|
|
212
211
|
def constraints
|
213
|
-
chain.
|
212
|
+
chain.flat_map(&:scopes)
|
214
213
|
end
|
215
214
|
|
216
215
|
def counter_cache_column
|
@@ -284,24 +283,37 @@ module ActiveRecord
|
|
284
283
|
end
|
285
284
|
|
286
285
|
def get_join_keys(association_klass)
|
287
|
-
JoinKeys.new(
|
286
|
+
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
288
287
|
end
|
289
288
|
|
290
289
|
def build_scope(table, predicate_builder = predicate_builder(table))
|
291
|
-
Relation.create(
|
290
|
+
Relation.create(
|
291
|
+
klass,
|
292
|
+
table: table,
|
293
|
+
predicate_builder: predicate_builder
|
294
|
+
)
|
295
|
+
end
|
296
|
+
|
297
|
+
def join_primary_key(*)
|
298
|
+
foreign_key
|
299
|
+
end
|
300
|
+
|
301
|
+
def join_foreign_key
|
302
|
+
active_record_primary_key
|
292
303
|
end
|
293
304
|
|
305
|
+
protected
|
306
|
+
def actual_source_reflection # FIXME: this is a horrible name
|
307
|
+
self
|
308
|
+
end
|
309
|
+
|
294
310
|
private
|
295
311
|
def predicate_builder(table)
|
296
312
|
PredicateBuilder.new(TableMetadata.new(klass, table))
|
297
313
|
end
|
298
314
|
|
299
|
-
def
|
300
|
-
|
301
|
-
end
|
302
|
-
|
303
|
-
def join_fk
|
304
|
-
active_record_primary_key
|
315
|
+
def primary_key(klass)
|
316
|
+
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
305
317
|
end
|
306
318
|
end
|
307
319
|
|
@@ -348,6 +360,17 @@ module ActiveRecord
|
|
348
360
|
#
|
349
361
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
|
350
362
|
# <tt>has_many :clients</tt> returns the Client class
|
363
|
+
#
|
364
|
+
# class Company < ActiveRecord::Base
|
365
|
+
# has_many :clients
|
366
|
+
# end
|
367
|
+
#
|
368
|
+
# Company.reflect_on_association(:clients).klass
|
369
|
+
# # => Client
|
370
|
+
#
|
371
|
+
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
372
|
+
# a new association object. Use +build_association+ or +create_association+
|
373
|
+
# instead. This allows plugins to hook into association object creation.
|
351
374
|
def klass
|
352
375
|
@klass ||= compute_class(class_name)
|
353
376
|
end
|
@@ -366,8 +389,8 @@ module ActiveRecord
|
|
366
389
|
active_record == other_aggregation.active_record
|
367
390
|
end
|
368
391
|
|
369
|
-
def scope_for(
|
370
|
-
|
392
|
+
def scope_for(relation, owner = nil)
|
393
|
+
relation.instance_exec(owner, &scope) || relation
|
371
394
|
end
|
372
395
|
|
373
396
|
private
|
@@ -388,23 +411,10 @@ module ActiveRecord
|
|
388
411
|
# Holds all the metadata about an association as it was specified in the
|
389
412
|
# Active Record class.
|
390
413
|
class AssociationReflection < MacroReflection #:nodoc:
|
391
|
-
# Returns the target association's class.
|
392
|
-
#
|
393
|
-
# class Author < ActiveRecord::Base
|
394
|
-
# has_many :books
|
395
|
-
# end
|
396
|
-
#
|
397
|
-
# Author.reflect_on_association(:books).klass
|
398
|
-
# # => Book
|
399
|
-
#
|
400
|
-
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
401
|
-
# a new association object. Use +build_association+ or +create_association+
|
402
|
-
# instead. This allows plugins to hook into association object creation.
|
403
|
-
def klass
|
404
|
-
@klass ||= compute_class(class_name)
|
405
|
-
end
|
406
|
-
|
407
414
|
def compute_class(name)
|
415
|
+
if polymorphic?
|
416
|
+
raise ArgumentError, "Polymorphic association does not support to compute class."
|
417
|
+
end
|
408
418
|
active_record.send(:compute_type, name)
|
409
419
|
end
|
410
420
|
|
@@ -414,31 +424,21 @@ module ActiveRecord
|
|
414
424
|
def initialize(name, scope, options, active_record)
|
415
425
|
super
|
416
426
|
@type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
|
417
|
-
@foreign_type = options[:foreign_type] || "#{name}_type"
|
427
|
+
@foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
|
418
428
|
@constructable = calculate_constructable(macro, options)
|
419
|
-
@association_scope_cache =
|
420
|
-
@scope_lock = Mutex.new
|
429
|
+
@association_scope_cache = Concurrent::Map.new
|
421
430
|
|
422
431
|
if options[:class_name] && options[:class_name].class == Class
|
423
|
-
|
424
|
-
Passing a class to the `class_name` is deprecated and will raise
|
425
|
-
an ArgumentError in Rails 5.2. It eagerloads more classes than
|
426
|
-
necessary and potentially creates circular dependencies.
|
427
|
-
|
428
|
-
Please pass the class name as a string:
|
429
|
-
`#{macro} :#{name}, class_name: '#{options[:class_name]}'`
|
430
|
-
MSG
|
432
|
+
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
431
433
|
end
|
432
434
|
end
|
433
435
|
|
434
|
-
def association_scope_cache(conn, owner)
|
436
|
+
def association_scope_cache(conn, owner, &block)
|
435
437
|
key = conn.prepared_statements
|
436
438
|
if polymorphic?
|
437
439
|
key = [key, owner._read_attribute(@foreign_type)]
|
438
440
|
end
|
439
|
-
@association_scope_cache
|
440
|
-
@association_scope_cache[key] ||= yield
|
441
|
-
}
|
441
|
+
@association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
|
442
442
|
end
|
443
443
|
|
444
444
|
def constructable? # :nodoc:
|
@@ -462,10 +462,6 @@ module ActiveRecord
|
|
462
462
|
options[:primary_key] || primary_key(klass || self.klass)
|
463
463
|
end
|
464
464
|
|
465
|
-
def association_primary_key_type
|
466
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
467
|
-
end
|
468
|
-
|
469
465
|
def active_record_primary_key
|
470
466
|
@active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
|
471
467
|
end
|
@@ -488,7 +484,7 @@ module ActiveRecord
|
|
488
484
|
alias :check_eager_loadable! :check_preloadable!
|
489
485
|
|
490
486
|
def join_id_for(owner) # :nodoc:
|
491
|
-
owner[
|
487
|
+
owner[join_foreign_key]
|
492
488
|
end
|
493
489
|
|
494
490
|
def through_reflection
|
@@ -571,7 +567,7 @@ module ActiveRecord
|
|
571
567
|
end
|
572
568
|
|
573
569
|
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
574
|
-
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:
|
570
|
+
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
|
575
571
|
|
576
572
|
def add_as_source(seed)
|
577
573
|
seed
|
@@ -589,12 +585,6 @@ module ActiveRecord
|
|
589
585
|
Array(options[:extend])
|
590
586
|
end
|
591
587
|
|
592
|
-
protected
|
593
|
-
|
594
|
-
def actual_source_reflection # FIXME: this is a horrible name
|
595
|
-
self
|
596
|
-
end
|
597
|
-
|
598
588
|
private
|
599
589
|
|
600
590
|
def calculate_constructable(macro, options)
|
@@ -635,12 +625,9 @@ module ActiveRecord
|
|
635
625
|
# +automatic_inverse_of+ method is a valid reflection. We must
|
636
626
|
# make sure that the reflection's active_record name matches up
|
637
627
|
# with the current reflection's klass name.
|
638
|
-
#
|
639
|
-
# Note: klass will always be valid because when there's a NameError
|
640
|
-
# from calling +klass+, +reflection+ will already be set to false.
|
641
628
|
def valid_inverse_reflection?(reflection)
|
642
629
|
reflection &&
|
643
|
-
klass
|
630
|
+
klass <= reflection.active_record &&
|
644
631
|
can_find_inverse_of_automatically?(reflection)
|
645
632
|
end
|
646
633
|
|
@@ -648,9 +635,8 @@ module ActiveRecord
|
|
648
635
|
# us from being able to guess the inverse automatically. First, the
|
649
636
|
# <tt>inverse_of</tt> option cannot be set to false. Second, we must
|
650
637
|
# have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
|
651
|
-
# Third, we must not have options such as <tt>:
|
652
|
-
#
|
653
|
-
# inverse association.
|
638
|
+
# Third, we must not have options such as <tt>:foreign_key</tt>
|
639
|
+
# which prevent us from correctly guessing the inverse association.
|
654
640
|
#
|
655
641
|
# Anything with a scope can additionally ruin our attempt at finding an
|
656
642
|
# inverse, so we exclude reflections with scopes.
|
@@ -680,10 +666,6 @@ module ActiveRecord
|
|
680
666
|
def derive_join_table
|
681
667
|
ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
|
682
668
|
end
|
683
|
-
|
684
|
-
def primary_key(klass)
|
685
|
-
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
686
|
-
end
|
687
669
|
end
|
688
670
|
|
689
671
|
class HasManyReflection < AssociationReflection # :nodoc:
|
@@ -737,30 +719,25 @@ module ActiveRecord
|
|
737
719
|
end
|
738
720
|
end
|
739
721
|
|
740
|
-
def
|
741
|
-
|
722
|
+
def join_primary_key(klass = nil)
|
723
|
+
polymorphic? ? association_primary_key(klass) : association_primary_key
|
724
|
+
end
|
725
|
+
|
726
|
+
def join_foreign_key
|
727
|
+
foreign_key
|
742
728
|
end
|
743
729
|
|
744
730
|
private
|
731
|
+
def can_find_inverse_of_automatically?(_)
|
732
|
+
!polymorphic? && super
|
733
|
+
end
|
745
734
|
|
746
735
|
def calculate_constructable(macro, options)
|
747
736
|
!polymorphic?
|
748
737
|
end
|
749
|
-
|
750
|
-
def join_fk
|
751
|
-
foreign_key
|
752
|
-
end
|
753
|
-
|
754
|
-
def join_pk(klass)
|
755
|
-
polymorphic? ? association_primary_key(klass) : association_primary_key
|
756
|
-
end
|
757
738
|
end
|
758
739
|
|
759
740
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
760
|
-
def initialize(name, scope, options, active_record)
|
761
|
-
super
|
762
|
-
end
|
763
|
-
|
764
741
|
def macro; :has_and_belongs_to_many; end
|
765
742
|
|
766
743
|
def collection?
|
@@ -771,8 +748,7 @@ module ActiveRecord
|
|
771
748
|
# Holds all the metadata about a :through association as it was specified
|
772
749
|
# in the Active Record class.
|
773
750
|
class ThroughReflection < AbstractReflection #:nodoc:
|
774
|
-
|
775
|
-
delegate :foreign_key, :foreign_type, :association_foreign_key,
|
751
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
|
776
752
|
:active_record_primary_key, :type, :get_join_keys, to: :source_reflection
|
777
753
|
|
778
754
|
def initialize(delegate_reflection)
|
@@ -863,10 +839,6 @@ module ActiveRecord
|
|
863
839
|
source_reflection.join_scopes(table, predicate_builder) + super
|
864
840
|
end
|
865
841
|
|
866
|
-
def source_type_scope
|
867
|
-
through_reflection.klass.where(foreign_type => options[:source_type])
|
868
|
-
end
|
869
|
-
|
870
842
|
def has_scope?
|
871
843
|
scope || options[:source_type] ||
|
872
844
|
source_reflection.has_scope? ||
|
@@ -887,10 +859,6 @@ module ActiveRecord
|
|
887
859
|
actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
|
888
860
|
end
|
889
861
|
|
890
|
-
def association_primary_key_type
|
891
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
892
|
-
end
|
893
|
-
|
894
862
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
895
863
|
#
|
896
864
|
# class Post < ActiveRecord::Base
|
@@ -935,10 +903,6 @@ module ActiveRecord
|
|
935
903
|
through_reflection.options
|
936
904
|
end
|
937
905
|
|
938
|
-
def join_id_for(owner) # :nodoc:
|
939
|
-
source_reflection.join_id_for(owner)
|
940
|
-
end
|
941
|
-
|
942
906
|
def check_validity!
|
943
907
|
if through_reflection.nil?
|
944
908
|
raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
|
@@ -997,23 +961,23 @@ module ActiveRecord
|
|
997
961
|
collect_join_reflections(seed + [self])
|
998
962
|
end
|
999
963
|
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
else
|
1005
|
-
through_reflection.add_as_through a
|
1006
|
-
end
|
1007
|
-
end
|
1008
|
-
|
1009
|
-
private
|
964
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
965
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
966
|
+
protected
|
967
|
+
attr_reader :delegate_reflection
|
1010
968
|
|
1011
969
|
def actual_source_reflection # FIXME: this is a horrible name
|
1012
|
-
source_reflection.
|
970
|
+
source_reflection.actual_source_reflection
|
1013
971
|
end
|
1014
972
|
|
1015
|
-
|
1016
|
-
|
973
|
+
private
|
974
|
+
def collect_join_reflections(seed)
|
975
|
+
a = source_reflection.add_as_source seed
|
976
|
+
if options[:source_type]
|
977
|
+
through_reflection.add_as_polymorphic_through self, a
|
978
|
+
else
|
979
|
+
through_reflection.add_as_through a
|
980
|
+
end
|
1017
981
|
end
|
1018
982
|
|
1019
983
|
def inverse_name; delegate_reflection.send(:inverse_name); end
|
@@ -1030,66 +994,32 @@ module ActiveRecord
|
|
1030
994
|
end
|
1031
995
|
|
1032
996
|
class PolymorphicReflection < AbstractReflection # :nodoc:
|
997
|
+
delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
|
998
|
+
|
1033
999
|
def initialize(reflection, previous_reflection)
|
1034
1000
|
@reflection = reflection
|
1035
1001
|
@previous_reflection = previous_reflection
|
1036
1002
|
end
|
1037
1003
|
|
1038
|
-
def scopes
|
1039
|
-
scopes = @previous_reflection.scopes
|
1040
|
-
if @previous_reflection.options[:source_type]
|
1041
|
-
scopes + [@previous_reflection.source_type_scope]
|
1042
|
-
else
|
1043
|
-
scopes
|
1044
|
-
end
|
1045
|
-
end
|
1046
|
-
|
1047
1004
|
def join_scopes(table, predicate_builder) # :nodoc:
|
1048
1005
|
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1049
|
-
|
1050
|
-
scopes + [@previous_reflection.source_type_scope]
|
1051
|
-
else
|
1052
|
-
scopes
|
1053
|
-
end
|
1054
|
-
end
|
1055
|
-
|
1056
|
-
def klass
|
1057
|
-
@reflection.klass
|
1058
|
-
end
|
1059
|
-
|
1060
|
-
def scope
|
1061
|
-
@reflection.scope
|
1062
|
-
end
|
1063
|
-
|
1064
|
-
def table_name
|
1065
|
-
@reflection.table_name
|
1066
|
-
end
|
1067
|
-
|
1068
|
-
def plural_name
|
1069
|
-
@reflection.plural_name
|
1070
|
-
end
|
1071
|
-
|
1072
|
-
def type
|
1073
|
-
@reflection.type
|
1006
|
+
scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
|
1074
1007
|
end
|
1075
1008
|
|
1076
1009
|
def constraints
|
1077
|
-
@reflection.constraints + [
|
1078
|
-
end
|
1079
|
-
|
1080
|
-
def source_type_info
|
1081
|
-
type = @previous_reflection.foreign_type
|
1082
|
-
source_type = @previous_reflection.options[:source_type]
|
1083
|
-
lambda { |object| where(type => source_type) }
|
1010
|
+
@reflection.constraints + [source_type_scope]
|
1084
1011
|
end
|
1085
1012
|
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1013
|
+
private
|
1014
|
+
def source_type_scope
|
1015
|
+
type = @previous_reflection.foreign_type
|
1016
|
+
source_type = @previous_reflection.options[:source_type]
|
1017
|
+
lambda { |object| where(type => source_type) }
|
1018
|
+
end
|
1089
1019
|
end
|
1090
1020
|
|
1091
|
-
class RuntimeReflection <
|
1092
|
-
|
1021
|
+
class RuntimeReflection < AbstractReflection # :nodoc:
|
1022
|
+
delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
|
1093
1023
|
|
1094
1024
|
def initialize(reflection, association)
|
1095
1025
|
@reflection = reflection
|
@@ -1100,24 +1030,8 @@ module ActiveRecord
|
|
1100
1030
|
@association.klass
|
1101
1031
|
end
|
1102
1032
|
|
1103
|
-
def
|
1104
|
-
klass.
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
def constraints
|
1108
|
-
@reflection.constraints
|
1109
|
-
end
|
1110
|
-
|
1111
|
-
def source_type_info
|
1112
|
-
@reflection.source_type_info
|
1113
|
-
end
|
1114
|
-
|
1115
|
-
def alias_candidate(name)
|
1116
|
-
"#{plural_name}_#{name}_join"
|
1117
|
-
end
|
1118
|
-
|
1119
|
-
def alias_name
|
1120
|
-
Arel::Table.new(table_name, type_caster: klass.type_caster)
|
1033
|
+
def aliased_table
|
1034
|
+
@aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
|
1121
1035
|
end
|
1122
1036
|
|
1123
1037
|
def all_includes; yield; end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_record/relation/batches/batch_enumerator"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -45,7 +47,12 @@ module ActiveRecord
|
|
45
47
|
# handle from 10000 and beyond by setting the +:start+ and +:finish+
|
46
48
|
# option on each worker.
|
47
49
|
#
|
48
|
-
# #
|
50
|
+
# # In worker 1, let's process until 9999 records.
|
51
|
+
# Person.find_each(finish: 9_999) do |person|
|
52
|
+
# person.party_all_night!
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# # In worker 2, let's process from record 10_000 and onwards.
|
49
56
|
# Person.find_each(start: 10_000) do |person|
|
50
57
|
# person.party_all_night!
|
51
58
|
# end
|
@@ -209,6 +216,7 @@ module ActiveRecord
|
|
209
216
|
|
210
217
|
relation = relation.reorder(batch_order).limit(batch_limit)
|
211
218
|
relation = apply_limits(relation, start, finish)
|
219
|
+
relation.skip_query_cache! # Retaining the results in the query cache would undermine the point of batching
|
212
220
|
batch_relation = relation
|
213
221
|
|
214
222
|
loop do
|
@@ -243,20 +251,27 @@ module ActiveRecord
|
|
243
251
|
end
|
244
252
|
end
|
245
253
|
|
246
|
-
|
254
|
+
attr = Relation::QueryAttribute.new(primary_key, primary_key_offset, klass.type_for_attribute(primary_key))
|
255
|
+
batch_relation = relation.where(arel_attribute(primary_key).gt(Arel::Nodes::BindParam.new(attr)))
|
247
256
|
end
|
248
257
|
end
|
249
258
|
|
250
259
|
private
|
251
260
|
|
252
261
|
def apply_limits(relation, start, finish)
|
253
|
-
|
254
|
-
|
262
|
+
if start
|
263
|
+
attr = Relation::QueryAttribute.new(primary_key, start, klass.type_for_attribute(primary_key))
|
264
|
+
relation = relation.where(arel_attribute(primary_key).gteq(Arel::Nodes::BindParam.new(attr)))
|
265
|
+
end
|
266
|
+
if finish
|
267
|
+
attr = Relation::QueryAttribute.new(primary_key, finish, klass.type_for_attribute(primary_key))
|
268
|
+
relation = relation.where(arel_attribute(primary_key).lteq(Arel::Nodes::BindParam.new(attr)))
|
269
|
+
end
|
255
270
|
relation
|
256
271
|
end
|
257
272
|
|
258
273
|
def batch_order
|
259
|
-
|
274
|
+
arel_attribute(primary_key).asc
|
260
275
|
end
|
261
276
|
|
262
277
|
def act_on_ignored_order(error_on_ignore)
|