activerecord 5.1.0 → 5.2.0.rc1

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 (260) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +410 -530
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  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 +23 -32
  10. data/lib/active_record/associations/association.rb +20 -21
  11. data/lib/active_record/associations/association_scope.rb +49 -49
  12. data/lib/active_record/associations/belongs_to_association.rb +12 -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 +10 -6
  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 +50 -41
  22. data/lib/active_record/associations/collection_proxy.rb +22 -39
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +4 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +12 -18
  26. data/lib/active_record/associations/has_one_association.rb +5 -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 -64
  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 +27 -44
  32. data/lib/active_record/associations/preloader/association.rb +53 -92
  33. data/lib/active_record/associations/preloader/through_association.rb +72 -73
  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 +26 -11
  37. data/lib/active_record/associations.rb +68 -76
  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/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +24 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +10 -13
  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 +22 -19
  48. data/lib/active_record/attribute_methods.rb +48 -12
  49. data/lib/active_record/attributes.rb +7 -6
  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 -6
  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 +14 -10
  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 +175 -33
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +58 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
  69. data/lib/active_record/connection_adapters/column.rb +4 -2
  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 -17
  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 -23
  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 +30 -1
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
  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 +2 -0
  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_time.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +269 -126
  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 +64 -85
  116. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  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 +18 -0
  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 +92 -95
  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 +39 -60
  128. data/lib/active_record/counter_cache.rb +3 -2
  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 +17 -13
  132. data/lib/active_record/errors.rb +42 -3
  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 +67 -60
  138. data/lib/active_record/gem_version.rb +4 -2
  139. data/lib/active_record/inheritance.rb +9 -9
  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 +8 -6
  144. data/lib/active_record/locking/pessimistic.rb +9 -6
  145. data/lib/active_record/log_subscriber.rb +46 -4
  146. data/lib/active_record/migration/command_recorder.rb +11 -9
  147. data/lib/active_record/migration/compatibility.rb +74 -22
  148. data/lib/active_record/migration/join_table.rb +2 -0
  149. data/lib/active_record/migration.rb +181 -137
  150. data/lib/active_record/model_schema.rb +73 -58
  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 +153 -18
  155. data/lib/active_record/query_cache.rb +17 -12
  156. data/lib/active_record/querying.rb +4 -2
  157. data/lib/active_record/railtie.rb +61 -3
  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 +47 -37
  161. data/lib/active_record/readonly_attributes.rb +3 -2
  162. data/lib/active_record/reflection.rb +131 -204
  163. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  164. data/lib/active_record/relation/batches.rb +32 -17
  165. data/lib/active_record/relation/calculations.rb +58 -20
  166. data/lib/active_record/relation/delegation.rb +10 -29
  167. data/lib/active_record/relation/finder_methods.rb +74 -85
  168. data/lib/active_record/relation/from_clause.rb +2 -8
  169. data/lib/active_record/relation/merger.rb +51 -20
  170. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  171. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  172. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  173. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
  175. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
  176. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  177. data/lib/active_record/relation/predicate_builder.rb +53 -78
  178. data/lib/active_record/relation/query_attribute.rb +9 -2
  179. data/lib/active_record/relation/query_methods.rb +101 -95
  180. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  181. data/lib/active_record/relation/spawn_methods.rb +3 -1
  182. data/lib/active_record/relation/where_clause.rb +65 -67
  183. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  184. data/lib/active_record/relation.rb +99 -202
  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 +129 -121
  188. data/lib/active_record/schema.rb +4 -2
  189. data/lib/active_record/schema_dumper.rb +36 -26
  190. data/lib/active_record/schema_migration.rb +2 -0
  191. data/lib/active_record/scoping/default.rb +10 -7
  192. data/lib/active_record/scoping/named.rb +38 -12
  193. data/lib/active_record/scoping.rb +12 -10
  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 +3 -1
  198. data/lib/active_record/suppressor.rb +2 -0
  199. data/lib/active_record/table_metadata.rb +12 -3
  200. data/lib/active_record/tasks/database_tasks.rb +37 -25
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  204. data/lib/active_record/timestamp.rb +5 -5
  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/adapter_specific_registry.rb +2 -0
  209. data/lib/active_record/type/date.rb +2 -0
  210. data/lib/active_record/type/date_time.rb +2 -0
  211. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  212. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  213. data/lib/active_record/type/internal/timezone.rb +2 -0
  214. data/lib/active_record/type/json.rb +30 -0
  215. data/lib/active_record/type/serialized.rb +2 -0
  216. data/lib/active_record/type/text.rb +2 -0
  217. data/lib/active_record/type/time.rb +2 -0
  218. data/lib/active_record/type/type_map.rb +2 -0
  219. data/lib/active_record/type/unsigned_integer.rb +2 -0
  220. data/lib/active_record/type.rb +4 -1
  221. data/lib/active_record/type_caster/connection.rb +2 -0
  222. data/lib/active_record/type_caster/map.rb +3 -1
  223. data/lib/active_record/type_caster.rb +2 -0
  224. data/lib/active_record/validations/absence.rb +2 -0
  225. data/lib/active_record/validations/associated.rb +2 -0
  226. data/lib/active_record/validations/length.rb +2 -0
  227. data/lib/active_record/validations/presence.rb +2 -0
  228. data/lib/active_record/validations/uniqueness.rb +35 -5
  229. data/lib/active_record/validations.rb +2 -0
  230. data/lib/active_record/version.rb +2 -0
  231. data/lib/active_record.rb +11 -4
  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/migration_generator.rb +3 -1
  235. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  236. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration.rb +2 -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. data/lib/rails/generators/active_record.rb +3 -1
  242. metadata +25 -37
  243. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  244. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  245. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  246. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  247. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  248. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  249. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  250. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  251. data/lib/active_record/attribute.rb +0 -240
  252. data/lib/active_record/attribute_mutation_tracker.rb +0 -113
  253. data/lib/active_record/attribute_set/builder.rb +0 -124
  254. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  255. data/lib/active_record/attribute_set.rb +0 -113
  256. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  257. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  258. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  259. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  260. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -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,8 +20,9 @@ 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
