activerecord 5.1.7 → 5.2.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (261) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +556 -685
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record.rb +11 -4
  8. data/lib/active_record/aggregations.rb +6 -5
  9. data/lib/active_record/association_relation.rb +7 -5
  10. data/lib/active_record/associations.rb +40 -63
  11. data/lib/active_record/associations/alias_tracker.rb +19 -27
  12. data/lib/active_record/associations/association.rb +41 -37
  13. data/lib/active_record/associations/association_scope.rb +38 -50
  14. data/lib/active_record/associations/belongs_to_association.rb +27 -8
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  16. data/lib/active_record/associations/builder/association.rb +4 -7
  17. data/lib/active_record/associations/builder/belongs_to.rb +12 -4
  18. data/lib/active_record/associations/builder/collection_association.rb +3 -3
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  20. data/lib/active_record/associations/builder/has_many.rb +2 -0
  21. data/lib/active_record/associations/builder/has_one.rb +2 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  23. data/lib/active_record/associations/collection_association.rb +59 -47
  24. data/lib/active_record/associations/collection_proxy.rb +20 -49
  25. data/lib/active_record/associations/foreign_association.rb +2 -0
  26. data/lib/active_record/associations/has_many_association.rb +12 -1
  27. data/lib/active_record/associations/has_many_through_association.rb +36 -30
  28. data/lib/active_record/associations/has_one_association.rb +12 -1
  29. data/lib/active_record/associations/has_one_through_association.rb +13 -8
  30. data/lib/active_record/associations/join_dependency.rb +48 -93
  31. data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
  32. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  33. data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
  34. data/lib/active_record/associations/preloader.rb +18 -38
  35. data/lib/active_record/associations/preloader/association.rb +45 -61
  36. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  37. data/lib/active_record/associations/singular_association.rb +14 -16
  38. data/lib/active_record/associations/through_association.rb +26 -11
  39. data/lib/active_record/attribute_assignment.rb +2 -5
  40. data/lib/active_record/attribute_decorators.rb +3 -2
  41. data/lib/active_record/attribute_methods.rb +65 -24
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +30 -214
  44. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  45. data/lib/active_record/attribute_methods/query.rb +2 -0
  46. data/lib/active_record/attribute_methods/read.rb +9 -3
  47. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  49. data/lib/active_record/attribute_methods/write.rb +21 -9
  50. data/lib/active_record/attributes.rb +6 -5
  51. data/lib/active_record/autosave_association.rb +35 -19
  52. data/lib/active_record/base.rb +2 -0
  53. data/lib/active_record/callbacks.rb +8 -6
  54. data/lib/active_record/coders/json.rb +2 -0
  55. data/lib/active_record/coders/yaml_column.rb +2 -0
  56. data/lib/active_record/collection_cache_key.rb +12 -8
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +139 -41
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -31
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
  70. data/lib/active_record/connection_adapters/column.rb +3 -1
  71. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
  73. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  101. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +233 -111
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -73
  118. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +22 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +81 -94
  127. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  128. data/lib/active_record/connection_handling.rb +4 -2
  129. data/lib/active_record/core.rb +41 -61
  130. data/lib/active_record/counter_cache.rb +10 -3
  131. data/lib/active_record/define_callbacks.rb +5 -3
  132. data/lib/active_record/dynamic_matchers.rb +9 -9
  133. data/lib/active_record/enum.rb +18 -13
  134. data/lib/active_record/errors.rb +42 -3
  135. data/lib/active_record/explain.rb +3 -1
  136. data/lib/active_record/explain_registry.rb +2 -0
  137. data/lib/active_record/explain_subscriber.rb +2 -0
  138. data/lib/active_record/fixture_set/file.rb +2 -0
  139. data/lib/active_record/fixtures.rb +67 -60
  140. data/lib/active_record/gem_version.rb +5 -3
  141. data/lib/active_record/inheritance.rb +49 -19
  142. data/lib/active_record/integration.rb +58 -19
  143. data/lib/active_record/internal_metadata.rb +2 -0
  144. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  145. data/lib/active_record/locking/optimistic.rb +14 -17
  146. data/lib/active_record/locking/pessimistic.rb +9 -6
  147. data/lib/active_record/log_subscriber.rb +43 -0
  148. data/lib/active_record/migration.rb +189 -139
  149. data/lib/active_record/migration/command_recorder.rb +11 -9
  150. data/lib/active_record/migration/compatibility.rb +47 -9
  151. data/lib/active_record/migration/join_table.rb +2 -0
  152. data/lib/active_record/model_schema.rb +16 -21
  153. data/lib/active_record/nested_attributes.rb +18 -6
  154. data/lib/active_record/no_touching.rb +3 -1
  155. data/lib/active_record/null_relation.rb +2 -0
  156. data/lib/active_record/persistence.rb +167 -16
  157. data/lib/active_record/query_cache.rb +6 -8
  158. data/lib/active_record/querying.rb +4 -2
  159. data/lib/active_record/railtie.rb +62 -6
  160. data/lib/active_record/railties/console_sandbox.rb +2 -0
  161. data/lib/active_record/railties/controller_runtime.rb +2 -0
  162. data/lib/active_record/railties/databases.rake +46 -36
  163. data/lib/active_record/readonly_attributes.rb +3 -2
  164. data/lib/active_record/reflection.rb +108 -194
  165. data/lib/active_record/relation.rb +120 -214
  166. data/lib/active_record/relation/batches.rb +20 -5
  167. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  168. data/lib/active_record/relation/calculations.rb +45 -19
  169. data/lib/active_record/relation/delegation.rb +45 -27
  170. data/lib/active_record/relation/finder_methods.rb +75 -76
  171. data/lib/active_record/relation/from_clause.rb +2 -8
  172. data/lib/active_record/relation/merger.rb +53 -23
  173. data/lib/active_record/relation/predicate_builder.rb +60 -79
  174. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  175. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  176. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  177. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  178. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  179. data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
  180. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  181. data/lib/active_record/relation/query_attribute.rb +28 -2
  182. data/lib/active_record/relation/query_methods.rb +128 -99
  183. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  184. data/lib/active_record/relation/spawn_methods.rb +4 -2
  185. data/lib/active_record/relation/where_clause.rb +65 -68
  186. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  187. data/lib/active_record/result.rb +2 -0
  188. data/lib/active_record/runtime_registry.rb +2 -0
  189. data/lib/active_record/sanitization.rb +129 -121
  190. data/lib/active_record/schema.rb +4 -2
  191. data/lib/active_record/schema_dumper.rb +36 -26
  192. data/lib/active_record/schema_migration.rb +2 -0
  193. data/lib/active_record/scoping.rb +9 -8
  194. data/lib/active_record/scoping/default.rb +8 -9
  195. data/lib/active_record/scoping/named.rb +23 -7
  196. data/lib/active_record/secure_token.rb +2 -0
  197. data/lib/active_record/serialization.rb +2 -0
  198. data/lib/active_record/statement_cache.rb +23 -13
  199. data/lib/active_record/store.rb +3 -1
  200. data/lib/active_record/suppressor.rb +2 -0
  201. data/lib/active_record/table_metadata.rb +12 -3
  202. data/lib/active_record/tasks/database_tasks.rb +25 -14
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  206. data/lib/active_record/timestamp.rb +6 -6
  207. data/lib/active_record/touch_later.rb +2 -0
  208. data/lib/active_record/transactions.rb +33 -28
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type.rb +4 -1
  211. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  212. data/lib/active_record/type/date.rb +2 -0
  213. data/lib/active_record/type/date_time.rb +2 -0
  214. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  215. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  216. data/lib/active_record/type/internal/timezone.rb +2 -0
  217. data/lib/active_record/type/json.rb +30 -0
  218. data/lib/active_record/type/serialized.rb +2 -0
  219. data/lib/active_record/type/text.rb +2 -0
  220. data/lib/active_record/type/time.rb +2 -0
  221. data/lib/active_record/type/type_map.rb +2 -0
  222. data/lib/active_record/type/unsigned_integer.rb +2 -0
  223. data/lib/active_record/type_caster.rb +2 -0
  224. data/lib/active_record/type_caster/connection.rb +2 -0
  225. data/lib/active_record/type_caster/map.rb +3 -1
  226. data/lib/active_record/validations.rb +2 -0
  227. data/lib/active_record/validations/absence.rb +2 -0
  228. data/lib/active_record/validations/associated.rb +2 -0
  229. data/lib/active_record/validations/length.rb +2 -0
  230. data/lib/active_record/validations/presence.rb +2 -0
  231. data/lib/active_record/validations/uniqueness.rb +35 -5
  232. data/lib/active_record/version.rb +2 -0
  233. data/lib/rails/generators/active_record.rb +3 -1
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  236. data/lib/rails/generators/active_record/migration.rb +2 -0
  237. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  238. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  239. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  240. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  241. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  242. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  243. metadata +23 -36
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  251. data/lib/active_record/attribute.rb +0 -240
  252. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  253. data/lib/active_record/attribute_mutation_tracker.rb +0 -122
  254. data/lib/active_record/attribute_set.rb +0 -113
  255. data/lib/active_record/attribute_set/builder.rb +0 -126
  256. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  257. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  258. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  259. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  260. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  261. data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record Query Cache
