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.

Files changed (260) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +410 -530
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record/aggregations.rb +6 -5
  8. data/lib/active_record/association_relation.rb +4 -2
  9. data/lib/active_record/associations/alias_tracker.rb +23 -32
  10. data/lib/active_record/associations/association.rb +20 -21
  11. data/lib/active_record/associations/association_scope.rb +49 -49
  12. data/lib/active_record/associations/belongs_to_association.rb +12 -10
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -6
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +2 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +50 -41
  22. data/lib/active_record/associations/collection_proxy.rb +22 -39
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +4 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +12 -18
  26. data/lib/active_record/associations/has_one_association.rb +5 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +8 -7
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -64
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  31. data/lib/active_record/associations/join_dependency.rb +27 -44
  32. data/lib/active_record/associations/preloader/association.rb +53 -92
  33. data/lib/active_record/associations/preloader/through_association.rb +72 -73
  34. data/lib/active_record/associations/preloader.rb +17 -37
  35. data/lib/active_record/associations/singular_association.rb +14 -10
  36. data/lib/active_record/associations/through_association.rb +26 -11
  37. data/lib/active_record/associations.rb +68 -76
  38. data/lib/active_record/attribute_assignment.rb +2 -0
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +24 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +10 -13
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +8 -2
  45. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  47. data/lib/active_record/attribute_methods/write.rb +22 -19
  48. data/lib/active_record/attribute_methods.rb +48 -12
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +8 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +8 -6
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +2 -0
  55. data/lib/active_record/collection_cache_key.rb +14 -10
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -33
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +58 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
  69. data/lib/active_record/connection_adapters/column.rb +4 -2
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -17
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -23
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +269 -126
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +64 -85
  116. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  118. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +18 -0
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  122. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  123. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  124. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +92 -95
  125. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  126. data/lib/active_record/connection_handling.rb +4 -2
  127. data/lib/active_record/core.rb +39 -60
  128. data/lib/active_record/counter_cache.rb +3 -2
  129. data/lib/active_record/define_callbacks.rb +5 -3
  130. data/lib/active_record/dynamic_matchers.rb +9 -9
  131. data/lib/active_record/enum.rb +17 -13
  132. data/lib/active_record/errors.rb +42 -3
  133. data/lib/active_record/explain.rb +3 -1
  134. data/lib/active_record/explain_registry.rb +2 -0
  135. data/lib/active_record/explain_subscriber.rb +2 -0
  136. data/lib/active_record/fixture_set/file.rb +2 -0
  137. data/lib/active_record/fixtures.rb +67 -60
  138. data/lib/active_record/gem_version.rb +4 -2
  139. data/lib/active_record/inheritance.rb +9 -9
  140. data/lib/active_record/integration.rb +58 -19
  141. data/lib/active_record/internal_metadata.rb +2 -0
  142. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  143. data/lib/active_record/locking/optimistic.rb +8 -6
  144. data/lib/active_record/locking/pessimistic.rb +9 -6
  145. data/lib/active_record/log_subscriber.rb +46 -4
  146. data/lib/active_record/migration/command_recorder.rb +11 -9
  147. data/lib/active_record/migration/compatibility.rb +74 -22
  148. data/lib/active_record/migration/join_table.rb +2 -0
  149. data/lib/active_record/migration.rb +181 -137
  150. data/lib/active_record/model_schema.rb +73 -58
  151. data/lib/active_record/nested_attributes.rb +18 -6
  152. data/lib/active_record/no_touching.rb +3 -1
  153. data/lib/active_record/null_relation.rb +2 -0
  154. data/lib/active_record/persistence.rb +153 -18
  155. data/lib/active_record/query_cache.rb +17 -12
  156. data/lib/active_record/querying.rb +4 -2
  157. data/lib/active_record/railtie.rb +61 -3
  158. data/lib/active_record/railties/console_sandbox.rb +2 -0
  159. data/lib/active_record/railties/controller_runtime.rb +2 -0
  160. data/lib/active_record/railties/databases.rake +47 -37
  161. data/lib/active_record/readonly_attributes.rb +3 -2
  162. data/lib/active_record/reflection.rb +131 -204
  163. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  164. data/lib/active_record/relation/batches.rb +32 -17
  165. data/lib/active_record/relation/calculations.rb +58 -20
  166. data/lib/active_record/relation/delegation.rb +10 -29
  167. data/lib/active_record/relation/finder_methods.rb +74 -85
  168. data/lib/active_record/relation/from_clause.rb +2 -8
  169. data/lib/active_record/relation/merger.rb +51 -20
  170. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  171. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  172. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  173. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
  175. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
  176. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  177. data/lib/active_record/relation/predicate_builder.rb +53 -78
  178. data/lib/active_record/relation/query_attribute.rb +9 -2
  179. data/lib/active_record/relation/query_methods.rb +101 -95
  180. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  181. data/lib/active_record/relation/spawn_methods.rb +3 -1
  182. data/lib/active_record/relation/where_clause.rb +65 -67
  183. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  184. data/lib/active_record/relation.rb +99 -202
  185. data/lib/active_record/result.rb +2 -0
  186. data/lib/active_record/runtime_registry.rb +2 -0
  187. data/lib/active_record/sanitization.rb +129 -121
  188. data/lib/active_record/schema.rb +4 -2
  189. data/lib/active_record/schema_dumper.rb +36 -26
  190. data/lib/active_record/schema_migration.rb +2 -0
  191. data/lib/active_record/scoping/default.rb +10 -7
  192. data/lib/active_record/scoping/named.rb +38 -12
  193. data/lib/active_record/scoping.rb +12 -10
  194. data/lib/active_record/secure_token.rb +2 -0
  195. data/lib/active_record/serialization.rb +2 -0
  196. data/lib/active_record/statement_cache.rb +22 -12
  197. data/lib/active_record/store.rb +3 -1
  198. data/lib/active_record/suppressor.rb +2 -0
  199. data/lib/active_record/table_metadata.rb +12 -3
  200. data/lib/active_record/tasks/database_tasks.rb +37 -25
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  204. data/lib/active_record/timestamp.rb +5 -5
  205. data/lib/active_record/touch_later.rb +2 -0
  206. data/lib/active_record/transactions.rb +9 -7
  207. data/lib/active_record/translation.rb +2 -0
  208. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  209. data/lib/active_record/type/date.rb +2 -0
  210. data/lib/active_record/type/date_time.rb +2 -0
  211. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  212. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  213. data/lib/active_record/type/internal/timezone.rb +2 -0
  214. data/lib/active_record/type/json.rb +30 -0
  215. data/lib/active_record/type/serialized.rb +2 -0
  216. data/lib/active_record/type/text.rb +2 -0
  217. data/lib/active_record/type/time.rb +2 -0
  218. data/lib/active_record/type/type_map.rb +2 -0
  219. data/lib/active_record/type/unsigned_integer.rb +2 -0
  220. data/lib/active_record/type.rb +4 -1
  221. data/lib/active_record/type_caster/connection.rb +2 -0
  222. data/lib/active_record/type_caster/map.rb +3 -1
  223. data/lib/active_record/type_caster.rb +2 -0
  224. data/lib/active_record/validations/absence.rb +2 -0
  225. data/lib/active_record/validations/associated.rb +2 -0
  226. data/lib/active_record/validations/length.rb +2 -0
  227. data/lib/active_record/validations/presence.rb +2 -0
  228. data/lib/active_record/validations/uniqueness.rb +35 -5
  229. data/lib/active_record/validations.rb +2 -0
  230. data/lib/active_record/version.rb +2 -0
  231. data/lib/active_record.rb +11 -4
  232. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  233. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  235. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  236. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration.rb +2 -0
  238. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  239. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  240. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record.rb +3 -1
  242. metadata +25 -37
  243. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  244. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  245. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  246. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  247. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  248. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  249. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  250. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  251. data/lib/active_record/attribute.rb +0 -240
  252. data/lib/active_record/attribute_mutation_tracker.rb +0 -113
  253. data/lib/active_record/attribute_set/builder.rb +0 -124
  254. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  255. data/lib/active_record/attribute_set.rb +0 -113
  256. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  257. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  258. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  259. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  260. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,6 +1,7 @@