@@ -33,74 +36,6 @@ module ActiveRecord
33
36
  reset
34
37
  end
35
38
 
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, id, id_was) # :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(@klass.primary_key => (id_was || id))
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
39
  def arel_attribute(name) # :nodoc:
105
40
  klass.arel_attribute(name, table)
106
41
  end
@@ -117,8 +52,8 @@ module ActiveRecord
117
52
  #
118
53
  # user = users.new { |user| user.name = 'Oscar' }
119
54
  # user.name # => Oscar
120
- def new(*args, &block)
121
- scoping { @klass.new(*args, &block) }
55
+ def new(attributes = nil, &block)
56
+ scoping { klass.new(scope_for_create(attributes), &block) }
122
57
  end
123
58
 
124
59
  alias build new
@@ -142,8 +77,12 @@ module ActiveRecord
142
77
  #
143
78
  # users.create(name: nil) # validation on name
144
79
  # # => #<User id: nil, name: nil, ...>
145
- def create(*args, &block)
146
- scoping { @klass.create(*args, &block) }
80
+ def create(attributes = nil, &block)
81
+ if attributes.is_a?(Array)
82
+ attributes.collect { |attr| create(attr, &block) }
83
+ else
84
+ scoping { klass.create(scope_for_create(attributes), &block) }
85
+ end
147
86
  end
148
87
 
149
88
  # Similar to #create, but calls
@@ -152,8 +91,12 @@ module ActiveRecord
152
91
  #
153
92
  # Expects arguments in the same format as
154
93
  # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!].
155
- def create!(*args, &block)
156
- scoping { @klass.create!(*args, &block) }
94
+ def create!(attributes = nil, &block)
95
+ if attributes.is_a?(Array)
96
+ attributes.collect { |attr| create!(attr, &block) }
97
+ else
98
+ scoping { klass.create!(scope_for_create(attributes), &block) }
99
+ end
157
100
  end
