activerecord 5.1.7 → 5.2.0

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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +372 -765
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record/aggregations.rb +6 -5
  8. data/lib/active_record/association_relation.rb +4 -2
  9. data/lib/active_record/associations/alias_tracker.rb +19 -27
  10. data/lib/active_record/associations/association.rb +16 -27
  11. data/lib/active_record/associations/association_scope.rb +38 -50
  12. data/lib/active_record/associations/belongs_to_association.rb +20 -10
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +4 -5
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +2 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +43 -35
  22. data/lib/active_record/associations/collection_proxy.rb +12 -15
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +3 -1
  25. data/lib/active_record/associations/has_many_through_association.rb +7 -18
  26. data/lib/active_record/associations/has_one_association.rb +4 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +8 -7
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  31. data/lib/active_record/associations/join_dependency.rb +23 -43
  32. data/lib/active_record/associations/preloader/association.rb +45 -61
  33. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  34. data/lib/active_record/associations/preloader.rb +17 -37
  35. data/lib/active_record/associations/singular_association.rb +14 -10
  36. data/lib/active_record/associations/through_association.rb +25 -10
  37. data/lib/active_record/associations.rb +31 -54
  38. data/lib/active_record/attribute_assignment.rb +2 -5
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +25 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +8 -2
  45. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  47. data/lib/active_record/attribute_methods/write.rb +21 -9
  48. data/lib/active_record/attribute_methods.rb +65 -24
  49. data/lib/active_record/attributes.rb +6 -5
  50. data/lib/active_record/autosave_association.rb +8 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +8 -10
  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 +11 -7
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +111 -38
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +157 -29
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -32
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +57 -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 +158 -78
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +111 -183
  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 +11 -2
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +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/array.rb +3 -11
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -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 +2 -0
  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 +4 -6
  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/oid.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +246 -110
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +58 -82
  117. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +18 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +80 -90
  126. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  127. data/lib/active_record/connection_handling.rb +4 -2
  128. data/lib/active_record/core.rb +39 -60
  129. data/lib/active_record/counter_cache.rb +15 -12
  130. data/lib/active_record/define_callbacks.rb +5 -3
  131. data/lib/active_record/dynamic_matchers.rb +9 -9
  132. data/lib/active_record/enum.rb +17 -13
  133. data/lib/active_record/errors.rb +54 -21
  134. data/lib/active_record/explain.rb +3 -1
  135. data/lib/active_record/explain_registry.rb +2 -0
  136. data/lib/active_record/explain_subscriber.rb +2 -0
  137. data/lib/active_record/fixture_set/file.rb +2 -0
  138. data/lib/active_record/fixtures.rb +67 -60
  139. data/lib/active_record/gem_version.rb +4 -2
  140. data/lib/active_record/inheritance.rb +49 -19
  141. data/lib/active_record/integration.rb +58 -19
  142. data/lib/active_record/internal_metadata.rb +2 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  144. data/lib/active_record/locking/optimistic.rb +14 -17
  145. data/lib/active_record/locking/pessimistic.rb +9 -6
  146. data/lib/active_record/log_subscriber.rb +43 -0
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +40 -2
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/migration.rb +189 -139
  151. data/lib/active_record/model_schema.rb +16 -21
  152. data/lib/active_record/nested_attributes.rb +18 -6
  153. data/lib/active_record/no_touching.rb +3 -1
  154. data/lib/active_record/null_relation.rb +2 -0
  155. data/lib/active_record/persistence.rb +166 -16
  156. data/lib/active_record/query_cache.rb +11 -6
  157. data/lib/active_record/querying.rb +3 -1
  158. data/lib/active_record/railtie.rb +61 -3
  159. data/lib/active_record/railties/console_sandbox.rb +2 -0
  160. data/lib/active_record/railties/controller_runtime.rb +2 -0
  161. data/lib/active_record/railties/databases.rake +46 -36
  162. data/lib/active_record/readonly_attributes.rb +3 -2
  163. data/lib/active_record/reflection.rb +110 -192
  164. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  165. data/lib/active_record/relation/batches.rb +20 -5
  166. data/lib/active_record/relation/calculations.rb +30 -8
  167. data/lib/active_record/relation/delegation.rb +15 -27
  168. data/lib/active_record/relation/finder_methods.rb +75 -78
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +51 -20
  171. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  172. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  173. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  174. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  175. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  176. data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
  177. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  178. data/lib/active_record/relation/predicate_builder.rb +53 -78
  179. data/lib/active_record/relation/query_attribute.rb +26 -2
  180. data/lib/active_record/relation/query_methods.rb +89 -88
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +3 -1
  183. data/lib/active_record/relation/where_clause.rb +65 -68
  184. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  185. data/lib/active_record/relation.rb +95 -208
  186. data/lib/active_record/result.rb +2 -0
  187. data/lib/active_record/runtime_registry.rb +2 -0
  188. data/lib/active_record/sanitization.rb +129 -121
  189. data/lib/active_record/schema.rb +4 -2
  190. data/lib/active_record/schema_dumper.rb +36 -26
  191. data/lib/active_record/schema_migration.rb +2 -0
  192. data/lib/active_record/scoping/default.rb +6 -7
  193. data/lib/active_record/scoping/named.rb +21 -7
  194. data/lib/active_record/scoping.rb +9 -8
  195. data/lib/active_record/secure_token.rb +2 -0
  196. data/lib/active_record/serialization.rb +2 -0
  197. data/lib/active_record/statement_cache.rb +22 -12
  198. data/lib/active_record/store.rb +3 -1
  199. data/lib/active_record/suppressor.rb +2 -0
  200. data/lib/active_record/table_metadata.rb +12 -3
  201. data/lib/active_record/tasks/database_tasks.rb +26 -15
  202. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  203. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  204. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  205. data/lib/active_record/timestamp.rb +5 -12
  206. data/lib/active_record/touch_later.rb +2 -0
  207. data/lib/active_record/transactions.rb +9 -7
  208. data/lib/active_record/translation.rb +2 -0
  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.rb +4 -1
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +3 -1
  224. data/lib/active_record/type_caster.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 +35 -5
  230. data/lib/active_record/validations.rb +2 -0
  231. data/lib/active_record/version.rb +2 -0
  232. data/lib/active_record.rb +11 -4
  233. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  234. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -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/migration.rb +2 -0
  239. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  240. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  242. data/lib/rails/generators/active_record.rb +3 -1
  243. metadata +24 -36
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  251. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  252. data/lib/active_record/attribute.rb +0 -240
  253. data/lib/active_record/attribute_mutation_tracker.rb +0 -122
  254. data/lib/active_record/attribute_set/builder.rb +0 -126
  255. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  256. data/lib/active_record/attribute_set.rb +0 -113
  257. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  258. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  259. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  260. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  261. data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class Relation
