activerecord 5.2.3.rc1 → 6.0.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 (240) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +326 -696
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +2 -1
  7. data/lib/active_record/aggregations.rb +4 -2
  8. data/lib/active_record/associations.rb +16 -12
  9. data/lib/active_record/associations/association.rb +35 -19
  10. data/lib/active_record/associations/association_scope.rb +4 -6
  11. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  13. data/lib/active_record/associations/builder/belongs_to.rb +14 -50
  14. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
  16. data/lib/active_record/associations/collection_association.rb +11 -25
  17. data/lib/active_record/associations/collection_proxy.rb +32 -6
  18. data/lib/active_record/associations/foreign_association.rb +7 -0
  19. data/lib/active_record/associations/has_many_association.rb +1 -1
  20. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  21. data/lib/active_record/associations/has_one_association.rb +28 -30
  22. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  23. data/lib/active_record/associations/join_dependency.rb +15 -20
  24. data/lib/active_record/associations/join_dependency/join_association.rb +6 -0
  25. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  26. data/lib/active_record/associations/preloader.rb +31 -28
  27. data/lib/active_record/associations/preloader/association.rb +1 -2
  28. data/lib/active_record/associations/singular_association.rb +2 -16
  29. data/lib/active_record/attribute_assignment.rb +7 -10
  30. data/lib/active_record/attribute_methods.rb +34 -56
  31. data/lib/active_record/attribute_methods/dirty.rb +64 -26
  32. data/lib/active_record/attribute_methods/primary_key.rb +8 -7
  33. data/lib/active_record/attribute_methods/read.rb +16 -48
  34. data/lib/active_record/attribute_methods/serialization.rb +1 -1
  35. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
  36. data/lib/active_record/attribute_methods/write.rb +15 -16
  37. data/lib/active_record/autosave_association.rb +1 -1
  38. data/lib/active_record/base.rb +2 -2
  39. data/lib/active_record/callbacks.rb +3 -17
  40. data/lib/active_record/collection_cache_key.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +10 -14
  42. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  43. data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
  44. data/lib/active_record/connection_adapters/abstract/query_cache.rb +14 -11
  45. data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
  46. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
  47. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
  48. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
  49. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +40 -26
  50. data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
  51. data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
  52. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
  53. data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
  54. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
  55. data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
  56. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  57. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
  58. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
  59. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
  60. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
  61. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
  62. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  63. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  64. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
  65. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
  66. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
  67. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  68. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  69. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
  70. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
  71. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
  72. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
  73. data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
  74. data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
  75. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
  76. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
  77. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +93 -60
  78. data/lib/active_record/connection_handling.rb +132 -26
  79. data/lib/active_record/core.rb +76 -43
  80. data/lib/active_record/counter_cache.rb +4 -29
  81. data/lib/active_record/database_configurations.rb +184 -0
  82. data/lib/active_record/database_configurations/database_config.rb +37 -0
  83. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  84. data/lib/active_record/database_configurations/url_config.rb +74 -0
  85. data/lib/active_record/enum.rb +22 -7
  86. data/lib/active_record/errors.rb +24 -21
  87. data/lib/active_record/explain.rb +1 -1
  88. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  89. data/lib/active_record/fixture_set/render_context.rb +17 -0
  90. data/lib/active_record/fixture_set/table_row.rb +153 -0
  91. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  92. data/lib/active_record/fixtures.rb +140 -472
  93. data/lib/active_record/gem_version.rb +4 -4
  94. data/lib/active_record/inheritance.rb +12 -2
  95. data/lib/active_record/integration.rb +56 -16
  96. data/lib/active_record/internal_metadata.rb +5 -1
  97. data/lib/active_record/locking/optimistic.rb +2 -2
  98. data/lib/active_record/locking/pessimistic.rb +3 -3
  99. data/lib/active_record/log_subscriber.rb +7 -26
  100. data/lib/active_record/migration.rb +38 -37
  101. data/lib/active_record/migration/command_recorder.rb +35 -5
  102. data/lib/active_record/migration/compatibility.rb +34 -16
  103. data/lib/active_record/model_schema.rb +30 -9
  104. data/lib/active_record/nested_attributes.rb +2 -2
  105. data/lib/active_record/no_touching.rb +7 -0
  106. data/lib/active_record/persistence.rb +18 -7
  107. data/lib/active_record/query_cache.rb +11 -4
  108. data/lib/active_record/querying.rb +19 -11
  109. data/lib/active_record/railtie.rb +71 -42
  110. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  111. data/lib/active_record/railties/controller_runtime.rb +30 -35
  112. data/lib/active_record/railties/databases.rake +94 -43
  113. data/lib/active_record/reflection.rb +46 -34
  114. data/lib/active_record/relation.rb +150 -69
  115. data/lib/active_record/relation/batches.rb +13 -10
  116. data/lib/active_record/relation/calculations.rb +34 -23
  117. data/lib/active_record/relation/delegation.rb +4 -13
  118. data/lib/active_record/relation/finder_methods.rb +12 -25
  119. data/lib/active_record/relation/merger.rb +2 -6
  120. data/lib/active_record/relation/predicate_builder.rb +4 -6
  121. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  122. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  123. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  124. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  125. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  126. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  127. data/lib/active_record/relation/query_attribute.rb +15 -12
  128. data/lib/active_record/relation/query_methods.rb +26 -47
  129. data/lib/active_record/relation/where_clause.rb +4 -0
  130. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  131. data/lib/active_record/result.rb +30 -11
  132. data/lib/active_record/sanitization.rb +2 -39
  133. data/lib/active_record/schema.rb +1 -10
  134. data/lib/active_record/schema_dumper.rb +12 -6
  135. data/lib/active_record/schema_migration.rb +4 -0
  136. data/lib/active_record/scoping.rb +9 -8
  137. data/lib/active_record/scoping/default.rb +8 -1
  138. data/lib/active_record/scoping/named.rb +10 -14
  139. data/lib/active_record/statement_cache.rb +30 -3
  140. data/lib/active_record/store.rb +39 -8
  141. data/lib/active_record/table_metadata.rb +1 -4
  142. data/lib/active_record/tasks/database_tasks.rb +89 -23
  143. data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
  144. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
  145. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
  146. data/lib/active_record/test_databases.rb +38 -0
  147. data/lib/active_record/test_fixtures.rb +224 -0
  148. data/lib/active_record/timestamp.rb +4 -6
  149. data/lib/active_record/transactions.rb +2 -21
  150. data/lib/active_record/translation.rb +1 -1
  151. data/lib/active_record/type.rb +3 -4
  152. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  153. data/lib/active_record/type_caster/connection.rb +1 -6
  154. data/lib/active_record/type_caster/map.rb +1 -4
  155. data/lib/active_record/validations/uniqueness.rb +13 -25
  156. data/lib/arel.rb +44 -0
  157. data/lib/arel/alias_predication.rb +9 -0
  158. data/lib/arel/attributes.rb +22 -0
  159. data/lib/arel/attributes/attribute.rb +37 -0
  160. data/lib/arel/collectors/bind.rb +24 -0
  161. data/lib/arel/collectors/composite.rb +31 -0
  162. data/lib/arel/collectors/plain_string.rb +20 -0
  163. data/lib/arel/collectors/sql_string.rb +20 -0
  164. data/lib/arel/collectors/substitute_binds.rb +28 -0
  165. data/lib/arel/crud.rb +42 -0
  166. data/lib/arel/delete_manager.rb +18 -0
  167. data/lib/arel/errors.rb +9 -0
  168. data/lib/arel/expressions.rb +29 -0
  169. data/lib/arel/factory_methods.rb +49 -0
  170. data/lib/arel/insert_manager.rb +49 -0
  171. data/lib/arel/math.rb +45 -0
  172. data/lib/arel/nodes.rb +67 -0
  173. data/lib/arel/nodes/and.rb +32 -0
  174. data/lib/arel/nodes/ascending.rb +23 -0
  175. data/lib/arel/nodes/binary.rb +52 -0
  176. data/lib/arel/nodes/bind_param.rb +36 -0
  177. data/lib/arel/nodes/case.rb +55 -0
  178. data/lib/arel/nodes/casted.rb +50 -0
  179. data/lib/arel/nodes/count.rb +12 -0
  180. data/lib/arel/nodes/delete_statement.rb +45 -0
  181. data/lib/arel/nodes/descending.rb +23 -0
  182. data/lib/arel/nodes/equality.rb +18 -0
  183. data/lib/arel/nodes/extract.rb +24 -0
  184. data/lib/arel/nodes/false.rb +16 -0
  185. data/lib/arel/nodes/full_outer_join.rb +8 -0
  186. data/lib/arel/nodes/function.rb +44 -0
  187. data/lib/arel/nodes/grouping.rb +8 -0
  188. data/lib/arel/nodes/in.rb +8 -0
  189. data/lib/arel/nodes/infix_operation.rb +80 -0
  190. data/lib/arel/nodes/inner_join.rb +8 -0
  191. data/lib/arel/nodes/insert_statement.rb +37 -0
  192. data/lib/arel/nodes/join_source.rb +20 -0
  193. data/lib/arel/nodes/matches.rb +18 -0
  194. data/lib/arel/nodes/named_function.rb +23 -0
  195. data/lib/arel/nodes/node.rb +50 -0
  196. data/lib/arel/nodes/node_expression.rb +13 -0
  197. data/lib/arel/nodes/outer_join.rb +8 -0
  198. data/lib/arel/nodes/over.rb +15 -0
  199. data/lib/arel/nodes/regexp.rb +16 -0
  200. data/lib/arel/nodes/right_outer_join.rb +8 -0
  201. data/lib/arel/nodes/select_core.rb +63 -0
  202. data/lib/arel/nodes/select_statement.rb +41 -0
  203. data/lib/arel/nodes/sql_literal.rb +16 -0
  204. data/lib/arel/nodes/string_join.rb +11 -0
  205. data/lib/arel/nodes/table_alias.rb +27 -0
  206. data/lib/arel/nodes/terminal.rb +16 -0
  207. data/lib/arel/nodes/true.rb +16 -0
  208. data/lib/arel/nodes/unary.rb +44 -0
  209. data/lib/arel/nodes/unary_operation.rb +20 -0
  210. data/lib/arel/nodes/unqualified_column.rb +22 -0
  211. data/lib/arel/nodes/update_statement.rb +41 -0
  212. data/lib/arel/nodes/values.rb +16 -0
  213. data/lib/arel/nodes/values_list.rb +24 -0
  214. data/lib/arel/nodes/window.rb +126 -0
  215. data/lib/arel/nodes/with.rb +11 -0
  216. data/lib/arel/order_predications.rb +13 -0
  217. data/lib/arel/predications.rb +257 -0
  218. data/lib/arel/select_manager.rb +271 -0
  219. data/lib/arel/table.rb +110 -0
  220. data/lib/arel/tree_manager.rb +72 -0
  221. data/lib/arel/update_manager.rb +34 -0
  222. data/lib/arel/visitors.rb +20 -0
  223. data/lib/arel/visitors/depth_first.rb +199 -0
  224. data/lib/arel/visitors/dot.rb +292 -0
  225. data/lib/arel/visitors/ibm_db.rb +21 -0
  226. data/lib/arel/visitors/informix.rb +56 -0
  227. data/lib/arel/visitors/mssql.rb +143 -0
  228. data/lib/arel/visitors/mysql.rb +83 -0
  229. data/lib/arel/visitors/oracle.rb +159 -0
  230. data/lib/arel/visitors/oracle12.rb +67 -0
  231. data/lib/arel/visitors/postgresql.rb +116 -0
  232. data/lib/arel/visitors/sqlite.rb +39 -0
  233. data/lib/arel/visitors/to_sql.rb +913 -0
  234. data/lib/arel/visitors/visitor.rb +42 -0
  235. data/lib/arel/visitors/where_sql.rb +23 -0
  236. data/lib/arel/window_predications.rb +9 -0
  237. data/lib/rails/generators/active_record/migration.rb +14 -1
  238. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  239. data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
  240. metadata +101 -23
