activerecord 5.1.7 → 5.2.0.beta1

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 (259) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +221 -900
  3. data/README.rdoc +3 -3
  4. data/examples/performance.rb +2 -0
  5. data/examples/simple.rb +2 -0
  6. data/lib/active_record.rb +10 -3
  7. data/lib/active_record/aggregations.rb +2 -0
  8. data/lib/active_record/association_relation.rb +2 -0
  9. data/lib/active_record/associations.rb +13 -42
  10. data/lib/active_record/associations/alias_tracker.rb +17 -17
  11. data/lib/active_record/associations/association.rb +11 -22
  12. data/lib/active_record/associations/association_scope.rb +32 -44
  13. data/lib/active_record/associations/belongs_to_association.rb +6 -4
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -1
  15. data/lib/active_record/associations/builder/association.rb +2 -5
  16. data/lib/active_record/associations/builder/belongs_to.rb +7 -12
  17. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  19. data/lib/active_record/associations/builder/has_many.rb +2 -0
  20. data/lib/active_record/associations/builder/has_one.rb +2 -0
  21. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  22. data/lib/active_record/associations/collection_association.rb +41 -33
  23. data/lib/active_record/associations/collection_proxy.rb +11 -14
  24. data/lib/active_record/associations/foreign_association.rb +2 -0
  25. data/lib/active_record/associations/has_many_association.rb +4 -2
  26. data/lib/active_record/associations/has_many_through_association.rb +4 -2
  27. data/lib/active_record/associations/has_one_association.rb +3 -1
  28. data/lib/active_record/associations/has_one_through_association.rb +3 -1
  29. data/lib/active_record/associations/join_dependency.rb +22 -40
  30. data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
  31. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  32. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  33. data/lib/active_record/associations/preloader.rb +17 -37
  34. data/lib/active_record/associations/preloader/association.rb +42 -58
  35. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  36. data/lib/active_record/associations/singular_association.rb +14 -10
  37. data/lib/active_record/associations/through_association.rb +3 -1
  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.rb +47 -7
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  42. data/lib/active_record/attribute_methods/dirty.rb +25 -214
  43. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  44. data/lib/active_record/attribute_methods/query.rb +2 -0
  45. data/lib/active_record/attribute_methods/read.rb +8 -2
  46. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  48. data/lib/active_record/attribute_methods/write.rb +21 -9
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +5 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +6 -8
  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 +10 -5
  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 +120 -28
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -33
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +13 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +40 -2
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +103 -63
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -90
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +75 -138
  69. data/lib/active_record/connection_adapters/column.rb +3 -1
  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 +3 -1
  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 -6
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +91 -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 +2 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -11
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +3 -5
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +10 -0
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +11 -7
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +79 -65
  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 +47 -82
  116. data/lib/active_record/connection_adapters/schema_cache.rb +2 -0
  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 +19 -2
  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 +34 -89
  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 +27 -57
  128. data/lib/active_record/counter_cache.rb +15 -12
  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 +15 -13
  132. data/lib/active_record/errors.rb +54 -21
  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 +40 -24
  138. data/lib/active_record/gem_version.rb +5 -3
  139. data/lib/active_record/inheritance.rb +6 -5
  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 +31 -20
  144. data/lib/active_record/locking/pessimistic.rb +10 -7
  145. data/lib/active_record/log_subscriber.rb +2 -0
  146. data/lib/active_record/migration.rb +47 -21
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +20 -2
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/model_schema.rb +29 -38
  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 +184 -40
  155. data/lib/active_record/query_cache.rb +17 -12
  156. data/lib/active_record/querying.rb +3 -1
  157. data/lib/active_record/railtie.rb +54 -1
  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 +41 -28
  161. data/lib/active_record/readonly_attributes.rb +3 -2
  162. data/lib/active_record/reflection.rb +100 -182
  163. data/lib/active_record/relation.rb +61 -193
  164. data/lib/active_record/relation/batches.rb +20 -5
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  166. data/lib/active_record/relation/calculations.rb +40 -23
  167. data/lib/active_record/relation/delegation.rb +10 -27
  168. data/lib/active_record/relation/finder_methods.rb +53 -49
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +22 -19
  171. data/lib/active_record/relation/predicate_builder.rb +42 -79
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  179. data/lib/active_record/relation/query_attribute.rb +9 -2
  180. data/lib/active_record/relation/query_methods.rb +80 -69
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +2 -0
  183. data/lib/active_record/relation/where_clause.rb +50 -67
  184. data/lib/active_record/relation/where_clause_factory.rb +4 -46
  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 +15 -9
  188. data/lib/active_record/schema.rb +3 -1
  189. data/lib/active_record/schema_dumper.rb +24 -23
  190. data/lib/active_record/schema_migration.rb +2 -0
  191. data/lib/active_record/scoping.rb +9 -8
  192. data/lib/active_record/scoping/default.rb +6 -7
  193. data/lib/active_record/scoping/named.rb +15 -7
  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 +2 -0
  198. data/lib/active_record/suppressor.rb +2 -0
  199. data/lib/active_record/table_metadata.rb +3 -1
  200. data/lib/active_record/tasks/database_tasks.rb +23 -12
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  204. data/lib/active_record/timestamp.rb +5 -12
  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.rb +4 -1
  209. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  210. data/lib/active_record/type/date.rb +2 -0
  211. data/lib/active_record/type/date_time.rb +2 -0
  212. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  213. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  214. data/lib/active_record/type/internal/timezone.rb +2 -0
  215. data/lib/active_record/type/json.rb +30 -0
  216. data/lib/active_record/type/serialized.rb +2 -4
  217. data/lib/active_record/type/text.rb +2 -0
  218. data/lib/active_record/type/time.rb +2 -0
  219. data/lib/active_record/type/type_map.rb +2 -0
  220. data/lib/active_record/type/unsigned_integer.rb +2 -0
  221. data/lib/active_record/type_caster.rb +2 -0
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +2 -0
  224. data/lib/active_record/validations.rb +2 -0
  225. data/lib/active_record/validations/absence.rb +2 -0
  226. data/lib/active_record/validations/associated.rb +2 -0
  227. data/lib/active_record/validations/length.rb +2 -0
  228. data/lib/active_record/validations/presence.rb +2 -0
  229. data/lib/active_record/validations/uniqueness.rb +36 -6
  230. data/lib/active_record/version.rb +2 -0
  231. data/lib/rails/generators/active_record.rb +3 -1
  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.rb +2 -0
  235. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  236. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -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. metadata +25 -38
  242. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  243. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  244. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  245. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  246. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  248. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  249. data/lib/active_record/attribute.rb +0 -240
  250. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  251. data/lib/active_record/attribute_mutation_tracker.rb +0 -122
  252. data/lib/active_record/attribute_set.rb +0 -113
  253. data/lib/active_record/attribute_set/builder.rb +0 -126
  254. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  255. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  256. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  257. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  258. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  259. 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