3
5
  class QueryCache
@@ -24,16 +26,12 @@ module ActiveRecord
24
26
  end
25
27
 
26
28
  def self.run
27
- caching_pool = ActiveRecord::Base.connection_pool
28
- caching_was_enabled = caching_pool.query_cache_enabled
29
-
30
- caching_pool.enable_query_cache!
31
-
32
- [caching_pool, caching_was_enabled]
29
+ ActiveRecord::Base.connection_handler.connection_pool_list.
30
+ reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
33
31
  end
34
32
 
35
- def self.complete((caching_pool, caching_was_enabled))
36
- caching_pool.disable_query_cache! unless caching_was_enabled
33
+ def self.complete(pools)
34
+ pools.each { |pool| pool.disable_query_cache! }
37
35
 
38
36
  ActiveRecord::Base.connection_handler.connection_pool_list.each do |pool|
39
37
  pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Querying
3
5
  delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all
@@ -5,7 +7,7 @@ module ActiveRecord
5
7
  delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
6
8
  delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
7
9
  delegate :find_by, :find_by!, to: :all
8
- delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, to: :all
10
+ delegate :destroy_all, :delete_all, :update_all, to: :all
9
11
  delegate :find_each, :find_in_batches, :in_batches, to: :all
10
12
  delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
11
13
  :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