@@ -14,38 +14,39 @@ module ActiveRecord
14
14
  [key] if key
15
15
  end
16
16
 
17
- # Returns the primary key value.
17
+ # Returns the primary key column's value.
18
18
  def id
19
19
  sync_with_transaction_state
20
20
  primary_key = self.class.primary_key
21
21
  _read_attribute(primary_key) if primary_key
22
22
  end
23
23
 
24
- # Sets the primary key value.
24
+ # Sets the primary key column's value.
25
25
  def id=(value)
26
26
  sync_with_transaction_state
27
27
  primary_key = self.class.primary_key
28
28
  _write_attribute(primary_key, value) if primary_key
29
29
  end
30
30
 
31
- # Queries the primary key value.
31
+ # Queries the primary key column's value.
32
32
  def id?
33
33
  sync_with_transaction_state
34
34
  query_attribute(self.class.primary_key)
35
35
  end
36
36
 
37
- # Returns the primary key value before type cast.
37
+ # Returns the primary key column's value before type cast.
38
38
  def id_before_type_cast
39
39
  sync_with_transaction_state
40
40
  read_attribute_before_type_cast(self.class.primary_key)
41
41
  end
42
42
 
43
- # Returns the primary key previous value.
43
+ # Returns the primary key column's previous value.
44
44
  def id_was