@@ -5,35 +7,38 @@ module ActiveRecord
5
7
  # Enable the query cache within the block if Active Record is configured.
6
8
  # If it's not, it will execute the given block.
7
9
  def cache(&block)
8
- if connected? || !configurations.empty?
9
- connection.cache(&block)
10
- else
10
+ if configurations.empty?
11
11
  yield
12
+ else
13
+ connection.cache(&block)
12
14
  end
13
15
  end
14
16
 
15
17
  # Disable the query cache within the block if Active Record is configured.
16
18
  # If it's not, it will execute the given block.
17
19
  def uncached(&block)
18
- if connected? || !configurations.empty?
19
- connection.uncached(&block)
20
- else
20
+ if configurations.empty?
21
21
  yield
22
+ else
23
+ connection.uncached(&block)
22
24
  end
23
25
  end
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
+ ActiveRecord::Base.connection_handler.connection_pool_list.map do |pool|
30
+ caching_was_enabled = pool.query_cache_enabled
29
31
 
30
- caching_pool.enable_query_cache!
32
+ pool.enable_query_cache!
31
33
 
32
- [caching_pool, caching_was_enabled]
34
+ [pool, caching_was_enabled]
35
+ end
33
36
  end
34
37
 
35
- def self.complete((caching_pool, caching_was_enabled))
36
- caching_pool.disable_query_cache! unless caching_was_enabled
38
+ def self.complete(caching_pools)
39
+ caching_pools.each do |pool, caching_was_enabled|
40
+ pool.disable_query_cache! unless caching_was_enabled
41
+ end
37
42
 