@@ -38,7 +40,7 @@ module ActiveRecord
38
40
  def find_by_sql(sql, binds = [], preparable: nil, &block)
39
41
  result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
40
42
  column_types = result_set.column_types.dup
41
- columns_hash.each_key { |k| column_types.delete k }
43
+ attribute_types.each_key { |k| column_types.delete k }
42
44
  message_bus = ActiveSupport::Notifications.instrumenter
43
45
 
44
46
  payload = {
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record"
2
4
  require "rails"
3
5
  require "active_model/railtie"
@@ -26,6 +28,9 @@ module ActiveRecord
26
28
  config.active_record.use_schema_cache_dump = true
27
29
  config.active_record.maintain_test_schema = true
28
30
 
31
+ config.active_record.sqlite3 = ActiveSupport::OrderedOptions.new
32
+ config.active_record.sqlite3.represent_boolean_as_integer = nil
33
+
29
34
  config.eager_load_namespaces << ActiveRecord
30
35
 
31
36
  rake_tasks do
@@ -54,6 +59,7 @@ module ActiveRecord
54
59
  console = ActiveSupport::Logger.new(STDERR)
55
60
  Rails.logger.extend ActiveSupport::Logger.broadcast console
56
61
  end
62
+ ActiveRecord::Base.verbose_query_logs = false
57
63
  end
58
64
 
59
65
  runner do
@@ -85,12 +91,16 @@ module ActiveRecord
85
91
  filename = File.join(app.config.paths["db"].first, "schema_cache.yml")
86
92
 
87
93
  if File.file?(filename)
94
+ current_version = ActiveRecord::Migrator.current_version
95
+
96
+ next if current_version.nil?
97
+
88
98
  cache = YAML.load(File.read(filename))
89
- if cache.version == ActiveRecord::Migrator.current_version
99
+ if cache.version == current_version
90
100
  connection.schema_cache = cache
91
101
  connection_pool.schema_cache = cache.dup
92
102
  else
93
- warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}."
103
+ warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
94
104
  end
95
105
  end
96
106
  end
@@ -108,7 +118,9 @@ module ActiveRecord
108
118
 
109
119
  initializer "active_record.set_configs" do |app|
110
120
  ActiveSupport.on_load(:active_record) do
111
- app.config.active_record.each do |k, v|
121
+ configs = app.config.active_record.dup
122
+ configs.delete(:sqlite3)
123
+ configs.each do |k, v|
112
124
  send "#{k}=", v
113
125
  end
114
126
  end
@@ -157,14 +169,58 @@ end_warning
157
169
  end
158
170
 
159
171
  initializer "active_record.set_executor_hooks" do
160
- ActiveSupport.on_load(:active_record) do
161
- ActiveRecord::QueryCache.install_executor_hooks
162
- end
172
+ ActiveRecord::QueryCache.install_executor_hooks
163
173
  end
164
174
 
165
175
  initializer "active_record.add_watchable_files" do |app|
166
176
  path = app.paths["db"].first
167
177
  config.watchable_files.concat ["#{path}/schema.rb", "#{path}/structure.sql"]
168
178
  end
179
+
180
+ initializer "active_record.clear_active_connections" do
181
+ config.after_initialize do
182
+ ActiveSupport.on_load(:active_record) do
183
+ # Ideally the application doesn't connect to the database during boot,
184
+ # but sometimes it does. In case it did, we want to empty out the
185
+ # connection pools so that a non-database-using process (e.g. a master
186
+ # process in a forking server model) doesn't retain a needless
187
+ # connection. If it was needed, the incremental cost of reestablishing
188
+ # this connection is trivial: the rest of the pool would need to be
189
+ # populated anyway.
190
+
191
+ clear_active_connections!
192
+ flush_idle_connections!
193
+ end
194
+ end
195
+ end
196
+
197
+ initializer "active_record.check_represent_sqlite3_boolean_as_integer" do
198
+ config.after_initialize do
199
+ ActiveSupport.on_load(:active_record_sqlite3adapter) do
200
+ represent_boolean_as_integer = Rails.application.config.active_record.sqlite3.delete(:represent_boolean_as_integer)
201
+ unless represent_boolean_as_integer.nil?
202
+ ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
203
+ end
204
+
205
+ unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
206
+ ActiveSupport::Deprecation.warn <<-MSG
207
+ Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
208
+ set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
209
+ boolean values and must have old data converted to 1 and 0 (its native boolean
210
+ serialization) before setting this flag to true. Conversion can be accomplished
211
+ by setting up a rake task which runs
212
+
213
+ ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
214
+ ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
215
+
216
+ for all models and all boolean columns, after which the flag must be set to
217
+ true by adding the following to your application.rb file:
218
+
219
+ Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
220
+ MSG
221
+ end
222
+ end
223
+ end
224
+ end
169
225
  end
170
226
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ActiveRecord::Base.connection.begin_transaction(joinable: false)
2
4
 
3
5
  at_exit do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/attr_internal"
2
4
  require "active_record/log_subscriber"
3
5
 
@@ -1,17 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record"
2
4
 
3
5
  db_namespace = namespace :db do
4
6
  desc "Set the environment value for the database"
5
- task "environment:set" => [:environment, :load_config] do
7
+ task "environment:set" => :load_config do
6
8
  ActiveRecord::InternalMetadata.create_table
7
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
9
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
8
10
  end