158
101
 
159
102
  def first_or_create(attributes = nil, &block) # :nodoc:
@@ -247,9 +190,10 @@ module ActiveRecord
247
190
  end
248
191
 
249
192
  # Converts relation objects to Array.
250
- def to_a
193
+ def to_ary
251
194
  records.dup
252
195
  end
196
+ alias to_a to_ary
253
197
 
254
198
  def records # :nodoc:
255
199
  load
@@ -269,8 +213,7 @@ module ActiveRecord
269
213
  # Returns true if there are no records.
270
214
  def empty?
271
215
  return @records.empty? if loaded?
272
-
273
- limit_value == 0 || !exists?
216
+ !exists?
274
217
  end
275
218
 
276
219
  # Returns true if there are no records.
@@ -333,7 +276,7 @@ module ActiveRecord
333
276
  # Please check unscoped if you want to remove all previous scopes (including
334
277
  # the default_scope) during the execution of a block.
335
278
  def scoping
336
- previous, klass.current_scope = klass.current_scope, self
279
+ previous, klass.current_scope = klass.current_scope(true), self
337
280
  yield
338
281
  ensure
339
282
  klass.current_scope = previous
@@ -364,12 +307,17 @@ module ActiveRecord
364
307
  def update_all(updates)
365
308
  raise ArgumentError, "Empty list of attributes to change" if updates.blank?
366
309
 
310
+ if eager_loading?
311
+ relation = apply_join_dependency
312
+ return relation.update_all(updates)
313
+ end
314
+
367
315
  stmt = Arel::UpdateManager.new
368
316
 
369
- stmt.set Arel.sql(@klass.send(:sanitize_sql_for_assignment, updates))
317
+ stmt.set Arel.sql(@klass.sanitize_sql_for_assignment(updates))
370
318
  stmt.table(table)
371
319
 
372
- if has_join_values?
320
+ if has_join_values? || offset_value
373
321
  @klass.connection.join_to_update(stmt, arel, arel_attribute(primary_key))
374
322
  else
375
323
  stmt.key = arel_attribute(primary_key)
@@ -378,51 +326,7 @@ module ActiveRecord
378
326
  stmt.wheres = arel.constraints
379
327
  end
380
328
 
381
- @klass.connection.update stmt, "SQL", bound_attributes
382
- end
383
-
384
- # Updates an object (or multiple objects) and saves it to the database, if validations pass.
385
- # The resulting object is returned whether the object was saved successfully to the database or not.
386
- #
387
- # ==== Parameters
388
- #
389
- # * +id+ - This should be the id or an array of ids to be updated.
390
- # * +attributes+ - This should be a hash of attributes or an array of hashes.
391
- #
392
- # ==== Examples
393
- #
394
- # # Updates one record
395
- # Person.update(15, user_name: 'Samuel', group: 'expert')
396
- #
397
- # # Updates multiple records
398
- # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
399
- # Person.update(people.keys, people.values)
400
- #
401
- # # Updates multiple records from the result of a relation
402
- # people = Person.where(group: 'expert')
403
- # people.update(group: 'masters')
404
- #
405
- # Note: Updating a large number of records will run an
406
- # UPDATE query for each record, which may cause a performance
407
- # issue. So if it is not needed to run callbacks for each update, it is
408
- # preferred to use #update_all for updating all records using
409
- # a single query.
410
- def update(id = :all, attributes)
411
- if id.is_a?(Array)
412
- id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) }
413
- elsif id == :all
414
- records.each { |record| record.update(attributes) }
415
- else
416
- if ActiveRecord::Base === id
417
- raise ArgumentError, <<-MSG.squish
418
- You are passing an instance of ActiveRecord::Base to `update`.
419
- Please pass the id of the object by calling `.id`.
420
- MSG
421
- end
422
- object = find(id)
423
- object.update(attributes)
424
- object
425
- end
329
+ @klass.connection.update stmt, "#{@klass} Update All"
426
330
  end