38
43
  ActiveRecord::Base.connection_handler.connection_pool_list.each do |pool|
39
44
  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,
@@ -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
@@ -108,7 +113,9 @@ module ActiveRecord
108
113
 
109
114
  initializer "active_record.set_configs" do |app|
110
115
  ActiveSupport.on_load(:active_record) do
111
- app.config.active_record.each do |k, v|
116
+ configs = app.config.active_record.dup
117
+ configs.delete(:sqlite3)
118
+ configs.each do |k, v|
112
119
  send "#{k}=", v
113
120
  end
114
121
  end
@@ -166,5 +173,51 @@ end_warning
166
173
  path = app.paths["db"].first
167
174
  config.watchable_files.concat ["#{path}/schema.rb", "#{path}/structure.sql"]
168
175
  end
176
+
177
+ initializer "active_record.clear_active_connections" do
178
+ config.after_initialize do
179
+ ActiveSupport.on_load(:active_record) do
180
+ # Ideally the application doesn't connect to the database during boot,
181
+ # but sometimes it does. In case it did, we want to empty out the
182
+ # connection pools so that a non-database-using process (e.g. a master
183
+ # process in a forking server model) doesn't retain a needless
184
+ # connection. If it was needed, the incremental cost of reestablishing
185
+ # this connection is trivial: the rest of the pool would need to be
186
+ # populated anyway.
187
+
188
+ clear_active_connections!
189
+ flush_idle_connections!
190
+ end
191
+ end
192
+ end
193
+
194
+ initializer "active_record.check_represent_sqlite3_boolean_as_integer" do
195
+ config.after_initialize do
196
+ ActiveSupport.on_load(:active_record_sqlite3adapter) do
197
+ represent_boolean_as_integer = Rails.application.config.active_record.sqlite3.delete(:represent_boolean_as_integer)
198
+ unless represent_boolean_as_integer.nil?
199
+ ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
200
+ end
201
+
202
+ unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
203
+ ActiveSupport::Deprecation.warn <<-MSG
204
+ Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
205
+ set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
206
+ boolean values and must have old data converted to 1 and 0 (its native boolean
207
+ serialization) before setting this flag to true. Conversion can be accomplished
208
+ by setting up a rake task which runs
209
+
210
+ ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
211
+ ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
212
+
213
+ for all models and all boolean columns, after which the flag must be set to
214
+ true by adding the following to your application.rb file:
215
+
216
+ Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
217
+ MSG
218
+ end
219
+ end
220
+ end
221
+ end
169
222
  end
170
223
  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
9
  ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.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,35 @@ 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::Migrator.run(
103
+ :up,
104
+ ActiveRecord::Tasks::DatabaseTasks.migrations_paths,
105
+ ActiveRecord::Tasks::DatabaseTasks.target_version
106
+ )
100
107
  db_namespace["_dump"].invoke
101
108
  end
102
109
 
103
110
  # desc 'Runs the "down" for a given migration VERSION.'
104
- task down: [:environment, :load_config] do
111
+ task down: :load_config do
105
112
  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)
113
+
114
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
115
+
116
+ ActiveRecord::Migrator.run(
117
+ :down,
118
+ ActiveRecord::Tasks::DatabaseTasks.migrations_paths,
119
+ ActiveRecord::Tasks::DatabaseTasks.target_version
120
+ )
108
121
  db_namespace["_dump"].invoke
109
122
  end
110
123
 
111
124
  desc "Display status of migrations"
112
- task status: [:environment, :load_config] do
125
+ task status: :load_config do
113
126
  unless ActiveRecord::SchemaMigration.table_exists?
114
127
  abort "Schema migrations table does not exist yet."
115
128
  end
@@ -127,14 +140,14 @@ db_namespace = namespace :db do
127
140
  end
128
141
 
129
142
  desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