9
11
 
10
- task check_protected_environments: [:environment, :load_config] do
12
+ task check_protected_environments: :load_config do
11
13
  ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
12
14
  end
13
15
 
14
- task :load_config do
16
+ task load_config: :environment do
15
17
  ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
16
18
  ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
17
19
  end
@@ -54,7 +56,7 @@ db_namespace = namespace :db do
54
56
  end
55
57
 
56
58
  desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
57
- task migrate: [:environment, :load_config] do
59
+ task migrate: :load_config do
58
60
  ActiveRecord::Tasks::DatabaseTasks.migrate
59
61
  db_namespace["_dump"].invoke
60
62
  end
@@ -76,7 +78,7 @@ db_namespace = namespace :db do
76
78
 
77
79
  namespace :migrate do
78
80
  # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
79
- task redo: [:environment, :load_config] do
81
+ task redo: :load_config do
80
82
  raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
81
83
 
82
84
  if ENV["VERSION"]
@@ -92,24 +94,33 @@ db_namespace = namespace :db do
92
94
  task reset: ["db:drop", "db:create", "db:migrate"]
93
95
 
94
96
  # desc 'Runs the "up" for a given migration VERSION.'
95
- task up: [:environment, :load_config] do
97
+ task up: :load_config do
96
98
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
97
99
 
98
- version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
99
- ActiveRecord::Migrator.run(:up, ActiveRecord::Tasks::DatabaseTasks.migrations_paths, version)
100
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
101
+
102
+ ActiveRecord::Base.connection.migration_context.run(
103
+ :up,
104
+ ActiveRecord::Tasks::DatabaseTasks.target_version
105
+ )
100
106
  db_namespace["_dump"].invoke
101
107
  end
102
108
 
103
109
  # desc 'Runs the "down" for a given migration VERSION.'
104
- task down: [:environment, :load_config] do
110
+ task down: :load_config do
105
111
  raise "VERSION is required - To go down one migration, use db:rollback" if !ENV["VERSION"] || ENV["VERSION"].empty?
106
- version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
107
- ActiveRecord::Migrator.run(:down, ActiveRecord::Tasks::DatabaseTasks.migrations_paths, version)
112
+
113
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
114
+
115
+ ActiveRecord::Base.connection.migration_context.run(
116
+ :down,
117
+ ActiveRecord::Tasks::DatabaseTasks.target_version
118
+ )
108
119
  db_namespace["_dump"].invoke
109
120
  end
110
121
 
111
122
  desc "Display status of migrations"
112
- task status: [:environment, :load_config] do
123
+ task status: :load_config do
113
124
  unless ActiveRecord::SchemaMigration.table_exists?
114
125
  abort "Schema migrations table does not exist yet."
115
126
  end
@@ -118,8 +129,7 @@ db_namespace = namespace :db do
118
129
  puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
119
130
  puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
120
131
  puts "-" * 50
121
- paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
122
- ActiveRecord::Migrator.migrations_status(paths).each do |status, version, name|
132
+ ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
123
133
  puts "#{status.center(8)} #{version.ljust(14)} #{name}"
124
134
  end
125
135
  puts
@@ -127,16 +137,16 @@ db_namespace = namespace :db do
127
137
  end
128
138
 
129
139
  desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