45
45
  sync_with_transaction_state
46
46
  attribute_was(self.class.primary_key)
47
47
  end
48
48
 
49
+ # Returns the primary key column's value from the database.
49
50
  def id_in_database
50
51
  sync_with_transaction_state
51
52
  attribute_in_database(self.class.primary_key)
@@ -83,7 +84,7 @@ module ActiveRecord
83
84
  end
84
85
 
85
86
  def reset_primary_key #:nodoc:
86
- if self == base_class
87
+ if base_class?
87
88
  self.primary_key = get_primary_key(base_class.name)
88
89
  else
89
90
  self.primary_key = base_class.primary_key
@@ -131,7 +132,7 @@ module ActiveRecord
131
132
  def suppress_composite_primary_key(pk)
132
133
  return pk unless pk.is_a?(Array)
133
134
 
134
- warn <<-WARNING.strip_heredoc
135
+ warn <<~WARNING
135
136
  WARNING: Active Record does not support composite primary key.
136
137
 
137
138
  #{table_name} has composite primary key. Composite primary key is ignored.
@@ -8,42 +8,19 @@ module ActiveRecord
8
8
  module ClassMethods # :nodoc:
9
9
  private
10
10
 
11
- # We want to generate the methods via module_eval rather than
12
- # define_method, because define_method is slower on dispatch.
13
- # Evaluating many similar methods may use more memory as the instruction
14
- # sequences are duplicated and cached (in MRI). define_method may
15
- # be slower on dispatch, but if you're careful about the closure
16
- # created, then define_method will consume much less memory.
17
- #
18
- # But sometimes the database might return columns with
19
- # characters that are not allowed in normal method names (like
20
- # 'my_column(omg)'. So to work around this we first define with
21
- # the __temp__ identifier, and then use alias method to rename
22
- # it to what we want.
23
- #
24
- # We are also defining a constant to hold the frozen string of
25
- # the attribute name. Using a constant means that we do not have
26
- # to allocate an object on each call to the attribute method.
27
- # Making it frozen means that it doesn't get duped when used to
28
- # key the @attributes in read_attribute.
29
11
  def define_method_attribute(name)