130
- task rollback: [:environment, :load_config] do
143
+ task rollback: :load_config do
131
144
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
132
145
  ActiveRecord::Migrator.rollback(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
133
146
  db_namespace["_dump"].invoke
134
147
  end
135
148
 
136
149
  # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
137
- task forward: [:environment, :load_config] do
150
+ task forward: :load_config do
138
151
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
139
152
  ActiveRecord::Migrator.forward(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
140
153
  db_namespace["_dump"].invoke
@@ -144,12 +157,12 @@ db_namespace = namespace :db do
144
157
  task reset: [ "db:drop", "db:setup" ]
145
158
 
146
159
  # desc "Retrieves the charset for the current environment's database"
147
- task charset: [:environment, :load_config] do
160
+ task charset: :load_config do
148
161
  puts ActiveRecord::Tasks::DatabaseTasks.charset_current
149
162
  end
150
163
 
151
164
  # desc "Retrieves the collation for the current environment's database"
152
- task collation: [:environment, :load_config] do
165
+ task collation: :load_config do
153
166
  begin
154
167
  puts ActiveRecord::Tasks::DatabaseTasks.collation_current
155
168
  rescue NoMethodError
@@ -158,12 +171,12 @@ db_namespace = namespace :db do
158
171
  end
159
172
 
160
173
  desc "Retrieves the current schema version number"
161
- task version: [:environment, :load_config] do
174
+ task version: :load_config do
162
175
  puts "Current version: #{ActiveRecord::Migrator.current_version}"
163
176
  end
164
177
 
165
178
  # desc "Raises an error if there are pending migrations"
166
- task abort_if_pending_migrations: [:environment, :load_config] do
179
+ task abort_if_pending_migrations: :load_config do
167
180
  pending_migrations = ActiveRecord::Migrator.open(ActiveRecord::Tasks::DatabaseTasks.migrations_paths).pending_migrations
168
181
 
169
182
  if pending_migrations.any?
@@ -186,7 +199,7 @@ db_namespace = namespace :db do
186
199
 
187
200
  namespace :fixtures do
188
201
  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
202
+ task load: :load_config do
190
203
  require "active_record/fixtures"
191
204
 
192
205
  base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
@@ -208,7 +221,7 @@ db_namespace = namespace :db do
208
221
  end
209
222
 
210
223
  # 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
224
+ task identify: :load_config do
212
225
  require "active_record/fixtures"
213
226
 
214
227
  label, id = ENV["LABEL"], ENV["ID"]
@@ -234,7 +247,7 @@ db_namespace = namespace :db do
234
247
 
235
248
  namespace :schema do
236
249
  desc "Creates a db/schema.rb file that is portable against any DB supported by Active Record"
237
- task dump: [:environment, :load_config] do
250
+ task dump: :load_config do
238
251
  require "active_record/schema_dumper"
239
252
  filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema.rb")
240
253
  File.open(filename, "w:utf-8") do |file|
@@ -244,7 +257,7 @@ db_namespace = namespace :db do
244
257
  end
245
258
 
246
259
  desc "Loads a schema.rb file into the database"
247
- task load: [:environment, :load_config, :check_protected_environments] do
260
+ task load: [:load_config, :check_protected_environments] do
248
261
  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV["SCHEMA"])
249
262
  end
250
263
 
@@ -254,14 +267,14 @@ db_namespace = namespace :db do
254
267
 
255
268
  namespace :cache do
256
269
  desc "Creates a db/schema_cache.yml file."
257
- task dump: [:environment, :load_config] do
270
+ task dump: :load_config do
258
271
  conn = ActiveRecord::Base.connection
259
272
  filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
260
273
  ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(conn, filename)
261
274
  end
262
275
 
263
276
  desc "Clears a db/schema_cache.yml file."
264
- task clear: [:environment, :load_config] do
277
+ task clear: :load_config do
265
278
  filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
266
279
  rm_f filename, verbose: false
267
280
  end
@@ -271,7 +284,7 @@ db_namespace = namespace :db do
271
284
 
272
285
  namespace :structure do
273
286
  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
287
+ task dump: :load_config do
275
288
  filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
276
289
  current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
277
290
  ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
@@ -286,7 +299,7 @@ db_namespace = namespace :db do
286
299
  end
287
300
 
288
301
  desc "Recreates the databases from the structure.sql file"
289
- task load: [:environment, :load_config, :check_protected_environments] do
302
+ task load: [:load_config, :check_protected_environments] do
290
303
  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV["SCHEMA"])
291
304
  end
292
305
 
@@ -325,12 +338,12 @@ db_namespace = namespace :db do
325
338
  end