3
5
  class WhereClauseFactory # :nodoc:
@@ -9,69 +11,24 @@ module ActiveRecord
9
11
  def build(opts, other)
10
12
  case opts
11
13
  when String, Array
12
- parts = [klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))]
14
+ parts = [klass.sanitize_sql(other.empty? ? opts : ([opts] + other))]
13
15
  when Hash
14
16
  attributes = predicate_builder.resolve_column_aliases(opts)
15
- attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes)
16
17
  attributes.stringify_keys!
17
18
 
18
- if perform_case_sensitive?(options = other.last)
19
- parts, binds = build_for_case_sensitive(attributes, options)
20
- else
21
- attributes, binds = predicate_builder.create_binds(attributes)
22
- parts = predicate_builder.build_from_hash(attributes)
23
- end
19
+ parts = predicate_builder.build_from_hash(attributes)
24
20
  when Arel::Nodes::Node
25
21
  parts = [opts]
26
22
  else
27
23
  raise ArgumentError, "Unsupported argument type: #{opts} (#{opts.class})"
28
24
  end
29
25
 
30
- WhereClause.new(parts, binds || [])
26
+ WhereClause.new(parts)
31
27
  end
32
28
 
33
- # TODO Change this to private once we've dropped Ruby 2.2 support.
34
- # Workaround for Ruby 2.2 "private attribute?" warning.
35
29
  protected
36
30
 
37
31
  attr_reader :klass, :predicate_builder
38
-
39
- private
40
-
41
- def perform_case_sensitive?(options)
42
- options && options.key?(:case_sensitive)
43
- end
44
-
45
- def build_for_case_sensitive(attributes, options)
46
- parts, binds = [], []
47
- table = klass.arel_table
48
-
49
- attributes.each do |attribute, value|
50
- if reflection = klass._reflect_on_association(attribute)
51
- attribute = reflection.foreign_key.to_s
52
- value = value[reflection.klass.primary_key] unless value.nil?
53
- end
54
-
55
- if value.nil?
56
- parts << table[attribute].eq(value)
57
- else
58
- column = klass.column_for_attribute(attribute)
59
-
60
- binds << predicate_builder.send(:build_bind_param, attribute, value)
61
- value = Arel::Nodes::BindParam.new
62
-
63
- predicate = if options[:case_sensitive]
64
- klass.connection.case_sensitive_comparison(table, attribute, column, value)
65
- else
66
- klass.connection.case_insensitive_comparison(table, attribute, column, value)
67
- end
68
-
69
- parts << predicate
70
- end
71
- end
72
-
73
- [parts, binds]
74
- end
75
32
  end