427
331
 
428
332
  # Destroys the records by instantiating each
@@ -445,33 +349,6 @@ module ActiveRecord
445
349
  records.each(&:destroy).tap { reset }
446
350
  end
447
351
 
448
- # Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
449
- # therefore all callbacks and filters are fired off before the object is deleted. This method is
450
- # less efficient than #delete but allows cleanup methods and other actions to be run.
451
- #
452
- # This essentially finds the object (or multiple objects) with the given id, creates a new object
453
- # from the attributes, and then calls destroy on it.
454
- #
455
- # ==== Parameters
456
- #
457
- # * +id+ - Can be either an Integer or an Array of Integers.
458
- #
459
- # ==== Examples
460
- #
461
- # # Destroy a single object
462
- # Todo.destroy(1)
463
- #
464
- # # Destroy multiple objects
465
- # todos = [1,2,3]
466
- # Todo.destroy(todos)
467
- def destroy(id)
468
- if id.is_a?(Array)
469
- id.map { |one_id| destroy(one_id) }
470
- else
471
- find(id).destroy
472
- end
473
- end
474
-
475
352
  # Deletes the records without instantiating the records
476
353
  # first, and hence not calling the {#destroy}[rdoc-ref:Persistence#destroy]
477
354
  # method nor invoking callbacks.
@@ -488,8 +365,8 @@ module ActiveRecord
488
365
  #
489
366
  # If an invalid method is supplied, #delete_all raises an ActiveRecordError:
490
367
  #
491
- # Post.limit(100).delete_all
492
- # # => ActiveRecord::ActiveRecordError: delete_all doesn't support limit
368
+ # Post.distinct.delete_all
369
+ # # => ActiveRecord::ActiveRecordError: delete_all doesn't support distinct
493
370
  def delete_all
494
371
  invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
495
372
  value = get_value(method)
@@ -499,44 +376,26 @@ module ActiveRecord
499
376
  raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
500
377
  end
501
378
 
379
+ if eager_loading?
380
+ relation = apply_join_dependency
381
+ return relation.delete_all
382
+ end
383
+
502
384
  stmt = Arel::DeleteManager.new
503
385
  stmt.from(table)
504
386
 
505
- if has_join_values?
387
+ if has_join_values? || has_limit_or_offset?
506
388
  @klass.connection.join_to_delete(stmt, arel, arel_attribute(primary_key))
507
389
  else
508
390
  stmt.wheres = arel.constraints
509
391
  end
510
392
 
511
- affected = @klass.connection.delete(stmt, "SQL", bound_attributes)
393
+ affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
512
394
 
513
395
  reset
514
396
  affected
515
397
  end
516
398
 
517
- # Deletes the row with a primary key matching the +id+ argument, using a
518
- # SQL +DELETE+ statement, and returns the number of rows deleted. Active
519
- # Record objects are not instantiated, so the object's callbacks are not
520
- # executed, including any <tt>:dependent</tt> association options.
521
- #
522
- # You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
523
- #
524
- # Note: Although it is often much faster than the alternative,
525
- # #destroy, skipping callbacks might bypass business logic in
526
- # your application that ensures referential integrity or performs other
527
- # essential jobs.
528
- #
529
- # ==== Examples
530
- #
531
- # # Delete a single row
532
- # Todo.delete(1)
533
- #
534
- # # Delete multiple rows
535
- # Todo.delete([2,3,4])
536
- def delete(id_or_array)
537
- where(primary_key => id_or_array).delete_all
538
- end
539
-
540
399
  # Causes the records to be loaded from the database if they have not
541
400
  # been loaded already. You can use this if for some reason you need
542
401
  # to explicitly load some records before actually using them. The
@@ -556,8 +415,7 @@ module ActiveRecord
556
415
  end
557
416
 
558
417
  def reset