30
- safe_name = name.unpack("h*".freeze).first
31
- temp_method = "__temp__#{safe_name}"
32
-
33
- ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
34
12
  sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
35
13
 
36
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
37
- def #{temp_method}
38
- #{sync_with_transaction_state}
39
- name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
40
- _read_attribute(name) { |n| missing_attribute(n, caller) }
41
- end
42
- STR
43
-
44
- generated_attribute_methods.module_eval do
45
- alias_method name, temp_method
46
- undef_method temp_method
14
+ ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
15
+ generated_attribute_methods, name
16
+ ) do |temp_method_name, attr_name_expr|
17
+ generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
18
+ def #{temp_method_name}
19
+ #{sync_with_transaction_state}
20
+ name = #{attr_name_expr}
21
+ _read_attribute(name) { |n| missing_attribute(n, caller) }
22
+ end
23
+ RUBY
47
24
  end
48
25
  end
49
26
  end
@@ -52,30 +29,21 @@ module ActiveRecord
52
29
  # it has been typecast (for example, "2004-12-12" in a date column is cast
53
30
  # to a date object, like Date.new(2004, 12, 12)).
54
31
  def read_attribute(attr_name, &block)
55
- name = if self.class.attribute_alias?(attr_name)
56
- self.class.attribute_alias(attr_name).to_s
57
- else
58
- attr_name.to_s
32
+ name = attr_name.to_s
33
+ if self.class.attribute_alias?(name)
34
+ name = self.class.attribute_alias(name)
59
35
  end
60
36
 
61
37
  primary_key = self.class.primary_key
62
- name = primary_key if name == "id".freeze && primary_key
38
+ name = primary_key if name == "id" && primary_key
63
39
  sync_with_transaction_state if name == primary_key
64
40
  _read_attribute(name, &block)
65
41
  end
66
42
 
67
43
  # This method exists to avoid the expensive primary_key check internally, without
68
44
  # breaking compatibility with the read_attribute API
69
- if defined?(JRUBY_VERSION)
70
- # This form is significantly faster on JRuby, and this is one of our biggest hotspots.
71
- # https://github.com/jruby/jruby/pull/2562
72
- def _read_attribute(attr_name, &block) # :nodoc:
73
- @attributes.fetch_value(attr_name.to_s, &block)
74
- end
75
- else
76
- def _read_attribute(attr_name) # :nodoc:
77
- @attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? }
78
- end
45
+ def _read_attribute(attr_name, &block) # :nodoc
46
+ @attributes.fetch_value(attr_name.to_s, &block)
79
47
  end
80
48
 
81
49
  alias :attribute :_read_attribute
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
 
8
8
  class ColumnNotSerializableError < StandardError
9
9
  def initialize(name, type)
10
- super <<-EOS.strip_heredoc
10
+ super <<~EOS
11
11
  Column `#{name}` of type #{type.class} does not support `serialize` feature.
12
12
  Usually it means that you are trying to use `serialize`
13
13
  on a column that already implements serialization natively.
@@ -73,7 +73,7 @@ module ActiveRecord
73
73
  # `skip_time_zone_conversion_for_attributes` would not be picked up.