326
339
 
327
340
  # desc "Empty the test database"
328
- task purge: %w(environment load_config check_protected_environments) do
341
+ task purge: %w(load_config check_protected_environments) do
329
342
  ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations["test"]
330
343
  end
331
344
 
332
345
  # desc 'Load the test schema'
333
- task prepare: %w(environment load_config) do
346
+ task prepare: :load_config do
334
347
  unless ActiveRecord::Base.configurations.blank?
335
348
  db_namespace["test:load"].invoke
336
349
  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)
@@ -35,8 +34,7 @@ module ActiveRecord
35
34
 
36
35
  def self.add_reflection(ar, name, reflection)
37
36
  ar.clear_reflections_cache
38
- name = name.to_s
39
- ar._reflections = ar._reflections.except(name).merge!(name => reflection)
37
+ ar._reflections = ar._reflections.merge(name.to_s => reflection)
40
38
  end
41
39
 
42
40
  def self.add_aggregate_reflection(ar, name, reflection)
@@ -139,7 +137,7 @@ module ActiveRecord
139
137
  # HasAndBelongsToManyReflection
140
138
  # ThroughReflection
141
139
  # PolymorphicReflection
142
- # RuntimeReflection
140
+ # RuntimeReflection
143
141
  class AbstractReflection # :nodoc:
144
142
  def through_reflection?
145
143
  false
@@ -155,14 +153,6 @@ module ActiveRecord
155
153
  klass.new(attributes, &block)
156
154
  end
157
155
 
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
156
  # Returns the class name for the macro.
167
157
  #
168
158
  # <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
@@ -174,7 +164,7 @@ module ActiveRecord
174
164
  JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
175
165
 
176
166
  def join_keys
177
- get_join_keys klass
167
+ @join_keys ||= get_join_keys(klass)
178
168
  end
179
169
 
180
170
  # Returns a list of scopes that should be applied for this Reflection
@@ -183,22 +173,34 @@ module ActiveRecord
183
173
  scope ? [scope] : []
184
174
  end
185
175
 
186
- def scope_chain
187
- chain.map(&:scopes)
176
+ def build_join_constraint(table, foreign_table)
177
+ key = join_keys.key
178
+ foreign_key = join_keys.foreign_key
179
+
180
+ constraint = table[key].eq(foreign_table[foreign_key])
181
+
182
+ if klass.finder_needs_type_condition?
183
+ table.create_and([constraint, klass.send(:type_condition, table)])
184
+ else
185
+ constraint
186
+ end
188
187
  end
189
- deprecate :scope_chain
190
188
 
191
- def join_scope(table)
189
+ def join_scope(table, foreign_klass)
192
190
  predicate_builder = predicate_builder(table)
193
191
  scope_chain_items = join_scopes(table, predicate_builder)
194
192
  klass_scope = klass_join_scope(table, predicate_builder)
195
193
 
196
- scope_chain_items.inject(klass_scope || scope_chain_items.shift, &:merge!)
194
+ if type
195
+ klass_scope.where!(type => foreign_klass.base_class.sti_name)
196
+ end
197
+
198
+ scope_chain_items.inject(klass_scope, &:merge!)
197
199
  end
198
200
 
199
201
  def join_scopes(table, predicate_builder) # :nodoc:
200
202
  if scope
201
- [build_scope(table, predicate_builder).instance_exec(&scope)]
203
+ [scope_for(build_scope(table, predicate_builder))]
202
204
  else
203
205
  []
204
206
  end
@@ -210,7 +212,7 @@ module ActiveRecord
210
212
  end
211
213
 
212
214
  def constraints
213
- chain.map(&:scopes).flatten
215
+ chain.flat_map(&:scopes)
214
216
  end
215
217
 
216
218
  def counter_cache_column
@@ -284,24 +286,33 @@ module ActiveRecord
284
286
  end
285
287
 
286
288
  def get_join_keys(association_klass)
287
- JoinKeys.new(join_pk(association_klass), join_fk)
289
+ JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
288
290
  end
289
291
 
290
292
  def build_scope(table, predicate_builder = predicate_builder(table))
291
293
  Relation.create(klass, table, predicate_builder)
292
294
  end
293
295
 