130
- task rollback: [:environment, :load_config] do
140
+ task rollback: :load_config do
131
141
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
132
- ActiveRecord::Migrator.rollback(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
142
+ ActiveRecord::Base.connection.migration_context.rollback(step)
133
143
  db_namespace["_dump"].invoke
134
144
  end
135
145
 
136
146
  # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
137
- task forward: [:environment, :load_config] do
147
+ task forward: :load_config do
138
148
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
139
- ActiveRecord::Migrator.forward(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
149
+ ActiveRecord::Base.connection.migration_context.forward(step)
140
150
  db_namespace["_dump"].invoke
141
151
  end
142
152
 
@@ -144,12 +154,12 @@ db_namespace = namespace :db do
144
154
  task reset: [ "db:drop", "db:setup" ]
145
155
 
146
156
  # desc "Retrieves the charset for the current environment's database"
147
- task charset: [:environment, :load_config] do
157
+ task charset: :load_config do
148
158
  puts ActiveRecord::Tasks::DatabaseTasks.charset_current
149
159
  end
150
160
 
151
161
  # desc "Retrieves the collation for the current environment's database"
152
- task collation: [:environment, :load_config] do
162
+ task collation: :load_config do
153
163
  begin
154
164
  puts ActiveRecord::Tasks::DatabaseTasks.collation_current
155
165
  rescue NoMethodError
@@ -158,13 +168,13 @@ db_namespace = namespace :db do
158
168
  end
159
169
 
160
170
  desc "Retrieves the current schema version number"
161
- task version: [:environment, :load_config] do
162
- puts "Current version: #{ActiveRecord::Migrator.current_version}"
171
+ task version: :load_config do
172
+ puts "Current version: #{ActiveRecord::Base.connection.migration_context.current_version}"
163
173
  end
164
174
 
165
175
  # desc "Raises an error if there are pending migrations"
166
- task abort_if_pending_migrations: [:environment, :load_config] do
167
- pending_migrations = ActiveRecord::Migrator.open(ActiveRecord::Tasks::DatabaseTasks.migrations_paths).pending_migrations
176
+ task abort_if_pending_migrations: :load_config do
177
+ pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
168
178
 
169
179
  if pending_migrations.any?
170
180
  puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
@@ -186,7 +196,7 @@ db_namespace = namespace :db do
186
196
 
187
197
  namespace :fixtures do
188
198
  desc "Loads fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
189
- task load: [:environment, :load_config] do
199
+ task load: :load_config do
190
200
  require "active_record/fixtures"
191
201
 
192
202
  base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
@@ -208,7 +218,7 @@ db_namespace = namespace :db do
208
218
  end
209
219
 
210
220
  # desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
211
- task identify: [:environment, :load_config] do
221
+ task identify: :load_config do
212
222
  require "active_record/fixtures"
213
223
 
214
224
  label, id = ENV["LABEL"], ENV["ID"]
@@ -219,7 +229,7 @@ db_namespace = namespace :db do
219
229
  base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
220
230
 
221
231
  Dir["#{base_dir}/**/*.yml"].each do |file|
222
- if data = YAML::load(ERB.new(IO.read(file)).result)
232
+ if data = YAML.load(ERB.new(IO.read(file)).result)
223
233
  data.each_key do |key|
224
234
  key_id = ActiveRecord::FixtureSet.identify(key)
225
235
 
@@ -234,7 +244,7 @@ db_namespace = namespace :db do
234
244
 
235
245
  namespace :schema do
236
246
  desc "Creates a db/schema.rb file that is portable against any DB supported by Active Record"
237
- task dump: [:environment, :load_config] do
247
+ task dump: :load_config do
238
248
  require "active_record/schema_dumper"
239
249
  filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema.rb")
240
250
  File.open(filename, "w:utf-8") do |file|
@@ -244,7 +254,7 @@ db_namespace = namespace :db do
244
254
  end
245
255
 
246
256
  desc "Loads a schema.rb file into the database"
247
- task load: [:environment, :load_config, :check_protected_environments] do
257
+ task load: [:load_config, :check_protected_environments] do
248
258
  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV["SCHEMA"])
249
259
  end
250
260
 
@@ -254,14 +264,14 @@ db_namespace = namespace :db do
254
264
 
255
265
  namespace :cache do
256
266
  desc "Creates a db/schema_cache.yml file."
257
- task dump: [:environment, :load_config] do
267
+ task dump: :load_config do
258
268
  conn = ActiveRecord::Base.connection
259
269
  filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
260
270
  ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(conn, filename)
261
271
  end
262
272
 
263
273
  desc "Clears a db/schema_cache.yml file."
264
- task clear: [:environment, :load_config] do
274
+ task clear: :load_config do
265
275
  filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
266
276
  rm_f filename, verbose: false
267
277
  end
@@ -271,7 +281,7 @@ db_namespace = namespace :db do
271
281
 
272
282
  namespace :structure do
273
283
  desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
274
- task dump: [:environment, :load_config] do
284
+ task dump: :load_config do
275
285
  filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
276
286
  current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
277
287
  ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
@@ -286,7 +296,7 @@ db_namespace = namespace :db do
286
296
  end
287
297
 
288
298
  desc "Recreates the databases from the structure.sql file"
289
- task load: [:environment, :load_config, :check_protected_environments] do
299
+ task load: [:load_config, :check_protected_environments] do
290
300
  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV["SCHEMA"])
291
301
  end
292
302
 
@@ -325,12 +335,12 @@ db_namespace = namespace :db do
325
335
  end
326
336
 
327
337
  # desc "Empty the test database"
328
- task purge: %w(environment load_config check_protected_environments) do
338
+ task purge: %w(load_config check_protected_environments) do
329
339
  ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations["test"]
330
340
  end
331
341
 
332
342
  # desc 'Load the test schema'
333
- task prepare: %w(environment load_config) do
343
+ task prepare: :load_config do
334
344
  unless ActiveRecord::Base.configurations.blank?
335
345
  db_namespace["test:load"].invoke
336
346
  end
@@ -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
- 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)
@@ -139,7 +138,7 @@ module ActiveRecord
139
138
  # HasAndBelongsToManyReflection
140
139
  # ThroughReflection
141
140
  # PolymorphicReflection
142
- # RuntimeReflection
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 klass
168
+ @join_keys ||= get_join_keys(klass)
178
169
  end
179
170
 
180
171
  # Returns a list of scopes that should be applied for this Reflection
@@ -183,22 +174,30 @@ module ActiveRecord
183
174
  scope ? [scope] : []
184
175
  end
185
176
 
186
- def scope_chain
187
- chain.map(&:scopes)
188
- end
189
- deprecate :scope_chain
190
-
191
- def join_scope(table)
177
+ def join_scope(table, foreign_table, foreign_klass)
192
178
  predicate_builder = predicate_builder(table)
193
179
  scope_chain_items = join_scopes(table, predicate_builder)
194
180
  klass_scope = klass_join_scope(table, predicate_builder)
195
181
 
196
- scope_chain_items.inject(klass_scope || scope_chain_items.shift, &:merge!)
182
+ key = join_keys.key
183
+ foreign_key = join_keys.foreign_key
184
+
185
+ klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
186
+
187
+ if type
188
+ klass_scope.where!(type => foreign_klass.polymorphic_name)
189
+ end
190
+
191
+ if klass.finder_needs_type_condition?
192
+ klass_scope.where!(klass.send(:type_condition, table))
193
+ end
194
+
195
+ scope_chain_items.inject(klass_scope, &:merge!)
197
196
  end