74
74
  subclass.class_eval do
75
75
  matcher = ->(name, type) { create_time_zone_conversion_attribute?(name, type) }
76
- decorate_matching_attribute_types(matcher, :_time_zone_conversion) do |type|
76
+ decorate_matching_attribute_types(matcher, "_time_zone_conversion") do |type|
77
77
  TimeZoneConverter.new(type)
78
78
  end
79
79
  end
@@ -13,19 +13,19 @@ module ActiveRecord
13
13
  private
14
14
 
15
15
  def define_method_attribute=(name)
16
- safe_name = name.unpack("h*".freeze).first
17
- ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
18
16
  sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
19
17
 
20
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
21
- def __temp__#{safe_name}=(value)
22
- name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
23
- #{sync_with_transaction_state}
24
- _write_attribute(name, value)
25
- end
26
- alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
27
- undef_method :__temp__#{safe_name}=
28
- STR
18
+ ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
19
+ generated_attribute_methods, name, writer: true,
20
+ ) do |temp_method_name, attr_name_expr|
21
+ generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
22
+ def #{temp_method_name}(value)
23
+ name = #{attr_name_expr}
24
+ #{sync_with_transaction_state}
25
+ _write_attribute(name, value)
26
+ end
27
+ RUBY
28
+ end
29
29
  end
30
30
  end
31
31
 
@@ -33,14 +33,13 @@ module ActiveRecord
33
33
  # specified +value+. Empty strings for Integer and Float columns are
34
34
  # turned into +nil+.
35
35
  def write_attribute(attr_name, value)
36
- name = if self.class.attribute_alias?(attr_name)
37
- self.class.attribute_alias(attr_name).to_s
38
- else
39
- attr_name.to_s
36
+ name = attr_name.to_s
37
+ if self.class.attribute_alias?(name)
38
+ name = self.class.attribute_alias(name)
40
39
  end
41
40
 
42
41
  primary_key = self.class.primary_key
43
- name = primary_key if name == "id".freeze && primary_key
42
+ name = primary_key if name == "id" && primary_key
44
43
  sync_with_transaction_state if name == primary_key
45
44
  _write_attribute(name, value)
46
45
  end
@@ -149,7 +149,7 @@ module ActiveRecord
149
149
  private
150
150
 
151
151
  def define_non_cyclic_method(name, &block)
152
- return if method_defined?(name)
152
+ return if instance_methods(false).include?(name)
153
153
  define_method(name) do |*args|
154
154
  result = true; @_already_called ||= {}
155
155
  # Loop prevention for validation of associations
@@ -9,7 +9,6 @@ require "active_support/core_ext/module/attribute_accessors"
9
9
  require "active_support/core_ext/array/extract_options"
10
10
  require "active_support/core_ext/hash/deep_merge"
11
11
  require "active_support/core_ext/hash/slice"
12
- require "active_support/core_ext/hash/transform_values"
13
12
  require "active_support/core_ext/string/behavior"
14
13
  require "active_support/core_ext/kernel/singleton_class"
15
14
  require "active_support/core_ext/module/introspection"
@@ -23,6 +22,7 @@ require "active_record/explain_subscriber"
23
22
  require "active_record/relation/delegation"
24
23
  require "active_record/attributes"
25
24
  require "active_record/type_caster"
25
+ require "active_record/database_configurations"
26
26
 
27
27
  module ActiveRecord #:nodoc:
28
28
  # = Active Record
@@ -289,6 +289,7 @@ module ActiveRecord #:nodoc:
289
289
  extend Enum
290
290
  extend Delegation::DelegateCache
291
291
  extend CollectionCacheKey
292
+ extend Aggregations::ClassMethods
292
293
 
293
294
  include Core
294
295
  include Persistence
@@ -314,7 +315,6 @@ module ActiveRecord #:nodoc:
314
315
  include ActiveModel::SecurePassword
315
316
  include AutosaveAssociation
316
317
  include NestedAttributes
317
- include Aggregations
318
318
  include Transactions
319
319
  include TouchLater
320
320
  include NoTouching
@@ -75,21 +75,7 @@ module ActiveRecord
75
75
  # end
76
76
  #
77
77
  # Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
78
- # run, both +destroy_author+ and +destroy_readers+ are called. Contrast this to the following situation
79
- # where the +before_destroy+ method is overridden:
80
- #
81
- # class Topic < ActiveRecord::Base
82
- # def before_destroy() destroy_author end
83
- # end
84
- #
85
- # class Reply < Topic
86
- # def before_destroy() destroy_readers end
87
- # end
88
- #
89
- # In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
90
- # So, use the callback macros when you want to ensure that a certain callback is called for the entire
91
- # hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant
92
- # to decide whether they want to call +super+ and trigger the inherited callbacks.
78
+ # run, both +destroy_author+ and +destroy_readers+ are called.
93
79
  #