296
+ def join_primary_key(_)
297
+ foreign_key
298
+ end
299
+
300
+ def join_foreign_key
301
+ active_record_primary_key
302
+ end
303
+
304
+ protected
305
+ def actual_source_reflection # FIXME: this is a horrible name
306
+ self
307
+ end
308
+
294
309
  private
295
310
  def predicate_builder(table)
296
311
  PredicateBuilder.new(TableMetadata.new(klass, table))
297
312
  end
298
313
 
299
- def join_pk(_)
300
- foreign_key
301
- end
302
-
303
- def join_fk
304
- active_record_primary_key
314
+ def primary_key(klass)
315
+ klass.primary_key || raise(UnknownPrimaryKey.new(klass))
305
316
  end
306
317
  end
307
318
 
@@ -348,6 +359,17 @@ module ActiveRecord
348
359
  #
349
360
  # <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
350
361
  # <tt>has_many :clients</tt> returns the Client class
362
+ #
363
+ # class Company < ActiveRecord::Base
364
+ # has_many :clients
365
+ # end
366
+ #
367
+ # Company.reflect_on_association(:clients).klass
368
+ # # => Client
369
+ #
370
+ # <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
371
+ # a new association object. Use +build_association+ or +create_association+
372
+ # instead. This allows plugins to hook into association object creation.
351
373
  def klass
352
374
  @klass ||= compute_class(class_name)
353
375
  end
@@ -366,8 +388,8 @@ module ActiveRecord
366
388
  active_record == other_aggregation.active_record
367
389
  end
368
390
 
369
- def scope_for(klass)
370
- scope ? klass.unscoped.instance_exec(nil, &scope) : klass.unscoped
391
+ def scope_for(relation, owner = nil)
392
+ relation.instance_exec(owner, &scope) || relation
371
393
  end
372
394
 
373
395
  private
@@ -388,22 +410,6 @@ module ActiveRecord
388
410
  # Holds all the metadata about an association as it was specified in the
389
411
  # Active Record class.
390
412
  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
413
  def compute_class(name)
408
414
  active_record.send(:compute_type, name)
409
415
  end
@@ -414,31 +420,21 @@ module ActiveRecord
414
420
  def initialize(name, scope, options, active_record)
415
421
  super
416
422
  @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
417
- @foreign_type = options[:foreign_type] || "#{name}_type"
423
+ @foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
418
424
  @constructable = calculate_constructable(macro, options)
419
- @association_scope_cache = {}
420
- @scope_lock = Mutex.new
425
+ @association_scope_cache = Concurrent::Map.new
421
426
 
422
427
  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
428
+ raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
431
429
  end
432
430
  end
433
431
 
434
- def association_scope_cache(conn, owner)
432
+ def association_scope_cache(conn, owner, &block)
435
433
  key = conn.prepared_statements
436
434
  if polymorphic?
437
435
  key = [key, owner._read_attribute(@foreign_type)]
438
436
  end
439
- @association_scope_cache[key] ||= @scope_lock.synchronize {
440
- @association_scope_cache[key] ||= yield
441
- }
437
+ @association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
442
438
  end
443
439
 
444
440
  def constructable? # :nodoc:
@@ -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 = [:conditions, :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)
@@ -640,7 +630,7 @@ module ActiveRecord
640
630
  # from calling +klass+, +reflection+ will already be set to false.
641
631
  def valid_inverse_reflection?(reflection)
642
632
  reflection &&
643
- klass.name == reflection.active_record.name &&
633
+ klass <= reflection.active_record &&
644
634
  can_find_inverse_of_automatically?(reflection)
645
635
  end
646
636
 
@@ -648,9 +638,8 @@ module ActiveRecord
648
638
  # us from being able to guess the inverse automatically. First, the
649
639
  # <tt>inverse_of</tt> option cannot be set to false. Second, we must
650
640
  # 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.
641
+ # Third, we must not have options such as <tt>:foreign_key</tt>
642
+ # which prevent us from correctly guessing the inverse association.
654
643
  #
655
644
  # Anything with a scope can additionally ruin our attempt at finding an
656
645
  # inverse, so we exclude reflections with scopes.
@@ -680,10 +669,6 @@ module ActiveRecord
680
669
  def derive_join_table
681
670
  ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
682
671
  end