198
197
 
199
198
  def join_scopes(table, predicate_builder) # :nodoc:
200
199
  if scope
201
- [build_scope(table, predicate_builder).instance_exec(&scope)]
200
+ [scope_for(build_scope(table, predicate_builder))]
202
201
  else
203
202
  []
204
203
  end
@@ -210,7 +209,7 @@ module ActiveRecord
210
209
  end
211
210
 
212
211
  def constraints
213
- chain.map(&:scopes).flatten
212
+ chain.flat_map(&:scopes)
214
213
  end
215
214
 
216
215
  def counter_cache_column
@@ -284,24 +283,37 @@ module ActiveRecord
284
283
  end
285
284
 
286
285
  def get_join_keys(association_klass)
287
- JoinKeys.new(join_pk(association_klass), join_fk)
286
+ JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
288
287
  end
289
288
 
290
289
  def build_scope(table, predicate_builder = predicate_builder(table))
291
- Relation.create(klass, table, predicate_builder)
290
+ Relation.create(
291
+ klass,
292
+ table: table,
293
+ predicate_builder: predicate_builder
294
+ )
295
+ end
296
+
297
+ def join_primary_key(*)
298
+ foreign_key
299
+ end
300
+
301
+ def join_foreign_key
302
+ active_record_primary_key
292
303
  end
293
304
 
305
+ protected
306
+ def actual_source_reflection # FIXME: this is a horrible name
307
+ self
308
+ end
309
+
294
310
  private
295
311
  def predicate_builder(table)
296
312
  PredicateBuilder.new(TableMetadata.new(klass, table))
297
313
  end
298
314
 
299
- def join_pk(_)
300
- foreign_key
301
- end
302
-
303
- def join_fk
304
- active_record_primary_key
315
+ def primary_key(klass)
316
+ klass.primary_key || raise(UnknownPrimaryKey.new(klass))
305
317
  end
306
318
  end
307
319
 
@@ -348,6 +360,17 @@ module ActiveRecord
348
360
  #
349
361
  # <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
350
362
  # <tt>has_many :clients</tt> returns the Client class
363
+ #
364
+ # class Company < ActiveRecord::Base
365
+ # has_many :clients
366
+ # end
367
+ #
368
+ # Company.reflect_on_association(:clients).klass
369
+ # # => Client
370
+ #
371
+ # <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
372
+ # a new association object. Use +build_association+ or +create_association+
373
+ # instead. This allows plugins to hook into association object creation.
351
374
  def klass
352
375
  @klass ||= compute_class(class_name)
353
376
  end
@@ -366,8 +389,8 @@ module ActiveRecord
366
389
  active_record == other_aggregation.active_record
367
390
  end
368
391
 
369
- def scope_for(klass)
370
- scope ? klass.unscoped.instance_exec(nil, &scope) : klass.unscoped
392
+ def scope_for(relation, owner = nil)
393
+ relation.instance_exec(owner, &scope) || relation
371
394
  end
372
395
 
373
396
  private
@@ -388,23 +411,10 @@ module ActiveRecord
388
411
  # Holds all the metadata about an association as it was specified in the
389
412
  # Active Record class.
390
413
  class AssociationReflection < MacroReflection #:nodoc:
391
- # Returns the target association's class.
392
- #
393
- # class Author < ActiveRecord::Base
394
- # has_many :books
395
- # end
396
- #
397
- # Author.reflect_on_association(:books).klass
398
- # # => Book
399
- #
400
- # <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
401
- # a new association object. Use +build_association+ or +create_association+
402
- # instead. This allows plugins to hook into association object creation.
403
- def klass
404
- @klass ||= compute_class(class_name)
405
- end
406
-
407
414
  def compute_class(name)
415
+ if polymorphic?
416
+ raise ArgumentError, "Polymorphic association does not support to compute class."
417
+ end
408
418
  active_record.send(:compute_type, name)
409
419
  end
410
420
 
@@ -414,31 +424,21 @@ module ActiveRecord
414
424
  def initialize(name, scope, options, active_record)
415
425
  super
416
426
  @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
417
- @foreign_type = options[:foreign_type] || "#{name}_type"
427
+ @foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
418
428
  @constructable = calculate_constructable(macro, options)
419
- @association_scope_cache = {}
420
- @scope_lock = Mutex.new
429
+ @association_scope_cache = Concurrent::Map.new
421
430
 
422
431
  if options[:class_name] && options[:class_name].class == Class
423
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
424
- Passing a class to the `class_name` is deprecated and will raise
425
- an ArgumentError in Rails 5.2. It eagerloads more classes than
426
- necessary and potentially creates circular dependencies.
427
-
428
- Please pass the class name as a string:
429
- `#{macro} :#{name}, class_name: '#{options[:class_name]}'`
430
- MSG
432
+ raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
431
433
  end
432
434
  end
433
435
 
434
- def association_scope_cache(conn, owner)
436
+ def association_scope_cache(conn, owner, &block)
435
437
  key = conn.prepared_statements
436
438
  if polymorphic?
437
439
  key = [key, owner._read_attribute(@foreign_type)]
438
440
  end
