activerecord 5.1.0 → 5.2.0.rc1
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 +5 -5
- data/CHANGELOG.md +410 -530
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- 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 +23 -32
- data/lib/active_record/associations/association.rb +20 -21
- data/lib/active_record/associations/association_scope.rb +49 -49
- data/lib/active_record/associations/belongs_to_association.rb +12 -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 +10 -6
- 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 +50 -41
- data/lib/active_record/associations/collection_proxy.rb +22 -39
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +12 -18
- data/lib/active_record/associations/has_one_association.rb +5 -1
- data/lib/active_record/associations/has_one_through_association.rb +8 -7
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -64
- 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 +27 -44
- data/lib/active_record/associations/preloader/association.rb +53 -92
- data/lib/active_record/associations/preloader/through_association.rb +72 -73
- 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 +26 -11
- data/lib/active_record/associations.rb +68 -76
- data/lib/active_record/attribute_assignment.rb +2 -0
- 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 +24 -214
- data/lib/active_record/attribute_methods/primary_key.rb +10 -13
- 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 +22 -19
- data/lib/active_record/attribute_methods.rb +48 -12
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +8 -11
- 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 +2 -0
- data/lib/active_record/collection_cache_key.rb +14 -10
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +58 -3
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
- data/lib/active_record/connection_adapters/column.rb +4 -2
- 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 -17
- 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 -23
- 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 +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
- 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_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- 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 -11
- 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 -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 +2 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
- 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 +269 -126
- 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 +64 -85
- 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 -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 +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +92 -95
- 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 +3 -2
- 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 +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 +4 -2
- data/lib/active_record/inheritance.rb +9 -9
- 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 +8 -6
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +46 -4
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +74 -22
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/migration.rb +181 -137
- data/lib/active_record/model_schema.rb +73 -58
- 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 +153 -18
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +4 -2
- 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 +47 -37
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +131 -204
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/batches.rb +32 -17
- data/lib/active_record/relation/calculations.rb +58 -20
- data/lib/active_record/relation/delegation.rb +10 -29
- data/lib/active_record/relation/finder_methods.rb +74 -85
- 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 +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- 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 +9 -2
- data/lib/active_record/relation/query_methods.rb +101 -95
- 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 -67
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/relation.rb +99 -202
- 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 +10 -7
- data/lib/active_record/scoping/named.rb +38 -12
- data/lib/active_record/scoping.rb +12 -10
- 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 +37 -25
- data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +5 -5
- 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 -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 +25 -37
- 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 -113
- data/lib/active_record/attribute_set/builder.rb +0 -124
- 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 -33
@@ -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)
|
@@ -35,7 +34,8 @@ module ActiveRecord
|
|
35
34
|
|
36
35
|
def self.add_reflection(ar, name, reflection)
|
37
36
|
ar.clear_reflections_cache
|
38
|
-
|
37
|
+
name = name.to_s
|
38
|
+
ar._reflections = ar._reflections.except(name).merge!(name => reflection)
|
39
39
|
end
|
40
40
|
|
41
41
|
def self.add_aggregate_reflection(ar, name, reflection)
|
@@ -138,7 +138,7 @@ module ActiveRecord
|
|
138
138
|
# HasAndBelongsToManyReflection
|
139
139
|
# ThroughReflection
|
140
140
|
# PolymorphicReflection
|
141
|
-
#
|
141
|
+
# RuntimeReflection
|
142
142
|
class AbstractReflection # :nodoc:
|
143
143
|
def through_reflection?
|
144
144
|
false
|
@@ -154,14 +154,6 @@ module ActiveRecord
|
|
154
154
|
klass.new(attributes, &block)
|
155
155
|
end
|
156
156
|
|
157
|
-
def quoted_table_name
|
158
|
-
klass.quoted_table_name
|
159
|
-
end
|
160
|
-
|
161
|
-
def primary_key_type
|
162
|
-
klass.type_for_attribute(klass.primary_key)
|
163
|
-
end
|
164
|
-
|
165
157
|
# Returns the class name for the macro.
|
166
158
|
#
|
167
159
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
|
@@ -173,7 +165,7 @@ module ActiveRecord
|
|
173
165
|
JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
|
174
166
|
|
175
167
|
def join_keys
|
176
|
-
get_join_keys
|
168
|
+
@join_keys ||= get_join_keys(klass)
|
177
169
|
end
|
178
170
|
|
179
171
|
# Returns a list of scopes that should be applied for this Reflection
|
@@ -182,37 +174,46 @@ module ActiveRecord
|
|
182
174
|
scope ? [scope] : []
|
183
175
|
end
|
184
176
|
|
185
|
-
def
|
186
|
-
|
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
|
+
end
|
189
|
+
|
190
|
+
def join_scope(table, foreign_klass)
|
191
|
+
predicate_builder = predicate_builder(table)
|
192
|
+
scope_chain_items = join_scopes(table, predicate_builder)
|
193
|
+
klass_scope = klass_join_scope(table, predicate_builder)
|
194
|
+
|
195
|
+
if type
|
196
|
+
klass_scope.where!(type => foreign_klass.base_class.sti_name)
|
197
|
+
end
|
198
|
+
|
199
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
187
200
|
end
|
188
|
-
deprecate :scope_chain
|
189
201
|
|
190
202
|
def join_scopes(table, predicate_builder) # :nodoc:
|
191
203
|
if scope
|
192
|
-
[
|
193
|
-
.instance_exec(&scope)]
|
204
|
+
[scope_for(build_scope(table, predicate_builder))]
|
194
205
|
else
|
195
206
|
[]
|
196
207
|
end
|
197
208
|
end
|
198
209
|
|
199
210
|
def klass_join_scope(table, predicate_builder) # :nodoc:
|
200
|
-
|
201
|
-
|
202
|
-
scope.joins_values = []
|
203
|
-
}
|
204
|
-
else
|
205
|
-
relation = ActiveRecord::Relation.create(
|
206
|
-
klass,
|
207
|
-
table,
|
208
|
-
predicate_builder,
|
209
|
-
)
|
210
|
-
klass.send(:build_default_scope, relation)
|
211
|
-
end
|
211
|
+
relation = build_scope(table, predicate_builder)
|
212
|
+
klass.scope_for_association(relation)
|
212
213
|
end
|
213
214
|
|
214
215
|
def constraints
|
215
|
-
chain.
|
216
|
+
chain.flat_map(&:scopes)
|
216
217
|
end
|
217
218
|
|
218
219
|
def counter_cache_column
|
@@ -286,17 +287,37 @@ module ActiveRecord
|
|
286
287
|
end
|
287
288
|
|
288
289
|
def get_join_keys(association_klass)
|
289
|
-
JoinKeys.new(
|
290
|
+
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
290
291
|
end
|
291
292
|
|
292
|
-
|
293
|
+
def build_scope(table, predicate_builder = predicate_builder(table))
|
294
|
+
Relation.create(
|
295
|
+
klass,
|
296
|
+
table: table,
|
297
|
+
predicate_builder: predicate_builder
|
298
|
+
)
|
299
|
+
end
|
293
300
|
|
294
|
-
|
295
|
-
|
301
|
+
def join_primary_key(*)
|
302
|
+
foreign_key
|
303
|
+
end
|
304
|
+
|
305
|
+
def join_foreign_key
|
306
|
+
active_record_primary_key
|
307
|
+
end
|
308
|
+
|
309
|
+
protected
|
310
|
+
def actual_source_reflection # FIXME: this is a horrible name
|
311
|
+
self
|
296
312
|
end
|
297
313
|
|
298
|
-
|
299
|
-
|
314
|
+
private
|
315
|
+
def predicate_builder(table)
|
316
|
+
PredicateBuilder.new(TableMetadata.new(klass, table))
|
317
|
+
end
|
318
|
+
|
319
|
+
def primary_key(klass)
|
320
|
+
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
300
321
|
end
|
301
322
|
end
|
302
323
|
|
@@ -343,6 +364,17 @@ module ActiveRecord
|
|
343
364
|
#
|
344
365
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
|
345
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.
|
346
378
|
def klass
|
347
379
|
@klass ||= compute_class(class_name)
|
348
380
|
end
|
@@ -361,8 +393,8 @@ module ActiveRecord
|
|
361
393
|
active_record == other_aggregation.active_record
|
362
394
|
end
|
363
395
|
|
364
|
-
def scope_for(
|
365
|
-
|
396
|
+
def scope_for(relation, owner = nil)
|
397
|
+
relation.instance_exec(owner, &scope) || relation
|
366
398
|
end
|
367
399
|
|
368
400
|
private
|
@@ -383,22 +415,6 @@ module ActiveRecord
|
|
383
415
|
# Holds all the metadata about an association as it was specified in the
|
384
416
|
# Active Record class.
|
385
417
|
class AssociationReflection < MacroReflection #:nodoc:
|
386
|
-
# Returns the target association's class.
|
387
|
-
#
|
388
|
-
# class Author < ActiveRecord::Base
|
389
|
-
# has_many :books
|
390
|
-
# end
|
391
|
-
#
|
392
|
-
# Author.reflect_on_association(:books).klass
|
393
|
-
# # => Book
|
394
|
-
#
|
395
|
-
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
396
|
-
# a new association object. Use +build_association+ or +create_association+
|
397
|
-
# instead. This allows plugins to hook into association object creation.
|
398
|
-
def klass
|
399
|
-
@klass ||= compute_class(class_name)
|
400
|
-
end
|
401
|
-
|
402
418
|
def compute_class(name)
|
403
419
|
active_record.send(:compute_type, name)
|
404
420
|
end
|
@@ -408,33 +424,22 @@ module ActiveRecord
|
|
408
424
|
|
409
425
|
def initialize(name, scope, options, active_record)
|
410
426
|
super
|
411
|
-
@automatic_inverse_of = nil
|
412
427
|
@type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
|
413
|
-
@foreign_type = options[:foreign_type] || "#{name}_type"
|
428
|
+
@foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
|
414
429
|
@constructable = calculate_constructable(macro, options)
|
415
|
-
@association_scope_cache =
|
416
|
-
@scope_lock = Mutex.new
|
430
|
+
@association_scope_cache = Concurrent::Map.new
|
417
431
|
|
418
432
|
if options[:class_name] && options[:class_name].class == Class
|
419
|
-
|
420
|
-
Passing a class to the `class_name` is deprecated and will raise
|
421
|
-
an ArgumentError in Rails 5.2. It eagerloads more classes than
|
422
|
-
necessary and potentially creates circular dependencies.
|
423
|
-
|
424
|
-
Please pass the class name as a string:
|
425
|
-
`#{macro} :#{name}, class_name: '#{options[:class_name]}'`
|
426
|
-
MSG
|
433
|
+
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
427
434
|
end
|
428
435
|
end
|
429
436
|
|
430
|
-
def association_scope_cache(conn, owner)
|
437
|
+
def association_scope_cache(conn, owner, &block)
|
431
438
|
key = conn.prepared_statements
|
432
439
|
if polymorphic?
|
433
440
|
key = [key, owner._read_attribute(@foreign_type)]
|
434
441
|
end
|
435
|
-
@association_scope_cache
|
436
|
-
@association_scope_cache[key] ||= yield
|
437
|
-
}
|
442
|
+
@association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
|
438
443
|
end
|
439
444
|
|
440
445
|
def constructable? # :nodoc:
|
@@ -458,10 +463,6 @@ module ActiveRecord
|
|
458
463
|
options[:primary_key] || primary_key(klass || self.klass)
|
459
464
|
end
|
460
465
|
|
461
|
-
def association_primary_key_type
|
462
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
463
|
-
end
|
464
|
-
|
465
466
|
def active_record_primary_key
|
466
467
|
@active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
|
467
468
|
end
|
@@ -484,7 +485,7 @@ module ActiveRecord
|
|
484
485
|
alias :check_eager_loadable! :check_preloadable!
|
485
486
|
|
486
487
|
def join_id_for(owner) # :nodoc:
|
487
|
-
owner[
|
488
|
+
owner[join_foreign_key]
|
488
489
|
end
|
489
490
|
|
490
491
|
def through_reflection
|
@@ -567,7 +568,7 @@ module ActiveRecord
|
|
567
568
|
end
|
568
569
|
|
569
570
|
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
570
|
-
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:
|
571
|
+
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
|
571
572
|
|
572
573
|
def add_as_source(seed)
|
573
574
|
seed
|
@@ -581,11 +582,9 @@ module ActiveRecord
|
|
581
582
|
seed + [self]
|
582
583
|
end
|
583
584
|
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
self
|
588
|
-
end
|
585
|
+
def extensions
|
586
|
+
Array(options[:extend])
|
587
|
+
end
|
589
588
|
|
590
589
|
private
|
591
590
|
|
@@ -597,12 +596,14 @@ module ActiveRecord
|
|
597
596
|
# If it cannot find a suitable inverse association name, it returns
|
598
597
|
# +nil+.
|
599
598
|
def inverse_name
|
600
|
-
|
601
|
-
@
|
599
|
+
unless defined?(@inverse_name)
|
600
|
+
@inverse_name = options.fetch(:inverse_of) { automatic_inverse_of }
|
602
601
|
end
|
602
|
+
|
603
|
+
@inverse_name
|
603
604
|
end
|
604
605
|
|
605
|
-
# returns either
|
606
|
+
# returns either +nil+ or the inverse association name that it finds.
|
606
607
|
def automatic_inverse_of
|
607
608
|
if can_find_inverse_of_automatically?(self)
|
608
609
|
inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
|
@@ -619,8 +620,6 @@ module ActiveRecord
|
|
619
620
|
return inverse_name
|
620
621
|
end
|
621
622
|
end
|
622
|
-
|
623
|
-
false
|
624
623
|
end
|
625
624
|
|
626
625
|
# Checks if the inverse reflection that is returned from the
|
@@ -632,7 +631,7 @@ module ActiveRecord
|
|
632
631
|
# from calling +klass+, +reflection+ will already be set to false.
|
633
632
|
def valid_inverse_reflection?(reflection)
|
634
633
|
reflection &&
|
635
|
-
klass
|
634
|
+
klass <= reflection.active_record &&
|
636
635
|
can_find_inverse_of_automatically?(reflection)
|
637
636
|
end
|
638
637
|
|
@@ -640,9 +639,8 @@ module ActiveRecord
|
|
640
639
|
# us from being able to guess the inverse automatically. First, the
|
641
640
|
# <tt>inverse_of</tt> option cannot be set to false. Second, we must
|
642
641
|
# have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
|
643
|
-
# Third, we must not have options such as <tt>:
|
644
|
-
#
|
645
|
-
# 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.
|
646
644
|
#
|
647
645
|
# Anything with a scope can additionally ruin our attempt at finding an
|
648
646
|
# inverse, so we exclude reflections with scopes.
|
@@ -672,10 +670,6 @@ module ActiveRecord
|
|
672
670
|
def derive_join_table
|
673
671
|
ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
|
674
672
|
end
|
675
|
-
|
676
|
-
def primary_key(klass)
|
677
|
-
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
678
|
-
end
|
679
673
|
end
|
680
674
|
|
681
675
|
class HasManyReflection < AssociationReflection # :nodoc:
|
@@ -690,6 +684,10 @@ module ActiveRecord
|
|
690
684
|
Associations::HasManyAssociation
|
691
685
|
end
|
692
686
|
end
|
687
|
+
|
688
|
+
def association_primary_key(klass = nil)
|
689
|
+
primary_key(klass || self.klass)
|
690
|
+
end
|
693
691
|
end
|
694
692
|
|
695
693
|
class HasOneReflection < AssociationReflection # :nodoc:
|
@@ -725,8 +723,12 @@ module ActiveRecord
|
|
725
723
|
end
|
726
724
|
end
|
727
725
|
|
728
|
-
def
|
729
|
-
|
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
|
730
732
|
end
|
731
733
|
|
732
734
|
private
|
@@ -734,21 +736,9 @@ module ActiveRecord
|
|
734
736
|
def calculate_constructable(macro, options)
|
735
737
|
!polymorphic?
|
736
738
|
end
|
737
|
-
|
738
|
-
def join_fk
|
739
|
-
foreign_key
|
740
|
-
end
|
741
|
-
|
742
|
-
def join_pk(klass)
|
743
|
-
polymorphic? ? association_primary_key(klass) : association_primary_key
|
744
|
-
end
|
745
739
|
end
|
746
740
|
|
747
741
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
748
|
-
def initialize(name, scope, options, active_record)
|
749
|
-
super
|
750
|
-
end
|
751
|
-
|
752
742
|
def macro; :has_and_belongs_to_many; end
|
753
743
|
|
754
744
|
def collection?
|
@@ -759,8 +749,7 @@ module ActiveRecord
|
|
759
749
|
# Holds all the metadata about a :through association as it was specified
|
760
750
|
# in the Active Record class.
|
761
751
|
class ThroughReflection < AbstractReflection #:nodoc:
|
762
|
-
|
763
|
-
delegate :foreign_key, :foreign_type, :association_foreign_key,
|
752
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
|
764
753
|
:active_record_primary_key, :type, :get_join_keys, to: :source_reflection
|
765
754
|
|
766
755
|
def initialize(delegate_reflection)
|
@@ -851,10 +840,6 @@ module ActiveRecord
|
|
851
840
|
source_reflection.join_scopes(table, predicate_builder) + super
|
852
841
|
end
|
853
842
|
|
854
|
-
def source_type_scope
|
855
|
-
through_reflection.klass.where(foreign_type => options[:source_type])
|
856
|
-
end
|
857
|
-
|
858
843
|
def has_scope?
|
859
844
|
scope || options[:source_type] ||
|
860
845
|
source_reflection.has_scope? ||
|
@@ -875,10 +860,6 @@ module ActiveRecord
|
|
875
860
|
actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
|
876
861
|
end
|
877
862
|
|
878
|
-
def association_primary_key_type
|
879
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
880
|
-
end
|
881
|
-
|
882
863
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
883
864
|
#
|
884
865
|
# class Post < ActiveRecord::Base
|
@@ -923,10 +904,6 @@ module ActiveRecord
|
|
923
904
|
through_reflection.options
|
924
905
|
end
|
925
906
|
|
926
|
-
def join_id_for(owner) # :nodoc:
|
927
|
-
source_reflection.join_id_for(owner)
|
928
|
-
end
|
929
|
-
|
930
907
|
def check_validity!
|
931
908
|
if through_reflection.nil?
|
932
909
|
raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
|
@@ -985,23 +962,23 @@ module ActiveRecord
|
|
985
962
|
collect_join_reflections(seed + [self])
|
986
963
|
end
|
987
964
|
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
else
|
993
|
-
through_reflection.add_as_through a
|
994
|
-
end
|
995
|
-
end
|
996
|
-
|
997
|
-
private
|
965
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
966
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
967
|
+
protected
|
968
|
+
attr_reader :delegate_reflection
|
998
969
|
|
999
970
|
def actual_source_reflection # FIXME: this is a horrible name
|
1000
|
-
source_reflection.
|
971
|
+
source_reflection.actual_source_reflection
|
1001
972
|
end
|
1002
973
|
|
1003
|
-
|
1004
|
-
|
974
|
+
private
|
975
|
+
def collect_join_reflections(seed)
|
976
|
+
a = source_reflection.add_as_source seed
|
977
|
+
if options[:source_type]
|
978
|
+
through_reflection.add_as_polymorphic_through self, a
|
979
|
+
else
|
980
|
+
through_reflection.add_as_through a
|
981
|
+
end
|
1005
982
|
end
|
1006
983
|
|
1007
984
|
def inverse_name; delegate_reflection.send(:inverse_name); end
|
@@ -1018,66 +995,32 @@ module ActiveRecord
|
|
1018
995
|
end
|
1019
996
|
|
1020
997
|
class PolymorphicReflection < AbstractReflection # :nodoc:
|
998
|
+
delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
|
999
|
+
|
1021
1000
|
def initialize(reflection, previous_reflection)
|
1022
1001
|
@reflection = reflection
|
1023
1002
|
@previous_reflection = previous_reflection
|
1024
1003
|
end
|
1025
1004
|
|
1026
|
-
def scopes
|
1027
|
-
scopes = @previous_reflection.scopes
|
1028
|
-
if @previous_reflection.options[:source_type]
|
1029
|
-
scopes + [@previous_reflection.source_type_scope]
|
1030
|
-
else
|
1031
|
-
scopes
|
1032
|
-
end
|
1033
|
-
end
|
1034
|
-
|
1035
1005
|
def join_scopes(table, predicate_builder) # :nodoc:
|
1036
1006
|
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1037
|
-
|
1038
|
-
scopes + [@previous_reflection.source_type_scope]
|
1039
|
-
else
|
1040
|
-
scopes
|
1041
|
-
end
|
1042
|
-
end
|
1043
|
-
|
1044
|
-
def klass
|
1045
|
-
@reflection.klass
|
1046
|
-
end
|
1047
|
-
|
1048
|
-
def scope
|
1049
|
-
@reflection.scope
|
1050
|
-
end
|
1051
|
-
|
1052
|
-
def table_name
|
1053
|
-
@reflection.table_name
|
1054
|
-
end
|
1055
|
-
|
1056
|
-
def plural_name
|
1057
|
-
@reflection.plural_name
|
1058
|
-
end
|
1059
|
-
|
1060
|
-
def type
|
1061
|
-
@reflection.type
|
1007
|
+
scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
|
1062
1008
|
end
|
1063
1009
|
|
1064
1010
|
def constraints
|
1065
|
-
@reflection.constraints + [
|
1066
|
-
end
|
1067
|
-
|
1068
|
-
def source_type_info
|
1069
|
-
type = @previous_reflection.foreign_type
|
1070
|
-
source_type = @previous_reflection.options[:source_type]
|
1071
|
-
lambda { |object| where(type => source_type) }
|
1011
|
+
@reflection.constraints + [source_type_scope]
|
1072
1012
|
end
|
1073
1013
|
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1014
|
+
private
|
1015
|
+
def source_type_scope
|
1016
|
+
type = @previous_reflection.foreign_type
|
1017
|
+
source_type = @previous_reflection.options[:source_type]
|
1018
|
+
lambda { |object| where(type => source_type) }
|
1019
|
+
end
|
1077
1020
|
end
|
1078
1021
|
|
1079
|
-
class RuntimeReflection <
|
1080
|
-
|
1022
|
+
class RuntimeReflection < AbstractReflection # :nodoc:
|
1023
|
+
delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
|
1081
1024
|
|
1082
1025
|
def initialize(reflection, association)
|
1083
1026
|
@reflection = reflection
|
@@ -1088,24 +1031,8 @@ module ActiveRecord
|
|
1088
1031
|
@association.klass
|
1089
1032
|
end
|
1090
1033
|
|
1091
|
-
def
|
1092
|
-
klass.
|
1093
|
-
end
|
1094
|
-
|
1095
|
-
def constraints
|
1096
|
-
@reflection.constraints
|
1097
|
-
end
|
1098
|
-
|
1099
|
-
def source_type_info
|
1100
|
-
@reflection.source_type_info
|
1101
|
-
end
|
1102
|
-
|
1103
|
-
def alias_candidate(name)
|
1104
|
-
"#{plural_name}_#{name}_join"
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
def alias_name
|
1108
|
-
Arel::Table.new(table_name)
|
1034
|
+
def aliased_table
|
1035
|
+
@aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
|
1109
1036
|
end
|
1110
1037
|
|
1111
1038
|
def all_includes; yield; end
|