1
- require "thread"
1
+ # frozen_string_literal: true
2
+
2
3
  require "active_support/core_ext/string/filters"
3
- require "active_support/deprecation"
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
- ar._reflections = ar._reflections.merge(name.to_s => reflection)
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
- # RuntimeReflection
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 klass
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 scope_chain
186
- chain.map(&:scopes)
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
- [ActiveRecord::Relation.create(klass, table, predicate_builder)
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
- if klass.current_scope
201
- klass.current_scope.clone.tap { |scope|
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.map(&:scopes).flatten
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(join_pk(association_klass), join_fk)
290
+ JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
290
291
  end
291
292
 
292
- private
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
- def join_pk(_)
295
- foreign_key
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
- def join_fk
299
- active_record_primary_key
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(klass)
365
- scope ? klass.unscoped.instance_exec(nil, &scope) : klass.unscoped
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
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
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[key] ||= @scope_lock.synchronize {
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[active_record_primary_key]
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 = [:conditions, :through, :polymorphic, :foreign_key]
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
- protected
585
-
586
- def actual_source_reflection # FIXME: this is a horrible name
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
- options.fetch(:inverse_of) do
601
- @automatic_inverse_of ||= automatic_inverse_of
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 false or the inverse association name that it finds.
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.name == reflection.active_record.name &&
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>:polymorphic</tt> or
644
- # <tt>:foreign_key</tt> which prevent us from correctly guessing the
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 join_id_for(owner) # :nodoc:
729
- owner[foreign_key]
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
- attr_reader :delegate_reflection
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
- def collect_join_reflections(seed)
989
- a = source_reflection.add_as_source seed
990
- if options[:source_type]
991
- through_reflection.add_as_polymorphic_through self, a
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.send(:actual_source_reflection)
971
+ source_reflection.actual_source_reflection
1001
972
  end
1002
973
 
1003
- def primary_key(klass)
1004
- klass.primary_key || raise(UnknownPrimaryKey.new(klass))
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
- if @previous_reflection.options[:source_type]
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 + [source_type_info]
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
- def get_join_keys(association_klass)
1075
- @reflection.get_join_keys(association_klass)
1076
- end
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 < PolymorphicReflection # :nodoc:
1080
- attr_accessor :next
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 table_name
1092
- klass.table_name
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Batches
3
5
  class BatchEnumerator