439
- @association_scope_cache[key] ||= @scope_lock.synchronize {
440
- @association_scope_cache[key] ||= yield
441
- }
441
+ @association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
442
442
  end
443
443
 
444
444
  def constructable? # :nodoc:
@@ -462,10 +462,6 @@ module ActiveRecord
462
462
  options[:primary_key] || primary_key(klass || self.klass)
463
463
  end
464
464
 
465
- def association_primary_key_type
466
- klass.type_for_attribute(association_primary_key.to_s)
467
- end
468
-
469
465
  def active_record_primary_key
470
466
  @active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
471
467
  end
@@ -488,7 +484,7 @@ module ActiveRecord
488
484
  alias :check_eager_loadable! :check_preloadable!
489
485
 
490
486
  def join_id_for(owner) # :nodoc:
491
- owner[active_record_primary_key]
487
+ owner[join_foreign_key]
492
488
  end
493
489
 
494
490
  def through_reflection
@@ -571,7 +567,7 @@ module ActiveRecord
571
567
  end
572
568
 
573
569
  VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
574
- INVALID_AUTOMATIC_INVERSE_OPTIONS = [:conditions, :through, :polymorphic, :foreign_key]
570
+ INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
575
571
 
576
572
  def add_as_source(seed)
577
573
  seed
@@ -589,12 +585,6 @@ module ActiveRecord
589
585
  Array(options[:extend])
590
586
  end
591
587
 
592
- protected
593
-
594
- def actual_source_reflection # FIXME: this is a horrible name
595
- self
596
- end
597
-
598
588
  private
599
589
 
600
590
  def calculate_constructable(macro, options)
@@ -635,12 +625,9 @@ module ActiveRecord
635
625
  # +automatic_inverse_of+ method is a valid reflection. We must
636
626
  # make sure that the reflection's active_record name matches up
637
627
  # with the current reflection's klass name.
638
- #
639
- # Note: klass will always be valid because when there's a NameError
640
- # from calling +klass+, +reflection+ will already be set to false.
641
628
  def valid_inverse_reflection?(reflection)
642
629
  reflection &&
643
- klass.name == reflection.active_record.name &&
630
+ klass <= reflection.active_record &&
644
631
  can_find_inverse_of_automatically?(reflection)
645
632
  end
646
633
 
@@ -648,9 +635,8 @@ module ActiveRecord
648
635
  # us from being able to guess the inverse automatically. First, the
649
636
  # <tt>inverse_of</tt> option cannot be set to false. Second, we must
650
637
  # have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
651
- # Third, we must not have options such as <tt>:polymorphic</tt> or
652
- # <tt>:foreign_key</tt> which prevent us from correctly guessing the
653
- # inverse association.
638
+ # Third, we must not have options such as <tt>:foreign_key</tt>
639
+ # which prevent us from correctly guessing the inverse association.
654
640
  #
655
641
  # Anything with a scope can additionally ruin our attempt at finding an
656
642
  # inverse, so we exclude reflections with scopes.
@@ -680,10 +666,6 @@ module ActiveRecord
680
666
  def derive_join_table
681
667
  ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
682
668
  end
683
-
684
- def primary_key(klass)
685
- klass.primary_key || raise(UnknownPrimaryKey.new(klass))
686
- end
687
669
  end
688
670
 
689
671
  class HasManyReflection < AssociationReflection # :nodoc:
@@ -737,30 +719,25 @@ module ActiveRecord
737
719
  end
738
720
  end
739
721
 
740
- def join_id_for(owner) # :nodoc:
741
- owner[foreign_key]
722
+ def join_primary_key(klass = nil)
723
+ polymorphic? ? association_primary_key(klass) : association_primary_key
724
+ end
725
+
726
+ def join_foreign_key
727
+ foreign_key
742
728
  end
743
729
 
744
730
  private
731
+ def can_find_inverse_of_automatically?(_)
732
+ !polymorphic? && super
733
+ end
745
734
 
746
735
  def calculate_constructable(macro, options)
747
736
  !polymorphic?
748
737
  end
749
-
750
- def join_fk
751
- foreign_key
752
- end
753
-
754
- def join_pk(klass)
755
- polymorphic? ? association_primary_key(klass) : association_primary_key
756
- end
757
738
  end
758
739
 
759
740
  class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
760
- def initialize(name, scope, options, active_record)
761
- super
762
- end
763
-
764
741
  def macro; :has_and_belongs_to_many; end
765
742
 
766
743
  def collection?
@@ -771,8 +748,7 @@ module ActiveRecord
771
748
  # Holds all the metadata about a :through association as it was specified
772
749
  # in the Active Record class.
773
750
  class ThroughReflection < AbstractReflection #:nodoc:
774
- attr_reader :delegate_reflection
775
- delegate :foreign_key, :foreign_type, :association_foreign_key,
751
+ delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
776
752
  :active_record_primary_key, :type, :get_join_keys, to: :source_reflection
777
753
 
778
754
  def initialize(delegate_reflection)
@@ -863,10 +839,6 @@ module ActiveRecord
863
839
  source_reflection.join_scopes(table, predicate_builder) + super
864
840
  end
865
841
 
866
- def source_type_scope
867
- through_reflection.klass.where(foreign_type => options[:source_type])
868
- end
869
-
870
842
  def has_scope?
871
843
  scope || options[:source_type] ||