94
80
  # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
95
81
  # callbacks before specifying the associations. Otherwise, you might trigger the loading of a
@@ -109,7 +95,7 @@ module ActiveRecord
109
95
  #
110
96
  # private
111
97
  # def delete_parents
112
- # self.class.delete_all "parent_id = #{id}"
98
+ # self.class.where(parent_id: id).delete_all
113
99
  # end
114
100
  # end
115
101
  #
@@ -142,7 +128,7 @@ module ActiveRecord
142
128
  # end
143
129
  # end
144
130
  #
145
- # So you specify the object you want messaged on a given callback. When that callback is triggered, the object has
131
+ # So you specify the object you want to be messaged on a given callback. When that callback is triggered, the object has
146
132
  # a method by the name of the callback messaged. You can make these callbacks more flexible by passing in other
147
133
  # initialization data such as the name of the attribute to work with:
148
134
  #
@@ -16,7 +16,7 @@ module ActiveRecord
16
16
  collection = collection.send(:apply_join_dependency)
17
17
  end
18
18
  column_type = type_for_attribute(timestamp_column)
19
- column = connection.column_name_from_arel_node(collection.arel_attribute(timestamp_column))
19
+ column = connection.visitor.compile(collection.arel_attribute(timestamp_column))
20
20
  select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
21
21
 
22
22
  if collection.has_limit_or_offset?
@@ -731,7 +731,7 @@ module ActiveRecord
731
731
  # this block can't be easily moved into attempt_to_checkout_all_existing_connections's
732
732
  # rescue block, because doing so would put it outside of synchronize section, without
733
733
  # being in a critical section thread_report might become inaccurate
734
- msg = "could not obtain ownership of all database connections in #{checkout_timeout} seconds".dup
734
+ msg = +"could not obtain ownership of all database connections in #{checkout_timeout} seconds"
735
735
 
736
736
  thread_report = []
737
737
  @connections.each do |conn|
@@ -915,16 +915,6 @@ module ActiveRecord
915
915
  # about the model. The model needs to pass a specification name to the handler,
916
916
  # in order to look up the correct connection pool.
917
917
  class ConnectionHandler
918
- def self.create_owner_to_pool # :nodoc:
919
- Concurrent::Map.new(initial_capacity: 2) do |h, k|
920
- # Discard the parent's connection pools immediately; we have no need
921
- # of them
922
- discard_unowned_pools(h)
923
-
924
- h[k] = Concurrent::Map.new(initial_capacity: 2)
925
- end
926
- end
927
-
928
918
  def self.unowned_pool_finalizer(pid_map) # :nodoc:
929
919
  lambda do |_|
930
920
  discard_unowned_pools(pid_map)
@@ -939,7 +929,13 @@ module ActiveRecord
939
929
 
940
930
  def initialize
941
931
  # These caches are keyed by spec.name (ConnectionSpecification#name).
942
- @owner_to_pool = ConnectionHandler.create_owner_to_pool
932
+ @owner_to_pool = Concurrent::Map.new(initial_capacity: 2) do |h, k|
933
+ # Discard the parent's connection pools immediately; we have no need
934
+ # of them
935
+ ConnectionHandler.discard_unowned_pools(h)
936
+
937
+ h[k] = Concurrent::Map.new(initial_capacity: 2)
938
+ end
943
939
 
944
940
  # Backup finalizer: if the forked child never needed a pool, the above
945
941
  # early discard has not occurred
@@ -1017,8 +1013,8 @@ module ActiveRecord
1017
1013
  # Returns true if a connection that's accessible to this class has
1018
1014
  # already been opened.
1019
1015
  def connected?(spec_name)
1020
- conn = retrieve_connection_pool(spec_name)
1021
- conn && conn.connected?
1016
+ pool = retrieve_connection_pool(spec_name)
1017
+ pool && pool.connected?
1022
1018
  end
1023
1019
 
1024
1020
  # Remove the connection for this class. This will close the active
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/deprecation"
4
+
3
5
  module ActiveRecord
4
6
  module ConnectionAdapters # :nodoc:
5
7
  module DatabaseLimits
@@ -12,11 +14,13 @@ module ActiveRecord
12
14
  def column_name_length
13
15
  64
14
16
  end
17
+ deprecate :column_name_length
15
18
 
16
19
  # Returns the maximum length of a table name.
17
20
  def table_name_length
18
21
  64
19
22
  end
23
+ deprecate :table_name_length
20
24
 
21
25
  # Returns the maximum allowed length for an index name. This
22
26
  # limit is enforced by \Rails and is less than or equal to
