activerecord 5.1.7 → 5.2.0
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 +372 -765
- 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 +4 -2
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +16 -27
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +20 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +4 -5
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- 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 +43 -35
- data/lib/active_record/associations/collection_proxy.rb +12 -15
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +3 -1
- data/lib/active_record/associations/has_many_through_association.rb +7 -18
- data/lib/active_record/associations/has_one_association.rb +4 -1
- data/lib/active_record/associations/has_one_through_association.rb +8 -7
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/join_dependency.rb +23 -43
- 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 +17 -37
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +25 -10
- data/lib/active_record/associations.rb +31 -54
- 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 +25 -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 +8 -2
- 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 +8 -11
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +8 -10
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +111 -38
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +157 -29
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -32
- 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 +57 -2
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -78
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +111 -183
- 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 +2 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -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 +3 -11
- 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 +3 -1
- 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 -6
- 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 +14 -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 +246 -110
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +58 -82
- 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 +18 -1
- 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 +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +80 -90
- 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 +39 -60
- data/lib/active_record/counter_cache.rb +15 -12
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +17 -13
- data/lib/active_record/errors.rb +54 -21
- 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 +4 -2
- 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 +40 -2
- 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 +166 -16
- data/lib/active_record/query_cache.rb +11 -6
- data/lib/active_record/querying.rb +3 -1
- data/lib/active_record/railtie.rb +61 -3
- 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 +110 -192
- 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 +30 -8
- data/lib/active_record/relation/delegation.rb +15 -27
- data/lib/active_record/relation/finder_methods.rb +75 -78
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +51 -20
- 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 +53 -78
- data/lib/active_record/relation/query_attribute.rb +26 -2
- data/lib/active_record/relation/query_methods.rb +89 -88
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -1
- 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 +95 -208
- 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 +6 -7
- data/lib/active_record/scoping/named.rb +21 -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 +22 -12
- 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 +26 -15
- 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 +5 -12
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- 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 -4
- 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 +24 -36
- 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,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ReadonlyAttributes
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
|
5
7
|
included do
|
6
|
-
class_attribute :_attr_readonly, instance_accessor: false
|
7
|
-
self._attr_readonly = []
|
8
|
+
class_attribute :_attr_readonly, instance_accessor: false, default: []
|
8
9
|
end
|
9
10
|
|
10
11
|
module ClassMethods
|
@@ -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,34 @@ module ActiveRecord
|
|
183
174
|
scope ? [scope] : []
|
184
175
|
end
|
185
176
|
|
186
|
-
def
|
187
|
-
|
177
|
+
def build_join_constraint(table, foreign_table)
|
178
|
+
key = join_keys.key
|
179
|
+
foreign_key = join_keys.foreign_key
|
180
|
+
|
181
|
+
constraint = table[key].eq(foreign_table[foreign_key])
|
182
|
+
|
183
|
+
if klass.finder_needs_type_condition?
|
184
|
+
table.create_and([constraint, klass.send(:type_condition, table)])
|
185
|
+
else
|
186
|
+
constraint
|
187
|
+
end
|
188
188
|
end
|
189
|
-
deprecate :scope_chain
|
190
189
|
|
191
|
-
def join_scope(table)
|
190
|
+
def join_scope(table, foreign_klass)
|
192
191
|
predicate_builder = predicate_builder(table)
|
193
192
|
scope_chain_items = join_scopes(table, predicate_builder)
|
194
193
|
klass_scope = klass_join_scope(table, predicate_builder)
|
195
194
|
|
196
|
-
|
195
|
+
if type
|
196
|
+
klass_scope.where!(type => foreign_klass.polymorphic_name)
|
197
|
+
end
|
198
|
+
|
199
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
197
200
|
end
|
198
201
|
|
199
202
|
def join_scopes(table, predicate_builder) # :nodoc:
|
200
203
|
if scope
|
201
|
-
[build_scope(table, predicate_builder)
|
204
|
+
[scope_for(build_scope(table, predicate_builder))]
|
202
205
|
else
|
203
206
|
[]
|
204
207
|
end
|
@@ -210,7 +213,7 @@ module ActiveRecord
|
|
210
213
|
end
|
211
214
|
|
212
215
|
def constraints
|
213
|
-
chain.
|
216
|
+
chain.flat_map(&:scopes)
|
214
217
|
end
|
215
218
|
|
216
219
|
def counter_cache_column
|
@@ -284,24 +287,37 @@ module ActiveRecord
|
|
284
287
|
end
|
285
288
|
|
286
289
|
def get_join_keys(association_klass)
|
287
|
-
JoinKeys.new(
|
290
|
+
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
288
291
|
end
|
289
292
|
|
290
293
|
def build_scope(table, predicate_builder = predicate_builder(table))
|
291
|
-
Relation.create(
|
294
|
+
Relation.create(
|
295
|
+
klass,
|
296
|
+
table: table,
|
297
|
+
predicate_builder: predicate_builder
|
298
|
+
)
|
299
|
+
end
|
300
|
+
|
301
|
+
def join_primary_key(*)
|
302
|
+
foreign_key
|
303
|
+
end
|
304
|
+
|
305
|
+
def join_foreign_key
|
306
|
+
active_record_primary_key
|
292
307
|
end
|
293
308
|
|
309
|
+
protected
|
310
|
+
def actual_source_reflection # FIXME: this is a horrible name
|
311
|
+
self
|
312
|
+
end
|
313
|
+
|
294
314
|
private
|
295
315
|
def predicate_builder(table)
|
296
316
|
PredicateBuilder.new(TableMetadata.new(klass, table))
|
297
317
|
end
|
298
318
|
|
299
|
-
def
|
300
|
-
|
301
|
-
end
|
302
|
-
|
303
|
-
def join_fk
|
304
|
-
active_record_primary_key
|
319
|
+
def primary_key(klass)
|
320
|
+
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
305
321
|
end
|
306
322
|
end
|
307
323
|
|
@@ -348,6 +364,17 @@ module ActiveRecord
|
|
348
364
|
#
|
349
365
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
|
350
366
|
# <tt>has_many :clients</tt> returns the Client class
|
367
|
+
#
|
368
|
+
# class Company < ActiveRecord::Base
|
369
|
+
# has_many :clients
|
370
|
+
# end
|
371
|
+
#
|
372
|
+
# Company.reflect_on_association(:clients).klass
|
373
|
+
# # => Client
|
374
|
+
#
|
375
|
+
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
376
|
+
# a new association object. Use +build_association+ or +create_association+
|
377
|
+
# instead. This allows plugins to hook into association object creation.
|
351
378
|
def klass
|
352
379
|
@klass ||= compute_class(class_name)
|
353
380
|
end
|
@@ -366,8 +393,8 @@ module ActiveRecord
|
|
366
393
|
active_record == other_aggregation.active_record
|
367
394
|
end
|
368
395
|
|
369
|
-
def scope_for(
|
370
|
-
|
396
|
+
def scope_for(relation, owner = nil)
|
397
|
+
relation.instance_exec(owner, &scope) || relation
|
371
398
|
end
|
372
399
|
|
373
400
|
private
|
@@ -388,23 +415,10 @@ module ActiveRecord
|
|
388
415
|
# Holds all the metadata about an association as it was specified in the
|
389
416
|
# Active Record class.
|
390
417
|
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
418
|
def compute_class(name)
|
419
|
+
if polymorphic?
|
420
|
+
raise ArgumentError, "Polymorphic association does not support to compute class."
|
421
|
+
end
|
408
422
|
active_record.send(:compute_type, name)
|
409
423
|
end
|
410
424
|
|
@@ -414,31 +428,21 @@ module ActiveRecord
|
|
414
428
|
def initialize(name, scope, options, active_record)
|
415
429
|
super
|
416
430
|
@type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
|
417
|
-
@foreign_type = options[:foreign_type] || "#{name}_type"
|
431
|
+
@foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
|
418
432
|
@constructable = calculate_constructable(macro, options)
|
419
|
-
@association_scope_cache =
|
420
|
-
@scope_lock = Mutex.new
|
433
|
+
@association_scope_cache = Concurrent::Map.new
|
421
434
|
|
422
435
|
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
|
436
|
+
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
431
437
|
end
|
432
438
|
end
|
433
439
|
|
434
|
-
def association_scope_cache(conn, owner)
|
440
|
+
def association_scope_cache(conn, owner, &block)
|
435
441
|
key = conn.prepared_statements
|
436
442
|
if polymorphic?
|
437
443
|
key = [key, owner._read_attribute(@foreign_type)]
|
438
444
|
end
|
439
|
-
@association_scope_cache
|
440
|
-
@association_scope_cache[key] ||= yield
|
441
|
-
}
|
445
|
+
@association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
|
442
446
|
end
|
443
447
|
|
444
448
|
def constructable? # :nodoc:
|
@@ -462,10 +466,6 @@ module ActiveRecord
|
|
462
466
|
options[:primary_key] || primary_key(klass || self.klass)
|
463
467
|
end
|
464
468
|
|
465
|
-
def association_primary_key_type
|
466
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
467
|
-
end
|
468
|
-
|
469
469
|
def active_record_primary_key
|
470
470
|
@active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
|
471
471
|
end
|
@@ -488,7 +488,7 @@ module ActiveRecord
|
|
488
488
|
alias :check_eager_loadable! :check_preloadable!
|
489
489
|
|
490
490
|
def join_id_for(owner) # :nodoc:
|
491
|
-
owner[
|
491
|
+
owner[join_foreign_key]
|
492
492
|
end
|
493
493
|
|
494
494
|
def through_reflection
|
@@ -571,7 +571,7 @@ module ActiveRecord
|
|
571
571
|
end
|
572
572
|
|
573
573
|
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
574
|
-
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:
|
574
|
+
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
|
575
575
|
|
576
576
|
def add_as_source(seed)
|
577
577
|
seed
|
@@ -589,12 +589,6 @@ module ActiveRecord
|
|
589
589
|
Array(options[:extend])
|
590
590
|
end
|
591
591
|
|
592
|
-
protected
|
593
|
-
|
594
|
-
def actual_source_reflection # FIXME: this is a horrible name
|
595
|
-
self
|
596
|
-
end
|
597
|
-
|
598
592
|
private
|
599
593
|
|
600
594
|
def calculate_constructable(macro, options)
|
@@ -635,12 +629,9 @@ module ActiveRecord
|
|
635
629
|
# +automatic_inverse_of+ method is a valid reflection. We must
|
636
630
|
# make sure that the reflection's active_record name matches up
|
637
631
|
# 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
632
|
def valid_inverse_reflection?(reflection)
|
642
633
|
reflection &&
|
643
|
-
klass
|
634
|
+
klass <= reflection.active_record &&
|
644
635
|
can_find_inverse_of_automatically?(reflection)
|
645
636
|
end
|
646
637
|
|
@@ -648,9 +639,8 @@ module ActiveRecord
|
|
648
639
|
# us from being able to guess the inverse automatically. First, the
|
649
640
|
# <tt>inverse_of</tt> option cannot be set to false. Second, we must
|
650
641
|
# 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.
|
642
|
+
# Third, we must not have options such as <tt>:foreign_key</tt>
|
643
|
+
# which prevent us from correctly guessing the inverse association.
|
654
644
|
#
|
655
645
|
# Anything with a scope can additionally ruin our attempt at finding an
|
656
646
|
# inverse, so we exclude reflections with scopes.
|
@@ -680,10 +670,6 @@ module ActiveRecord
|
|
680
670
|
def derive_join_table
|
681
671
|
ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
|
682
672
|
end
|
683
|
-
|
684
|
-
def primary_key(klass)
|
685
|
-
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
686
|
-
end
|
687
673
|
end
|
688
674
|
|
689
675
|
class HasManyReflection < AssociationReflection # :nodoc:
|
@@ -737,30 +723,25 @@ module ActiveRecord
|
|
737
723
|
end
|
738
724
|
end
|
739
725
|
|
740
|
-
def
|
741
|
-
|
726
|
+
def join_primary_key(klass = nil)
|
727
|
+
polymorphic? ? association_primary_key(klass) : association_primary_key
|
728
|
+
end
|
729
|
+
|
730
|
+
def join_foreign_key
|
731
|
+
foreign_key
|
742
732
|
end
|
743
733
|
|
744
734
|
private
|
735
|
+
def can_find_inverse_of_automatically?(_)
|
736
|
+
!polymorphic? && super
|
737
|
+
end
|
745
738
|
|
746
739
|
def calculate_constructable(macro, options)
|
747
740
|
!polymorphic?
|
748
741
|
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
742
|
end
|
758
743
|
|
759
744
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
760
|
-
def initialize(name, scope, options, active_record)
|
761
|
-
super
|
762
|
-
end
|
763
|
-
|
764
745
|
def macro; :has_and_belongs_to_many; end
|
765
746
|
|
766
747
|
def collection?
|
@@ -771,8 +752,7 @@ module ActiveRecord
|
|
771
752
|
# Holds all the metadata about a :through association as it was specified
|
772
753
|
# in the Active Record class.
|
773
754
|
class ThroughReflection < AbstractReflection #:nodoc:
|
774
|
-
|
775
|
-
delegate :foreign_key, :foreign_type, :association_foreign_key,
|
755
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
|
776
756
|
:active_record_primary_key, :type, :get_join_keys, to: :source_reflection
|
777
757
|
|
778
758
|
def initialize(delegate_reflection)
|
@@ -863,10 +843,6 @@ module ActiveRecord
|
|
863
843
|
source_reflection.join_scopes(table, predicate_builder) + super
|
864
844
|
end
|
865
845
|
|
866
|
-
def source_type_scope
|
867
|
-
through_reflection.klass.where(foreign_type => options[:source_type])
|
868
|
-
end
|
869
|
-
|
870
846
|
def has_scope?
|
871
847
|
scope || options[:source_type] ||
|
872
848
|
source_reflection.has_scope? ||
|
@@ -887,10 +863,6 @@ module ActiveRecord
|
|
887
863
|
actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
|
888
864
|
end
|
889
865
|
|
890
|
-
def association_primary_key_type
|
891
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
892
|
-
end
|
893
|
-
|
894
866
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
895
867
|
#
|
896
868
|
# class Post < ActiveRecord::Base
|
@@ -935,10 +907,6 @@ module ActiveRecord
|
|
935
907
|
through_reflection.options
|
936
908
|
end
|
937
909
|
|
938
|
-
def join_id_for(owner) # :nodoc:
|
939
|
-
source_reflection.join_id_for(owner)
|
940
|
-
end
|
941
|
-
|
942
910
|
def check_validity!
|
943
911
|
if through_reflection.nil?
|
944
912
|
raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
|
@@ -997,23 +965,23 @@ module ActiveRecord
|
|
997
965
|
collect_join_reflections(seed + [self])
|
998
966
|
end
|
999
967
|
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
else
|
1005
|
-
through_reflection.add_as_through a
|
1006
|
-
end
|
1007
|
-
end
|
1008
|
-
|
1009
|
-
private
|
968
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
969
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
970
|
+
protected
|
971
|
+
attr_reader :delegate_reflection
|
1010
972
|
|
1011
973
|
def actual_source_reflection # FIXME: this is a horrible name
|
1012
|
-
source_reflection.
|
974
|
+
source_reflection.actual_source_reflection
|
1013
975
|
end
|
1014
976
|
|
1015
|
-
|
1016
|
-
|
977
|
+
private
|
978
|
+
def collect_join_reflections(seed)
|
979
|
+
a = source_reflection.add_as_source seed
|
980
|
+
if options[:source_type]
|
981
|
+
through_reflection.add_as_polymorphic_through self, a
|
982
|
+
else
|
983
|
+
through_reflection.add_as_through a
|
984
|
+
end
|
1017
985
|
end
|
1018
986
|
|
1019
987
|
def inverse_name; delegate_reflection.send(:inverse_name); end
|
@@ -1030,66 +998,32 @@ module ActiveRecord
|
|
1030
998
|
end
|
1031
999
|
|
1032
1000
|
class PolymorphicReflection < AbstractReflection # :nodoc:
|
1001
|
+
delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
|
1002
|
+
|
1033
1003
|
def initialize(reflection, previous_reflection)
|
1034
1004
|
@reflection = reflection
|
1035
1005
|
@previous_reflection = previous_reflection
|
1036
1006
|
end
|
1037
1007
|
|
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
1008
|
def join_scopes(table, predicate_builder) # :nodoc:
|
1048
1009
|
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
|
1010
|
+
scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
|
1074
1011
|
end
|
1075
1012
|
|
1076
1013
|
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) }
|
1014
|
+
@reflection.constraints + [source_type_scope]
|
1084
1015
|
end
|
1085
1016
|
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1017
|
+
private
|
1018
|
+
def source_type_scope
|
1019
|
+
type = @previous_reflection.foreign_type
|
1020
|
+
source_type = @previous_reflection.options[:source_type]
|
1021
|
+
lambda { |object| where(type => source_type) }
|
1022
|
+
end
|
1089
1023
|
end
|
1090
1024
|
|
1091
|
-
class RuntimeReflection <
|
1092
|
-
|
1025
|
+
class RuntimeReflection < AbstractReflection # :nodoc:
|
1026
|
+
delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
|
1093
1027
|
|
1094
1028
|
def initialize(reflection, association)
|
1095
1029
|
@reflection = reflection
|
@@ -1100,24 +1034,8 @@ module ActiveRecord
|
|
1100
1034
|
@association.klass
|
1101
1035
|
end
|
1102
1036
|
|
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)
|
1037
|
+
def aliased_table
|
1038
|
+
@aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
|
1121
1039
|
end
|
1122
1040
|
|
1123
1041
|
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)
|