76
33
  end
77
34
  end
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record \Relation
3
5
  class Relation
4
6
  MULTI_VALUE_METHODS = [:includes, :eager_load, :preload, :select, :group,
5
- :order, :joins, :left_joins, :left_outer_joins, :references,
7
+ :order, :joins, :left_outer_joins, :references,
6
8
  :extending, :unscope]
7
9
 
8
10
  SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering,
9
- :reverse_order, :distinct, :create_with]
11
+ :reverse_order, :distinct, :create_with, :skip_query_cache]
10
12
  CLAUSE_METHODS = [:where, :having, :from]
11
- INVALID_METHODS_FOR_DELETE_ALL = [:limit, :distinct, :offset, :group, :having]
13
+ INVALID_METHODS_FOR_DELETE_ALL = [:distinct, :group, :having]
12
14
 
13
15
  VALUE_METHODS = MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS
14
16
 
@@ -18,14 +20,16 @@ module ActiveRecord
18
20
  attr_reader :table, :klass, :loaded, :predicate_builder
19
21
  alias :model :klass
20
22
  alias :loaded? :loaded
23
+ alias :locked? :lock_value
21
24
 
22
- def initialize(klass, table, predicate_builder, values = {})
25
+ def initialize(klass, table: klass.arel_table, predicate_builder: klass.predicate_builder, values: {})
23
26
  @klass = klass
24
27
  @table = table
25
28
  @values = values
26
29
  @offsets = {}
27
30
  @loaded = false
28
31
  @predicate_builder = predicate_builder
32
+ @delegate_to_klass = false
29
33
  end
30
34
 
31
35
  def initialize_copy(other)
@@ -33,74 +37,6 @@ module ActiveRecord
33
37
  reset
34
38
  end
35
39
 
36
- def insert(values) # :nodoc:
37
- primary_key_value = nil
38
-
39
- if primary_key && Hash === values
40
- primary_key_value = values[values.keys.find { |k|
41
- k.name == primary_key
42
- }]
43
-
44
- if !primary_key_value && klass.prefetch_primary_key?
45
- primary_key_value = klass.next_sequence_value
46
- values[arel_attribute(klass.primary_key)] = primary_key_value
47
- end
48
- end
49
-
50
- im = arel.create_insert
51
- im.into @table
52
-
53
- substitutes, binds = substitute_values values
54
-
55
- if values.empty? # empty insert
56
- im.values = Arel.sql(connection.empty_insert_statement_value)
57
- else
58
- im.insert substitutes
59
- end
60
-
61
- @klass.connection.insert(
62
- im,
63
- "SQL",
64
- primary_key || false,
65
- primary_key_value,
66
- nil,
67
- binds)
68
- end
69
-
70
- def _update_record(values, constraints) # :nodoc:
71
- substitutes, binds = substitute_values values
72
-
73
- scope = @klass.unscoped
74
-
75
- if @klass.finder_needs_type_condition?
76
- scope.unscope!(where: @klass.inheritance_column)
77
- end
78
-
79
- relation = scope.where(constraints)
80
- bvs = binds + relation.bound_attributes
81
- um = relation
82
- .arel
83
- .compile_update(substitutes, @klass.primary_key)
84
-
85
- @klass.connection.update(
86
- um,
87
- "SQL",
88
- bvs,
89
- )
90
- end
91
-
92
- def substitute_values(values) # :nodoc:
93
- binds = []
94
- substitutes = []
95
-
96
- values.each do |arel_attr, value|
97
- binds.push QueryAttribute.new(arel_attr.name, value, klass.type_for_attribute(arel_attr.name))
98
- substitutes.push [arel_attr, Arel::Nodes::BindParam.new]
99
- end
100
-
101
- [substitutes, binds]
102
- end
103
-
104
40
  def arel_attribute(name) # :nodoc:
105
41
  klass.arel_attribute(name, table)
106
42
  end
@@ -117,8 +53,8 @@ module ActiveRecord
117
53
  #