@@ -36,16 +40,19 @@ module ActiveRecord
36
40
  def columns_per_table
37
41
  1024
38
42
  end
43
+ deprecate :columns_per_table
39
44
 
40
45
  # Returns the maximum number of indexes per table.
41
46
  def indexes_per_table
42
47
  16
43
48
  end
49
+ deprecate :indexes_per_table
44
50
 
45
51
  # Returns the maximum number of columns in a multicolumn index.
46
52
  def columns_per_multicolumn_index
47
53
  16
48
54
  end
55
+ deprecate :columns_per_multicolumn_index
49
56
 
50
57
  # Returns the maximum number of elements in an IN (x,y,z) clause.
51
58
  # +nil+ means no limit.
@@ -57,11 +64,13 @@ module ActiveRecord
57
64
  def sql_query_length
58
65
  1048575
59
66
  end
67
+ deprecate :sql_query_length
60
68
 
61
69
  # Returns maximum number of joins in a single query.
62
70
  def joins_per_query
63
71
  256
64
72
  end
73
+ deprecate :joins_per_query
65
74
 
66
75
  private
67
76
  def bind_params_length
@@ -20,22 +20,9 @@ module ActiveRecord
20
20
  raise "Passing bind parameters with an arel AST is forbidden. " \
21
21
  "The values must be stored on the AST directly"
22
22
  end
23
-
24
- if prepared_statements
25
- sql, binds = visitor.accept(arel_or_sql_string.ast, collector).value
26
-
27
- if binds.length > bind_params_length
28
- unprepared_statement do
29
- sql, binds = to_sql_and_binds(arel_or_sql_string)
30
- visitor.preparable = false
31
- end
32
- end
33
- else
34
- sql = visitor.accept(arel_or_sql_string.ast, collector).value
35
- end
36
- [sql.freeze, binds]
23
+ sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
24
+ [sql.freeze, binds || []]
37
25
  else
38
- visitor.preparable = false if prepared_statements
39
26
  [arel_or_sql_string.dup.freeze, binds]
40
27
  end
41
28
  end
@@ -45,11 +32,11 @@ module ActiveRecord
45
32
  # can be used to query the database repeatedly.
46
33
  def cacheable_query(klass, arel) # :nodoc:
47
34
  if prepared_statements
48
- sql, binds = visitor.accept(arel.ast, collector).value
35
+ sql, binds = visitor.compile(arel.ast, collector)
49
36
  query = klass.query(sql)
50
37
  else
51
- collector = PartialQueryCollector.new
52
- parts, binds = visitor.accept(arel.ast, collector).value
38
+ collector = klass.partial_query_collector
39
+ parts, binds = visitor.compile(arel.ast, collector)
53
40
  query = klass.partial_query(parts)
54
41
  end
55
42
  [query, binds]
@@ -60,8 +47,13 @@ module ActiveRecord
60
47
  arel = arel_from_relation(arel)
61
48
  sql, binds = to_sql_and_binds(arel, binds)
62
49
 
63
- if preparable.nil?
64
- preparable = prepared_statements ? visitor.preparable : false
50
+ if !prepared_statements || (arel.is_a?(String) && preparable.nil?)
51
+ preparable = false
52
+ elsif binds.length > bind_params_length
53
+ sql, binds = unprepared_statement { to_sql_and_binds(arel) }
54
+ preparable = false
55
+ else
56
+ preparable = visitor.preparable
65
57
  end
66
58
 
67
59
  if prepared_statements && preparable
@@ -106,6 +98,11 @@ module ActiveRecord
106
98
  exec_query(sql, name).rows
107
99
  end
108
100
 
101
+ # Determines whether the SQL statement is a write query.
102
+ def write_query?(sql)
103
+ raise NotImplementedError
104
+ end
105
+
109
106
  # Executes the SQL statement in the context of this connection and returns
110
107
  # the raw result from the connection adapter.
111
108
  # Note: depending on your database connector, the result returned by this
@@ -126,7 +123,7 @@ module ActiveRecord
126
123
  # +binds+ as the bind substitutes. +name+ is logged along with
127
124
  # the executed +sql+ statement.
128
125
  def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
129
- sql, binds = sql_for_insert(sql, pk, nil, sequence_name, binds)
126
+ sql, binds = sql_for_insert(sql, pk, sequence_name, binds)
130
127
  exec_query(sql, name, binds)
131
128
  end
132
129
 
@@ -176,13 +173,6 @@ module ActiveRecord
176
173
  exec_delete(sql, name, binds)
177
174
  end
178
175
 
179
- # Returns +true+ when the connection adapter supports prepared statement
180
- # caching, otherwise returns +false+
181
- def supports_statement_cache? # :nodoc:
182
- true
183
- end
184
- deprecate :supports_statement_cache?
185
-
186
176
  # Runs the given block in a database transaction, and returns the result