683
-
684
- def primary_key(klass)
685
- klass.primary_key || raise(UnknownPrimaryKey.new(klass))
686
- end
687
672
  end
688
673
 
689
674
  class HasManyReflection < AssociationReflection # :nodoc:
@@ -737,8 +722,12 @@ module ActiveRecord
737
722
  end
738
723
  end
739
724
 
740
- def join_id_for(owner) # :nodoc:
741
- owner[foreign_key]
725
+ def join_primary_key(klass)
726
+ polymorphic? ? association_primary_key(klass) : association_primary_key
727
+ end
728
+
729
+ def join_foreign_key
730
+ foreign_key
742
731
  end
743
732
 
744
733
  private
@@ -746,21 +735,9 @@ module ActiveRecord
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? ||
@@ -935,10 +907,6 @@ module ActiveRecord
935
907
  through_reflection.options
936
908
  end
937
909
 
938
- def join_id_for(owner) # :nodoc:
939
- source_reflection.join_id_for(owner)
940
- end
941
-
942
910
  def check_validity!
943
911
  if through_reflection.nil?
944
912
  raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
@@ -997,23 +965,23 @@ module ActiveRecord
997
965
  collect_join_reflections(seed + [self])
998
966
  end
999
967
 
1000
- 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
968
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
969
+ # Workaround for Ruby 2.2 "private attribute?" warning.
970
+ protected
971
+ attr_reader :delegate_reflection
1010
972
 
1011
973
  def actual_source_reflection # FIXME: this is a horrible name
1012
- source_reflection.send(:actual_source_reflection)
974
+ source_reflection.actual_source_reflection
1013
975
  end
1014
976
 
1015
- def primary_key(klass)
1016
- klass.primary_key || raise(UnknownPrimaryKey.new(klass))
977
+ private
978
+ def collect_join_reflections(seed)
979
+ a = source_reflection.add_as_source seed
980
+ if options[:source_type]
981
+ through_reflection.add_as_polymorphic_through self, a
982
+ else
983
+ through_reflection.add_as_through a
984
+ end
1017
985
  end
1018
986
 
1019
987
  def inverse_name; delegate_reflection.send(:inverse_name); end
@@ -1030,66 +998,32 @@ module ActiveRecord
1030
998
  end
1031
999
 
1032
1000
  class PolymorphicReflection < AbstractReflection # :nodoc:
1001
+ delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
1002
+
1033
1003
  def initialize(reflection, previous_reflection)
1034
1004
  @reflection = reflection
1035
1005
  @previous_reflection = previous_reflection
1036
1006
  end
1037
1007
 
1038
- def scopes
1039
- scopes = @previous_reflection.scopes
1040
- if @previous_reflection.options[:source_type]
1041
- scopes + [@previous_reflection.source_type_scope]
1042
- else
1043
- scopes
1044
- end
1045
- end
1046
-
1047
1008
  def join_scopes(table, predicate_builder) # :nodoc:
1048
1009
  scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
1049
- 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
1010
+ scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
1074
1011
  end
1075
1012
 
1076
1013
  def constraints
1077
- @reflection.constraints + [source_type_info]
1014
+ @reflection.constraints + [source_type_scope]
1078
1015
  end
1079
1016
 
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) }
1084
- end
1085
-
1086
- def get_join_keys(association_klass)
1087
- @reflection.get_join_keys(association_klass)
1088
- end
1017
+ private
1018
+ def source_type_scope
1019
+ type = @previous_reflection.foreign_type
1020
+ source_type = @previous_reflection.options[:source_type]
1021
+ lambda { |object| where(type => source_type) }
1022
+ end
1089
1023
  end
1090
1024
 
1091
- class RuntimeReflection < PolymorphicReflection # :nodoc:
1092
- attr_accessor :next
1025
+ class RuntimeReflection < AbstractReflection # :nodoc:
1026
+ delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
1093
1027
 
1094
1028
  def initialize(reflection, association)
1095
1029
  @reflection = reflection
@@ -1100,24 +1034,8 @@ module ActiveRecord
1100
1034
  @association.klass
1101
1035
  end
1102
1036
 
1103
- def 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)
1037
+ def aliased_table
1038
+ @aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
1121
1039
  end
1122
1040
 
1123
1041
  def all_includes; yield; end