118
54
  # user = users.new { |user| user.name = 'Oscar' }
119
55
  # user.name # => Oscar
120
- def new(*args, &block)
121
- scoping { @klass.new(*args, &block) }
56
+ def new(attributes = nil, &block)
57
+ scoping { klass.new(scope_for_create(attributes), &block) }
122
58
  end
123
59
 
124
60
  alias build new
@@ -142,8 +78,12 @@ module ActiveRecord
142
78
  #
143
79
  # users.create(name: nil) # validation on name
144
80
  # # => #<User id: nil, name: nil, ...>
145
- def create(*args, &block)
146
- scoping { @klass.create(*args, &block) }
81
+ def create(attributes = nil, &block)
82
+ if attributes.is_a?(Array)
83
+ attributes.collect { |attr| create(attr, &block) }
84
+ else
85
+ scoping { klass.create(scope_for_create(attributes), &block) }
86
+ end
147
87
  end
148
88
 
149
89
  # Similar to #create, but calls
@@ -152,8 +92,12 @@ module ActiveRecord
152
92
  #
153
93
  # Expects arguments in the same format as
154
94
  # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!].
155
- def create!(*args, &block)
156
- scoping { @klass.create!(*args, &block) }
95
+ def create!(attributes = nil, &block)
96
+ if attributes.is_a?(Array)
97
+ attributes.collect { |attr| create!(attr, &block) }
98
+ else
99
+ scoping { klass.create!(scope_for_create(attributes), &block) }
100
+ end
157
101
  end
158
102
 
159
103
  def first_or_create(attributes = nil, &block) # :nodoc:
@@ -247,9 +191,10 @@ module ActiveRecord
247
191
  end
248
192
 
249
193
  # Converts relation objects to Array.
250
- def to_a
194
+ def to_ary
251
195
  records.dup
252
196
  end
197
+ alias to_a to_ary
253
198
 
254
199
  def records # :nodoc:
255
200
  load
@@ -338,6 +283,13 @@ module ActiveRecord
338
283
  klass.current_scope = previous
339
284
  end
340
285
 
286
+ def _exec_scope(*args, &block) # :nodoc:
287
+ @delegate_to_klass = true
288
+ instance_exec(*args, &block) || self
289
+ ensure
290
+ @delegate_to_klass = false
291
+ end
292
+
341
293
  # Updates all records in the current relation with details given. This method constructs a single SQL UPDATE
342
294
  # statement and sends it straight to the database. It does not instantiate the involved models and it does not
343
295
  # trigger Active Record callbacks or validations. However, values passed to #update_all will still go through
@@ -363,12 +315,17 @@ module ActiveRecord
363
315
  def update_all(updates)
364
316
  raise ArgumentError, "Empty list of attributes to change" if updates.blank?
365
317
 
318
+ if eager_loading?
319
+ relation = apply_join_dependency
320
+ return relation.update_all(updates)
321
+ end
322
+
366
323
  stmt = Arel::UpdateManager.new
367
324
 
368
- stmt.set Arel.sql(@klass.send(:sanitize_sql_for_assignment, updates))
325
+ stmt.set Arel.sql(@klass.sanitize_sql_for_assignment(updates))
369
326
  stmt.table(table)
370
327
 
371
- if has_join_values?
328
+ if has_join_values? || offset_value
372
329
  @klass.connection.join_to_update(stmt, arel, arel_attribute(primary_key))
373
330
  else
374
331
  stmt.key = arel_attribute(primary_key)
@@ -377,51 +334,7 @@ module ActiveRecord
377
334
  stmt.wheres = arel.constraints
378
335
  end
379
336
 