187
177
  # of the block.
188
178
  #
@@ -272,7 +262,9 @@ module ActiveRecord
272
262
 
273
263
  attr_reader :transaction_manager #:nodoc:
274
264
 
275
- delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction, :commit_transaction, :rollback_transaction, to: :transaction_manager
265
+ delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
266
+ :commit_transaction, :rollback_transaction, :materialize_transactions,
267
+ :disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
276
268
 
277
269
  def transaction_open?
278
270
  current_transaction.open?
@@ -337,7 +329,7 @@ module ActiveRecord
337
329
 
338
330
  # Inserts the given fixture into the table. Overridden in adapters that require
339
331
  # something beyond a simple insert (eg. Oracle).
340
- # Most of adapters should implement `insert_fixtures` that leverages bulk SQL insert.
332
+ # Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
341
333
  # We keep this method to provide fallback
342
334
  # for databases like sqlite that do not support bulk inserts.
343
335
  def insert_fixture(fixture, table_name)
@@ -366,18 +358,6 @@ module ActiveRecord
366
358
  execute manager.to_sql, "Fixture Insert"
367
359
  end
368
360
 
369
- # Inserts a set of fixtures into the table. Overridden in adapters that require
370
- # something beyond a simple insert (eg. Oracle).
371
- def insert_fixtures(fixtures, table_name)
372
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
373
- `insert_fixtures` is deprecated and will be removed in the next version of Rails.
374
- Consider using `insert_fixtures_set` for performance improvement.
375
- MSG
376
- return if fixtures.empty?
377
-
378
- execute(build_fixture_sql(fixtures, table_name), "Fixtures Insert")
379
- end
380
-
381
361
  def insert_fixtures_set(fixture_set, tables_to_delete = [])
382
362
  fixture_inserts = fixture_set.map do |table_name, fixtures|
383
363
  next if fixtures.empty?
@@ -385,7 +365,7 @@ module ActiveRecord
385
365
  build_fixture_sql(fixtures, table_name)
386
366
  end.compact
387
367
 
388
- table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}".dup }
368
+ table_deletes = tables_to_delete.map { |table| +"DELETE FROM #{quote_table_name table}" }
389
369
  total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))
390
370
 
391
371
  disable_referential_integrity do
@@ -398,7 +378,7 @@ module ActiveRecord
398
378
  end
399
379
  end
400
380
 
401
- def empty_insert_statement_value
381
+ def empty_insert_statement_value(primary_key = nil)
402
382
  "DEFAULT VALUES"
403
383
  end
404
384
 
@@ -416,16 +396,6 @@ module ActiveRecord
416
396
  end
417
397
  end
418
398
 
419
- # The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
420
- # on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
421
- # an UPDATE statement, so in the MySQL adapters we redefine this to do that.
422
- def join_to_update(update, select, key) # :nodoc:
423
- subselect = subquery_for(key, select)
424
-
425
- update.where key.in(subselect)
426
- end
427
- alias join_to_delete join_to_update
428
-
429
399
  private
430
400
  def default_insert_value(column)
431
401
  Arel.sql("DEFAULT")
@@ -466,13 +436,6 @@ module ActiveRecord
466
436
  total_sql.join(";\n")
467
437
  end
468
438
 
469
- # Returns a subquery for the given key using the join information.
470
- def subquery_for(key, select)
471
- subselect = select.clone
472
- subselect.projections = [key]
473
- subselect
474
- end
475
-
476
439
  # Returns an ActiveRecord::Result instance.
477
440
  def select(sql, name = nil, binds = [])
478
441
  exec_query(sql, name, binds, prepare: false)
@@ -482,7 +445,7 @@ module ActiveRecord
482
445
  exec_query(sql, name, binds, prepare: true)
483
446
  end
484
447
 
485
- def sql_for_insert(sql, pk, id_value, sequence_name, binds)
448
+ def sql_for_insert(sql, pk, sequence_name, binds)
486
449
  [sql, binds]
487
450
  end
488
451
 
@@ -513,28 +476,6 @@ module ActiveRecord
513
476
  value
514
477
  end
515
478
  end
516
-
517
- class PartialQueryCollector
518
- def initialize
519
- @parts = []
520
- @binds = []
521
- end
522
-
523
- def <<(str)
524
- @parts << str
525
- self
526
- end
527
-
528
- def add_bind(obj)
529
- @binds << obj
530
- @parts << Arel::Nodes::BindParam.new(1)
531
- self
532
- end
533
-
534
- def value
535
- [@parts, @binds]
536
- end
537
- end
538
479
  end
539
480
  end
540
481
  end