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
@@ -26,7 +26,7 @@ The Product class is automatically mapped to the table named "products",
26
26
  which might look like this:
27
27
 
28
28
  CREATE TABLE products (
29
- id int NOT NULL auto_increment,
29
+ id bigint NOT NULL auto_increment,
30
30
  name varchar(255),
31
31
  PRIMARY KEY (id)
32
32
  );
@@ -162,7 +162,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
162
162
  == Philosophy
163
163
 
164
164
  Active Record is an implementation of the object-relational mapping (ORM)
165
- pattern[http://www.martinfowler.com/eaaCatalog/activeRecord.html] by the same
165
+ pattern[https://www.martinfowler.com/eaaCatalog/activeRecord.html] by the same
166
166
  name described by Martin Fowler:
167
167
 
168
168
  "An object that wraps a row in a database table or view,
@@ -199,7 +199,7 @@ Source code can be downloaded as part of the Rails project on GitHub:
199
199
 
200
200
  Active Record is released under the MIT license:
201
201
 
202
- * http://www.opensource.org/licenses/MIT
202
+ * https://opensource.org/licenses/MIT
203
203
 
204
204
 
205
205
  == Support
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record"
2
4
  require "benchmark/ips"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record"
2
4
 
3
5
  class Person < ActiveRecord::Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #--
2
4
  # Copyright (c) 2004-2017 David Heinemeier Hansson
3
5
  #
@@ -25,14 +27,14 @@ require "active_support"
25
27
  require "active_support/rails"
26
28
  require "active_model"
27
29
  require "arel"
30
+ require "yaml"
28
31
 
29
32
  require "active_record/version"
30
- require "active_record/attribute_set"
33
+ require "active_model/attribute_set"
31
34
 
32
35
  module ActiveRecord
33
36
  extend ActiveSupport::Autoload
34
37
 
35
- autoload :Attribute
36
38
  autoload :Base
37
39
  autoload :Callbacks
38
40
  autoload :Core
@@ -102,6 +104,7 @@ module ActiveRecord
102
104
 
103
105
  autoload :Result
104
106
  autoload :TableMetadata
107
+ autoload :Type
105
108
  end
106
109
 
107
110
  module Coders
@@ -177,5 +180,9 @@ ActiveSupport.on_load(:active_record) do
177
180
  end
178
181
 
179
182
  ActiveSupport.on_load(:i18n) do
180
- I18n.load_path << File.dirname(__FILE__) + "/active_record/locale/en.yml"
183
+ I18n.load_path << File.expand_path("active_record/locale/en.yml", __dir__)
181
184
  end
185
+
186
+ YAML.load_tags["!ruby/object:ActiveRecord::AttributeSet"] = "ActiveModel::AttributeSet"
187
+ YAML.load_tags["!ruby/object:ActiveRecord::Attribute::FromDatabase"] = "ActiveModel::Attribute::FromDatabase"
188
+ YAML.load_tags["!ruby/object:ActiveRecord::LazyAttributeHash"] = "ActiveModel::LazyAttributeHash"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # See ActiveRecord::Aggregations::ClassMethods for documentation
3
5
  module Aggregations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class AssociationRelation < Relation
3
5
  def initialize(klass, table, predicate_builder, association)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/enumerable"
2
4
  require "active_support/core_ext/string/conversions"
3
5
  require "active_support/core_ext/module/remove_method"
@@ -138,26 +140,6 @@ module ActiveRecord
138
140
  class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
139
141
  end
140
142
 
141
- class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc:
142
- def initialize(owner = nil, reflection = nil)
143
- if owner && reflection
144
- super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.")
145
- else
146
- super("Cannot associate new records.")
147
- end
148
- end
149
- end
150
-
151
- class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
152
- def initialize(owner = nil, reflection = nil)
153
- if owner && reflection
154
- super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.")
155
- else
156
- super("Cannot dissociate new records.")
157
- end
158
- end
159
- end
160
-
161
143
  class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
162
144
  def initialize(owner = nil, reflection = nil)
163
145
  if owner && reflection
@@ -187,16 +169,6 @@ module ActiveRecord
187
169
  end
188
170
  end
189
171
 
190
- class ReadOnlyAssociation < ActiveRecordError #:nodoc:
191
- def initialize(reflection = nil)
192
- if reflection
193
- super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.")
194
- else
195
- super("Read-only reflection error.")
196
- end
197
- end
198
- end
199
-
200
172
  # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
201
173
  # (has_many, has_one) when there is at least 1 child associated instance.
202
174
  # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
@@ -481,14 +453,14 @@ module ActiveRecord
481
453
  # The tables for these classes could look something like:
482
454
  #
483
455
  # CREATE TABLE users (
484
- # id int NOT NULL auto_increment,
485
- # account_id int default NULL,
456
+ # id bigint NOT NULL auto_increment,
457
+ # account_id bigint default NULL,
486
458
  # name varchar default NULL,
487
459
  # PRIMARY KEY (id)
488
460
  # )
489
461
  #
490
462
  # CREATE TABLE accounts (
491
- # id int NOT NULL auto_increment,
463
+ # id bigint NOT NULL auto_increment,
492
464
  # name varchar default NULL,
493
465
  # PRIMARY KEY (id)
494
466
  # )
@@ -555,9 +527,8 @@ module ActiveRecord
555
527
  # has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
556
528
  # end
557
529
  #
558
- # Note: Joining, eager loading and preloading of these associations is not fully possible.
530
+ # Note: Joining, eager loading and preloading of these associations is not possible.
559
531
  # These operations happen before instance creation and the scope will be called with a +nil+ argument.
560
- # This can lead to unexpected behavior and is deprecated.
561
532
  #
562
533
  # == Association callbacks
563
534
  #
@@ -848,7 +819,7 @@ module ActiveRecord
848
819
  # project.milestones # fetches milestones from the database
849
820
  # project.milestones.size # uses the milestone cache
850
821
  # project.milestones.empty? # uses the milestone cache
851
- # project.milestones(true).size # fetches milestones from the database
822
+ # project.milestones.reload.size # fetches milestones from the database
852
823
  # project.milestones # uses the milestone cache
853
824
  #
854
825
  # == Eager loading of associations
@@ -1189,7 +1160,7 @@ module ActiveRecord
1189
1160
  # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1190
1161
  # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
1191
1162
  #
1192
- # [collection(force_reload = false)]
1163
+ # [collection]
1193
1164
  # Returns a Relation of all the associated objects.
1194
1165
  # An empty Relation is returned if none are found.
1195
1166
  # [collection<<(object, ...)]
@@ -1398,7 +1369,7 @@ module ActiveRecord
1398
1369
  # has_many :tags, as: :taggable
1399
1370
  # has_many :reports, -> { readonly }
1400
1371
  # has_many :subscribers, through: :subscriptions, source: :user
1401
- def has_many(name, scope = nil, options = {}, &extension)
1372
+ def has_many(name, scope = nil, **options, &extension)
1402
1373
  reflection = Builder::HasMany.build(self, name, scope, options, &extension)
1403
1374
  Reflection.add_reflection self, name, reflection
1404
1375
  end
@@ -1532,7 +1503,7 @@ module ActiveRecord
1532
1503
  # has_one :club, through: :membership
1533
1504
  # has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
1534
1505
  # has_one :credit_card, required: true
1535
- def has_one(name, scope = nil, options = {})
1506
+ def has_one(name, scope = nil, **options)
1536
1507
  reflection = Builder::HasOne.build(self, name, scope, options)
1537
1508
  Reflection.add_reflection self, name, reflection
1538
1509
  end
@@ -1676,7 +1647,7 @@ module ActiveRecord
1676
1647
  # belongs_to :company, touch: :employees_last_updated_at
1677
1648
  # belongs_to :user, optional: true
1678
1649
  # belongs_to :account, default: -> { company.account }
1679
- def belongs_to(name, scope = nil, options = {})
1650
+ def belongs_to(name, scope = nil, **options)
1680
1651
  reflection = Builder::BelongsTo.build(self, name, scope, options)
1681
1652
  Reflection.add_reflection self, name, reflection
1682
1653
  end
@@ -1846,7 +1817,7 @@ module ActiveRecord
1846
1817
 
1847
1818
  builder = Builder::HasAndBelongsToMany.new name, self, options
1848
1819
 
1849
- join_model = ActiveSupport::Deprecation.silence { builder.through_model }
1820
+ join_model = builder.through_model
1850
1821
 
1851
1822
  const_set join_model.name, join_model
1852
1823
  private_constant join_model.name
@@ -1875,7 +1846,7 @@ module ActiveRecord
1875
1846
  hm_options[k] = options[k] if options.key? k
1876
1847
  end
1877
1848
 
1878
- ActiveSupport::Deprecation.silence { has_many name, scope, hm_options, &extension }
1849
+ has_many name, scope, hm_options, &extension
1879
1850
  _reflections[name.to_s].parent_reflection = habtm_reflection
1880
1851
  end
1881
1852
  end
@@ -1,41 +1,39 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/string/conversions"
2
4
 
3
5
  module ActiveRecord
4
6
  module Associations
5
7
  # Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
6
8
  class AliasTracker # :nodoc:
7
- attr_reader :aliases
8
-
9
- def self.create(connection, initial_table)
10
- aliases = Hash.new(0)
11
- aliases[initial_table] = 1
12
- new(connection, aliases)
13
- end
14
-
15
- def self.create_with_joins(connection, initial_table, joins)
9
+ def self.create(connection, initial_table, joins)
16
10
  if joins.empty?
17
- create(connection, initial_table)
11
+ aliases = Hash.new(0)
18
12
  else
19
13
  aliases = Hash.new { |h, k|
20
14
  h[k] = initial_count_for(connection, k, joins)
21
15
  }
22
- aliases[initial_table] = 1
23
- new(connection, aliases)
24
16
  end
17
+ aliases[initial_table] = 1
18
+ new(connection, aliases)
25
19
  end
26
20
 
27
21
  def self.initial_count_for(connection, name, table_joins)
28
- # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase
29
- quoted_name = connection.quote_table_name(name).downcase
22
+ quoted_name = nil
30
23
 
31
24
  counts = table_joins.map do |join|
32
25
  if join.is_a?(Arel::Nodes::StringJoin)
26
+ # quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
27
+ quoted_name ||= connection.quote_table_name(name)
28
+
33
29
  # Table names + table aliases
34
- join.left.downcase.scan(
35
- /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/
30
+ join.left.scan(
31
+ /JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
36
32
  ).size
37
33
  elsif join.respond_to? :left
38
- join.left.table_name == name ? 1 : 0
34
+ join.left.name == name ? 1 : 0
35
+ elsif join.is_a?(Hash)
36
+ join.fetch(name, 0)
39
37
  else
40
38
  # this branch is reached by two tests:
41
39
  #
@@ -79,6 +77,8 @@ module ActiveRecord
79
77
  end
80
78
  end
81
79
 
80
+ attr_reader :aliases
81
+
82
82
  private
83
83
 
84
84
  def truncate(name)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/array/wrap"
2
4
 
3
5
  module ActiveRecord
@@ -30,14 +32,6 @@ module ActiveRecord
30
32
  reset_scope
31
33
  end
32
34
 
33
- # Returns the name of the table of the associated class:
34
- #
35
- # post.comments.aliased_table_name # => "comments"
36
- #
37
- def aliased_table_name
38
- klass.table_name
39
- end
40
-
41
35
  # Resets the \loaded flag to +false+ and sets the \target to +nil+.
42
36
  def reset
43
37
  @loaded = false
@@ -94,7 +88,7 @@ module ActiveRecord
94
88
  # actually gets built.
95
89
  def association_scope
96
90
  if klass
97
- @association_scope ||= AssociationScope.scope(self, klass.connection)
91
+ @association_scope ||= AssociationScope.scope(self)
98
92
  end
99
93
  end
100
94
 
@@ -136,8 +130,8 @@ module ActiveRecord
136
130
  def extensions
137
131
  extensions = klass.default_extensions | reflection.extensions
138
132
 
139
- if scope = reflection.scope
140
- extensions |= klass.unscoped.instance_exec(owner, &scope).extensions
133
+ if reflection.scope
134
+ extensions |= reflection.scope_for(klass.unscoped, owner).extensions
141
135
  end
142
136
 
143
137
  extensions
@@ -162,14 +156,6 @@ module ActiveRecord
162
156
  reset
163
157
  end
164
158
 
165
- def interpolate(sql, record = nil)
166
- if sql.respond_to?(:to_proc)
167
- owner.instance_exec(record, &sql)
168
- else
169
- sql
170
- end
171
- end
172
-
173
159
  # We can't dump @reflection since it contains the scope proc
174
160
  def marshal_dump
175
161
  ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
@@ -187,8 +173,8 @@ module ActiveRecord
187
173
  skip_assign = [reflection.foreign_key, reflection.type].compact
188
174
  assigned_keys = record.changed_attribute_names_to_save
189
175
  assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
190
- attributes = create_scope.except(*(assigned_keys - skip_assign))
191
- record.assign_attributes(attributes)
176
+ attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
177
+ record.send(:_assign_attributes, attributes) if attributes.any?
192
178
  set_inverse_instance(record)
193
179
  end
194
180
 
@@ -201,6 +187,9 @@ module ActiveRecord
201
187
  end
202
188
 
203
189
  private
190
+ def scope_for_create
191
+ scope.scope_for_create
192
+ end
204
193
 
205
194
  def find_target?
206
195
  !loaded? && (!owner.new_record? || foreign_key_present?) && klass
@@ -284,7 +273,7 @@ module ActiveRecord
284
273
  end
285
274
 
286
275
  # Returns true if statement cache should be skipped on the association reader.
287
- def skip_statement_cache?
276
+ def skip_statement_cache?(scope)
288
277
  reflection.has_scope? ||
289
278
  scope.eager_loading? ||
290
279
  klass.scope_attributes? ||
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Associations
3
5
  class AssociationScope #:nodoc:
4
- def self.scope(association, connection)
5
- INSTANCE.scope(association, connection)
6
+ def self.scope(association)
7
+ INSTANCE.scope(association)
6
8
  end
7
9
 
8
10
  def self.create(&block)
@@ -16,20 +18,15 @@ module ActiveRecord
16
18
 
17
19
  INSTANCE = create
18
20
 
19
- def scope(association, connection)
21
+ def scope(association)
20
22
  klass = association.klass
21
23
  reflection = association.reflection
22
24
  scope = klass.unscoped
23
25
  owner = association.owner
24
- alias_tracker = AliasTracker.create connection, association.klass.table_name
25
- chain_head, chain_tail = get_chain(reflection, association, alias_tracker)
26
+ chain = get_chain(reflection, association, scope.alias_tracker)
26
27
 
27
28
  scope.extending! reflection.extensions
28
- add_constraints(scope, owner, reflection, chain_head, chain_tail)
29
- end
30
-
31
- def join_type
32
- Arel::Nodes::InnerJoin
29
+ add_constraints(scope, owner, chain)
33
30
  end
34
31
 
35
32
  def self.get_bind_values(owner, chain)
@@ -57,14 +54,15 @@ module ActiveRecord
57
54
 
58
55
  private
59
56
  def join(table, constraint)
60
- table.create_join(table, table.create_on(constraint), join_type)
57
+ table.create_join(table, table.create_on(constraint))
61
58
  end
62
59
 
63
- def last_chain_scope(scope, table, reflection, owner)
60
+ def last_chain_scope(scope, reflection, owner)
64
61
  join_keys = reflection.join_keys
65
62
  key = join_keys.key
66
63
  foreign_key = join_keys.foreign_key
67
64
 
65
+ table = reflection.aliased_table
68
66
  value = transform_value(owner[foreign_key])
69
67
  scope = apply_scope(scope, table, key, value)
70
68
 
@@ -80,11 +78,13 @@ module ActiveRecord
80
78
  value_transformation.call(value)
81
79
  end
82
80
 
83
- def next_chain_scope(scope, table, reflection, foreign_table, next_reflection)
81
+ def next_chain_scope(scope, reflection, next_reflection)
84
82
  join_keys = reflection.join_keys
85
83
  key = join_keys.key
86
84
  foreign_key = join_keys.foreign_key
87
85
 
86
+ table = reflection.aliased_table
87
+ foreign_table = next_reflection.aliased_table
88
88
  constraint = table[key].eq(foreign_table[foreign_key])
89
89
 
90
90
  if reflection.type
@@ -96,12 +96,11 @@ module ActiveRecord
96
96
  end
97
97
 
98
98
  class ReflectionProxy < SimpleDelegator # :nodoc:
99
- attr_accessor :next
100
- attr_reader :alias_name
99
+ attr_reader :aliased_table
101
100
 
102
- def initialize(reflection, alias_name)
101
+ def initialize(reflection, aliased_table)
103
102
  super(reflection)
104
- @alias_name = alias_name
103
+ @aliased_table = aliased_table
105
104
  end
106
105
 
107
106
  def all_includes; nil; end
@@ -109,42 +108,33 @@ module ActiveRecord
109
108
 
110
109
  def get_chain(reflection, association, tracker)
111
110
  name = reflection.name
112
- runtime_reflection = Reflection::RuntimeReflection.new(reflection, association)
113
- previous_reflection = runtime_reflection
111
+ chain = [Reflection::RuntimeReflection.new(reflection, association)]
114
112
  reflection.chain.drop(1).each do |refl|
115
- alias_name = tracker.aliased_table_for(
113
+ aliased_table = tracker.aliased_table_for(
116
114
  refl.table_name,
117
115
  refl.alias_candidate(name),
118
116
  refl.klass.type_caster
119
117
  )
120
- proxy = ReflectionProxy.new(refl, alias_name)
121
- previous_reflection.next = proxy
122
- previous_reflection = proxy
118
+ chain << ReflectionProxy.new(refl, aliased_table)
123
119
  end
124
- [runtime_reflection, previous_reflection]
120
+ chain
125
121
  end
126
122
 
127
- def add_constraints(scope, owner, refl, chain_head, chain_tail)
128
- owner_reflection = chain_tail
129
- table = owner_reflection.alias_name
130
- scope = last_chain_scope(scope, table, owner_reflection, owner)
131
-
132
- reflection = chain_head
133
- while reflection
134
- table = reflection.alias_name
135
- next_reflection = reflection.next
123
+ def add_constraints(scope, owner, chain)
124
+ scope = last_chain_scope(scope, chain.last, owner)
136
125
 
137
- unless reflection == chain_tail
138
- foreign_table = next_reflection.alias_name
139
- scope = next_chain_scope(scope, table, reflection, foreign_table, next_reflection)
140
- end
126
+ chain.each_cons(2) do |reflection, next_reflection|
127
+ scope = next_chain_scope(scope, reflection, next_reflection)
128
+ end
141
129
 
130
+ chain_head = chain.first
131
+ chain.reverse_each do |reflection|
142
132
  # Exclude the scope of the association itself, because that
143
133
  # was already merged in the #scope method.
144
134
  reflection.constraints.each do |scope_chain_item|
145
- item = eval_scope(reflection.klass, table, scope_chain_item, owner)
135
+ item = eval_scope(reflection, scope_chain_item, owner)
146
136
 
147
- if scope_chain_item == refl.scope
137
+ if scope_chain_item == chain_head.scope
148
138
  scope.merge! item.except(:where, :includes)
149
139
  end
150
140
 
@@ -156,8 +146,6 @@ module ActiveRecord
156
146
  scope.where_clause += item.where_clause
157
147
  scope.order_values |= item.order_values
158
148
  end
159
-
160
- reflection = next_reflection
161
149
  end
162
150
 
163
151
  scope
@@ -171,9 +159,9 @@ module ActiveRecord
171
159
  end
172
160
  end
173
161
 
174
- def eval_scope(klass, table, scope, owner)
175
- predicate_builder = PredicateBuilder.new(TableMetadata.new(klass, table))
176
- ActiveRecord::Relation.create(klass, table, predicate_builder).instance_exec(owner, &scope)
162
+ def eval_scope(reflection, scope, owner)
163
+ relation = reflection.build_scope(reflection.aliased_table)
164
+ relation.instance_exec(owner, &scope) || relation
177
165
  end
178
166
  end
179
167
  end