872
844
  source_reflection.has_scope? ||
@@ -887,10 +859,6 @@ module ActiveRecord
887
859
  actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
888
860
  end
889
861
 
890
- def association_primary_key_type
891
- klass.type_for_attribute(association_primary_key.to_s)
892
- end
893
-
894
862
  # Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
895
863
  #
896
864
  # class Post < ActiveRecord::Base
@@ -935,10 +903,6 @@ module ActiveRecord
935
903
  through_reflection.options
936
904
  end
937
905
 
938
- def join_id_for(owner) # :nodoc:
939
- source_reflection.join_id_for(owner)
940
- end
941
-
942
906
  def check_validity!
943
907
  if through_reflection.nil?
944
908
  raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
@@ -997,23 +961,23 @@ module ActiveRecord
997
961
  collect_join_reflections(seed + [self])
998
962
  end
999
963
 
1000
- def collect_join_reflections(seed)
1001
- a = source_reflection.add_as_source seed
1002
- if options[:source_type]
1003
- through_reflection.add_as_polymorphic_through self, a
1004
- else
1005
- through_reflection.add_as_through a
1006
- end
1007
- end
1008
-
1009
- private
964
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
965
+ # Workaround for Ruby 2.2 "private attribute?" warning.
966
+ protected
967
+ attr_reader :delegate_reflection
1010
968
 
1011
969
  def actual_source_reflection # FIXME: this is a horrible name
1012
- source_reflection.send(:actual_source_reflection)
970
+ source_reflection.actual_source_reflection
1013
971
  end
1014
972
 
1015
- def primary_key(klass)
1016
- klass.primary_key || raise(UnknownPrimaryKey.new(klass))
973
+ private
974
+ def collect_join_reflections(seed)
975
+ a = source_reflection.add_as_source seed
976
+ if options[:source_type]
977
+ through_reflection.add_as_polymorphic_through self, a
978
+ else
979
+ through_reflection.add_as_through a
980
+ end
1017
981
  end
1018
982
 
1019
983
  def inverse_name; delegate_reflection.send(:inverse_name); end
@@ -1030,66 +994,32 @@ module ActiveRecord
1030
994
  end
1031
995
 
1032
996
  class PolymorphicReflection < AbstractReflection # :nodoc:
997
+ delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
998
+
1033
999
  def initialize(reflection, previous_reflection)
1034
1000
  @reflection = reflection
1035
1001
  @previous_reflection = previous_reflection
1036
1002
  end
1037
1003
 
1038
- def scopes
1039
- scopes = @previous_reflection.scopes
1040
- if @previous_reflection.options[:source_type]
1041
- scopes + [@previous_reflection.source_type_scope]
1042
- else
1043
- scopes
1044
- end
1045
- end
1046
-
1047
1004
  def join_scopes(table, predicate_builder) # :nodoc:
1048
1005
  scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
1049
- if @previous_reflection.options[:source_type]
1050
- scopes + [@previous_reflection.source_type_scope]
1051
- else
1052
- scopes
1053
- end
1054
- end
1055
-
1056
- def klass
1057
- @reflection.klass
1058
- end
1059
-
1060
- def scope
1061
- @reflection.scope
1062
- end
1063
-
1064
- def table_name
1065
- @reflection.table_name
1066
- end
1067
-
1068
- def plural_name
1069
- @reflection.plural_name
1070
- end
1071
-
1072
- def type
1073
- @reflection.type
1006
+ scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
1074
1007
  end
1075
1008
 
1076
1009
  def constraints
1077
- @reflection.constraints + [source_type_info]
1078
- end
1079
-
1080
- def source_type_info
1081
- type = @previous_reflection.foreign_type
1082
- source_type = @previous_reflection.options[:source_type]
1083
- lambda { |object| where(type => source_type) }
1010
+ @reflection.constraints + [source_type_scope]
1084
1011
  end
1085
1012
 
1086
- def get_join_keys(association_klass)
1087
- @reflection.get_join_keys(association_klass)
1088
- end
1013
+ private
1014
+ def source_type_scope
1015
+ type = @previous_reflection.foreign_type
1016
+ source_type = @previous_reflection.options[:source_type]
1017
+ lambda { |object| where(type => source_type) }
1018
+ end
1089
1019
  end
1090
1020
 
1091
- class RuntimeReflection < PolymorphicReflection # :nodoc:
1092
- attr_accessor :next
1021
+ class RuntimeReflection < AbstractReflection # :nodoc:
1022
+ delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
1093
1023
 
1094
1024
  def initialize(reflection, association)
1095
1025
  @reflection = reflection
@@ -1100,24 +1030,8 @@ module ActiveRecord
1100
1030
  @association.klass
1101
1031
  end
1102
1032
 
1103
- def table_name
1104
- klass.table_name
1105
- end
1106
-
1107
- def constraints
1108
- @reflection.constraints
1109
- end
1110
-
1111
- def source_type_info
1112
- @reflection.source_type_info
1113
- end
1114
-
1115
- def alias_candidate(name)
1116
- "#{plural_name}_#{name}_join"
1117
- end
1118
-
1119
- def alias_name
1120
- Arel::Table.new(table_name, type_caster: klass.type_caster)
1033
+ def aliased_table
1034
+ @aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
1121
1035
  end
1122
1036
 
1123
1037
  def all_includes; yield; end