380
- @klass.connection.update stmt, "SQL", bound_attributes
381
- end
382
-
383
- # Updates an object (or multiple objects) and saves it to the database, if validations pass.
384
- # The resulting object is returned whether the object was saved successfully to the database or not.
385
- #
386
- # ==== Parameters
387
- #
388
- # * +id+ - This should be the id or an array of ids to be updated.
389
- # * +attributes+ - This should be a hash of attributes or an array of hashes.
390
- #
391
- # ==== Examples
392
- #
393
- # # Updates one record
394
- # Person.update(15, user_name: 'Samuel', group: 'expert')
395
- #
396
- # # Updates multiple records
397
- # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
398
- # Person.update(people.keys, people.values)
399
- #
400
- # # Updates multiple records from the result of a relation
401
- # people = Person.where(group: 'expert')
402
- # people.update(group: 'masters')
403
- #
404
- # Note: Updating a large number of records will run an
405
- # UPDATE query for each record, which may cause a performance
406
- # issue. So if it is not needed to run callbacks for each update, it is
407
- # preferred to use #update_all for updating all records using
408
- # a single query.
409
- def update(id = :all, attributes)
410
- if id.is_a?(Array)
411
- id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) }
412
- elsif id == :all
413
- records.each { |record| record.update(attributes) }
414
- else
415
- if ActiveRecord::Base === id
416
- raise ArgumentError, <<-MSG.squish
417
- You are passing an instance of ActiveRecord::Base to `update`.
418
- Please pass the id of the object by calling `.id`.
419
- MSG
420
- end
421
- object = find(id)
422
- object.update(attributes)
423
- object
424
- end
337
+ @klass.connection.update stmt, "#{@klass} Update All"
425
338
  end
426
339
 
427
340
  # Destroys the records by instantiating each
@@ -444,33 +357,6 @@ module ActiveRecord
444
357
  records.each(&:destroy).tap { reset }
445
358
  end
446
359
 
447
- # Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
448
- # therefore all callbacks and filters are fired off before the object is deleted. This method is
449
- # less efficient than #delete but allows cleanup methods and other actions to be run.
450
- #
451
- # This essentially finds the object (or multiple objects) with the given id, creates a new object
452
- # from the attributes, and then calls destroy on it.
453
- #
454
- # ==== Parameters
455
- #
456
- # * +id+ - Can be either an Integer or an Array of Integers.
457
- #
458
- # ==== Examples
459
- #
460
- # # Destroy a single object
461
- # Todo.destroy(1)
462
- #
463
- # # Destroy multiple objects
464
- # todos = [1,2,3]
465
- # Todo.destroy(todos)
466
- def destroy(id)
467
- if id.is_a?(Array)
468
- id.map { |one_id| destroy(one_id) }
469
- else
470
- find(id).destroy
471
- end
472
- end
473
-
474
360
  # Deletes the records without instantiating the records
475
361
  # first, and hence not calling the {#destroy}[rdoc-ref:Persistence#destroy]
476
362
  # method nor invoking callbacks.
@@ -487,8 +373,8 @@ module ActiveRecord
487
373
  #
488
374
  # If an invalid method is supplied, #delete_all raises an ActiveRecordError:
489
375
  #
490
- # Post.limit(100).delete_all
491
- # # => ActiveRecord::ActiveRecordError: delete_all doesn't support limit
376
+ # Post.distinct.delete_all
377
+ # # => ActiveRecord::ActiveRecordError: delete_all doesn't support distinct
492
378
  def delete_all
493
379
  invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
494
380
  value = get_value(method)
@@ -498,44 +384,26 @@ module ActiveRecord
498
384
  raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
499
385
  end
500
386
 
387
+ if eager_loading?
388
+ relation = apply_join_dependency
389
+ return relation.delete_all
390
+ end
391
+
501
392
  stmt = Arel::DeleteManager.new
502
393
  stmt.from(table)
503
394
 
504
- if has_join_values?
395
+ if has_join_values? || has_limit_or_offset?
505
396
  @klass.connection.join_to_delete(stmt, arel, arel_attribute(primary_key))
506
397
  else
507
398
  stmt.wheres = arel.constraints
508
399
  end
509
400
 
510
- affected = @klass.connection.delete(stmt, "SQL", bound_attributes)
401
+ affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
511
402
 
512
403
  reset
513
404
  affected
514
405
  end
515
406
 
516
- # Deletes the row with a primary key matching the +id+ argument, using a
517
- # SQL +DELETE+ statement, and returns the number of rows deleted. Active
518
- # Record objects are not instantiated, so the object's callbacks are not
519
- # executed, including any <tt>:dependent</tt> association options.
520
- #
521
- # You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
522
- #
523
- # Note: Although it is often much faster than the alternative,
524
- # #destroy, skipping callbacks might bypass business logic in
525
- # your application that ensures referential integrity or performs other
526
- # essential jobs.
527
- #
528
- # ==== Examples
529
- #
530
- # # Delete a single row
531
- # Todo.delete(1)
532
- #
533
- # # Delete multiple rows
534
- # Todo.delete([2,3,4])
535
- def delete(id_or_array)
536
- where(primary_key => id_or_array).delete_all
537
- end
538
-
539
407
  # Causes the records to be loaded from the database if they have not