559
- @last = @to_sql = @order_clause = @scope_for_create = @arel = @loaded = nil
560
- @should_eager_load = @join_dependency = nil
418
+ @to_sql = @arel = @loaded = @should_eager_load = nil
561
419
  @records = [].freeze
562
420
  @offsets = {}
563
421
  self
@@ -572,12 +430,12 @@ module ActiveRecord
572
430
  relation = self
573
431
 
574
432
  if eager_loading?
575
- find_with_associations { |rel| relation = rel }
433
+ apply_join_dependency { |rel, _| relation = rel }
576
434
  end
577
435
 
578
436
  conn = klass.connection
579
437
  conn.unprepared_statement {
580
- conn.to_sql(relation.arel, relation.bound_attributes)
438
+ conn.to_sql(relation.arel)
581
439
  }
582
440
  end
583
441
  end
@@ -586,12 +444,14 @@ module ActiveRecord
586
444
  #
587
445
  # User.where(name: 'Oscar').where_values_hash
588
446
  # # => {name: "Oscar"}
589
- def where_values_hash(relation_table_name = table_name)
447
+ def where_values_hash(relation_table_name = klass.table_name)
590
448
  where_clause.to_h(relation_table_name)
591
449
  end
592
450
 
593
- def scope_for_create
594
- @scope_for_create ||= where_values_hash.merge(create_with_value)
451
+ def scope_for_create(attributes = nil)
452
+ scope = where_values_hash.merge!(create_with_value.stringify_keys)
453
+ scope.merge!(attributes) if attributes
454
+ scope
595
455
  end
596
456
 
597
457
  # Returns true if relation needs eager loading.
@@ -643,6 +503,19 @@ module ActiveRecord
643
503
  "#<#{self.class.name} [#{entries.join(', ')}]>"
644
504
  end
645
505
 
506
+ def empty_scope? # :nodoc:
507
+ @values == klass.unscoped.values
508
+ end
509
+
510
+ def has_limit_or_offset? # :nodoc:
511
+ limit_value || offset_value
512
+ end
513
+
514
+ def alias_tracker(joins = [], aliases = nil) # :nodoc:
515
+ joins += [aliases] if aliases
516
+ ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins)
517
+ end
518
+
646
519
  protected
647
520
 
648
521
  def load_records(records)
@@ -657,20 +530,44 @@ module ActiveRecord
657
530
  end
658
531
 
659
532
  def exec_queries(&block)
660
- @records = eager_loading? ? find_with_associations.freeze : @klass.find_by_sql(arel, bound_attributes, &block).freeze
661
-
662
- preload = preload_values
663
- preload += includes_values unless eager_loading?
664
- preloader = nil
665
- preload.each do |associations|
666
- preloader ||= build_preloader
667
- preloader.preload @records, associations
668
- end
533
+ skip_query_cache_if_necessary do
534
+ @records =
535
+ if eager_loading?
536
+ apply_join_dependency do |relation, join_dependency|
537
+ if ActiveRecord::NullRelation === relation
538
+ []
539
+ else
540
+ rows = connection.select_all(relation.arel, "SQL")
541
+ join_dependency.instantiate(rows, &block)
542
+ end.freeze
543
+ end
544
+ else
545
+ klass.find_by_sql(arel, &block).freeze
546
+ end
547
+
548
+ preload = preload_values
549
+ preload += includes_values unless eager_loading?
550
+ preloader = nil
551
+ preload.each do |associations|
552
+ preloader ||= build_preloader
553
+ preloader.preload @records, associations
554
+ end
669
555
 
670
- @records.each(&:readonly!) if readonly_value
556
+ @records.each(&:readonly!) if readonly_value
671
557
 
672
- @loaded = true
673
- @records
558
+ @loaded = true
559
+ @records
560
+ end
561
+ end
562
+
563
+ def skip_query_cache_if_necessary
564
+ if skip_query_cache_value
565
+ uncached do
566
+ yield
567
+ end
568
+ else
569
+ yield
570
+ end
674
571
  end
675
572
 
676
573
  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