540
408
  # been loaded already. You can use this if for some reason you need
541
409
  # to explicitly load some records before actually using them. The
@@ -555,8 +423,8 @@ module ActiveRecord
555
423
  end
556
424
 
557
425
  def reset
558
- @last = @to_sql = @order_clause = @scope_for_create = @arel = @loaded = nil
559
- @should_eager_load = @join_dependency = nil
426
+ @delegate_to_klass = false
427
+ @to_sql = @arel = @loaded = @should_eager_load = nil
560
428
  @records = [].freeze
561
429
  @offsets = {}
562
430
  self
@@ -571,12 +439,12 @@ module ActiveRecord
571
439
  relation = self
572
440
 
573
441
  if eager_loading?
574
- find_with_associations { |rel, _| relation = rel }
442
+ apply_join_dependency { |rel, _| relation = rel }
575
443
  end
576
444
 
577
445
  conn = klass.connection
578
446
  conn.unprepared_statement {
579
- conn.to_sql(relation.arel, relation.bound_attributes)
447
+ conn.to_sql(relation.arel)
580
448
  }
581
449
  end
582
450
  end
@@ -585,12 +453,14 @@ module ActiveRecord
585
453
  #
586
454
  # User.where(name: 'Oscar').where_values_hash
587
455
  # # => {name: "Oscar"}
588
- def where_values_hash(relation_table_name = table_name)
456
+ def where_values_hash(relation_table_name = klass.table_name)
589
457
  where_clause.to_h(relation_table_name)
590
458
  end
591
459
 
592
- def scope_for_create
593
- @scope_for_create ||= where_values_hash.merge(create_with_value)
460
+ def scope_for_create(attributes = nil)
461
+ scope = where_values_hash.merge!(create_with_value.stringify_keys)
462
+ scope.merge!(attributes) if attributes
463
+ scope
594
464
  end
595
465
 
596
466
  # Returns true if relation needs eager loading.
@@ -650,6 +520,11 @@ module ActiveRecord
650
520
  limit_value || offset_value
651
521
  end
652
522
 
523
+ def alias_tracker(joins = [], aliases = nil) # :nodoc:
524
+ joins += [aliases] if aliases
525
+ ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins)
526
+ end
527
+
653
528
  protected
654
529
 
655
530
  def load_records(records)
@@ -664,32 +539,44 @@ module ActiveRecord
664
539
  end
665
540
 
666
541
  def exec_queries(&block)
667
- @records =
668
- if eager_loading?
669
- find_with_associations do |relation, join_dependency|
670
- if ActiveRecord::NullRelation === relation
671
- []
672
- else
673
- rows = connection.select_all(relation.arel, "SQL", relation.bound_attributes)
674
- join_dependency.instantiate(rows, &block)
675
- end.freeze
542
+ skip_query_cache_if_necessary do
543
+ @records =
544
+ if eager_loading?
545
+ apply_join_dependency do |relation, join_dependency|
546
+ if ActiveRecord::NullRelation === relation
547
+ []
548
+ else
549
+ rows = connection.select_all(relation.arel, "SQL")
550
+ join_dependency.instantiate(rows, &block)
551
+ end.freeze
552
+ end
553
+ else
554
+ klass.find_by_sql(arel, &block).freeze
676
555
  end
677
- else
678
- klass.find_by_sql(arel, bound_attributes, &block).freeze
556
+
557
+ preload = preload_values
558
+ preload += includes_values unless eager_loading?
559
+ preloader = nil
560
+ preload.each do |associations|
561
+ preloader ||= build_preloader
562
+ preloader.preload @records, associations
679
563
  end
680
564
 
681
- preload = preload_values
682
- preload += includes_values unless eager_loading?
683
- preloader = nil
684
- preload.each do |associations|
685
- preloader ||= build_preloader
686
- preloader.preload @records, associations
687
- end
565
+ @records.each(&:readonly!) if readonly_value
688
566
 
689
- @records.each(&:readonly!) if readonly_value
567
+ @loaded = true
568
+ @records
569
+ end
570
+ end
690
571
 
691
- @loaded = true
692
- @records
572
+ def skip_query_cache_if_necessary
573
+ if skip_query_cache_value
574
+ uncached do
575
+ yield
576
+ end
577
+ else
578
+ yield
579
+ end
693
580
  end
694
581
 
695
582
  def build_preloader
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  ###
3
5
  # This class encapsulates a result returned from calling
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/per_thread_registry"
2
4
 
3
5
  module ActiveRecord