activerecord 7.2.3 → 8.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +192 -1261
  3. data/README.rdoc +2 -2
  4. data/lib/active_record/associations/alias_tracker.rb +4 -6
  5. data/lib/active_record/associations/association.rb +25 -5
  6. data/lib/active_record/associations/belongs_to_association.rb +2 -18
  7. data/lib/active_record/associations/builder/association.rb +7 -6
  8. data/lib/active_record/associations/collection_association.rb +4 -4
  9. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  10. data/lib/active_record/associations/has_many_through_association.rb +4 -9
  11. data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
  12. data/lib/active_record/associations/preloader/association.rb +2 -2
  13. data/lib/active_record/associations/singular_association.rb +8 -3
  14. data/lib/active_record/associations.rb +50 -32
  15. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  16. data/lib/active_record/attribute_methods/serialization.rb +1 -1
  17. data/lib/active_record/attribute_methods.rb +19 -24
  18. data/lib/active_record/attributes.rb +26 -37
  19. data/lib/active_record/autosave_association.rb +81 -49
  20. data/lib/active_record/base.rb +2 -2
  21. data/lib/active_record/callbacks.rb +1 -1
  22. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
  23. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
  24. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
  25. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -75
  26. data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
  27. data/lib/active_record/connection_adapters/abstract/query_cache.rb +14 -19
  28. data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
  29. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +2 -6
  30. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +27 -9
  31. data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
  32. data/lib/active_record/connection_adapters/abstract_adapter.rb +27 -57
  33. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +28 -58
  34. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -15
  35. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
  36. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
  37. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
  38. data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -16
  39. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
  40. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  41. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +0 -1
  42. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +12 -14
  43. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
  44. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +51 -9
  45. data/lib/active_record/connection_adapters/postgresql_adapter.rb +44 -101
  46. data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
  47. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
  48. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -13
  49. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  50. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
  51. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -2
  52. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +60 -22
  53. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
  54. data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -18
  55. data/lib/active_record/connection_handling.rb +29 -11
  56. data/lib/active_record/core.rb +15 -60
  57. data/lib/active_record/counter_cache.rb +1 -1
  58. data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -3
  59. data/lib/active_record/delegated_type.rb +18 -18
  60. data/lib/active_record/encryption/config.rb +3 -1
  61. data/lib/active_record/encryption/encryptable_record.rb +5 -5
  62. data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
  63. data/lib/active_record/encryption/encryptor.rb +35 -29
  64. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  65. data/lib/active_record/encryption/scheme.rb +8 -1
  66. data/lib/active_record/enum.rb +12 -13
  67. data/lib/active_record/errors.rb +16 -8
  68. data/lib/active_record/fixture_set/table_row.rb +2 -19
  69. data/lib/active_record/fixtures.rb +0 -1
  70. data/lib/active_record/future_result.rb +14 -10
  71. data/lib/active_record/gem_version.rb +4 -4
  72. data/lib/active_record/insert_all.rb +1 -1
  73. data/lib/active_record/marshalling.rb +1 -4
  74. data/lib/active_record/migration/command_recorder.rb +22 -5
  75. data/lib/active_record/migration/compatibility.rb +5 -2
  76. data/lib/active_record/migration.rb +36 -35
  77. data/lib/active_record/model_schema.rb +1 -1
  78. data/lib/active_record/nested_attributes.rb +4 -6
  79. data/lib/active_record/persistence.rb +128 -130
  80. data/lib/active_record/query_cache.rb +5 -4
  81. data/lib/active_record/query_logs.rb +98 -44
  82. data/lib/active_record/query_logs_formatter.rb +17 -28
  83. data/lib/active_record/querying.rb +10 -10
  84. data/lib/active_record/railtie.rb +5 -6
  85. data/lib/active_record/railties/databases.rake +1 -2
  86. data/lib/active_record/reflection.rb +9 -7
  87. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  88. data/lib/active_record/relation/batches.rb +132 -72
  89. data/lib/active_record/relation/calculations.rb +55 -55
  90. data/lib/active_record/relation/delegation.rb +25 -14
  91. data/lib/active_record/relation/finder_methods.rb +31 -32
  92. data/lib/active_record/relation/merger.rb +8 -8
  93. data/lib/active_record/relation/predicate_builder/association_query_value.rb +0 -2
  94. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
  95. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  96. data/lib/active_record/relation/predicate_builder.rb +5 -0
  97. data/lib/active_record/relation/query_attribute.rb +1 -1
  98. data/lib/active_record/relation/query_methods.rb +90 -91
  99. data/lib/active_record/relation/record_fetch_warning.rb +2 -2
  100. data/lib/active_record/relation/spawn_methods.rb +1 -1
  101. data/lib/active_record/relation/where_clause.rb +2 -8
  102. data/lib/active_record/relation.rb +77 -76
  103. data/lib/active_record/result.rb +68 -7
  104. data/lib/active_record/sanitization.rb +7 -6
  105. data/lib/active_record/schema_dumper.rb +16 -29
  106. data/lib/active_record/schema_migration.rb +2 -1
  107. data/lib/active_record/scoping/named.rb +5 -2
  108. data/lib/active_record/secure_token.rb +3 -3
  109. data/lib/active_record/signed_id.rb +6 -7
  110. data/lib/active_record/statement_cache.rb +12 -12
  111. data/lib/active_record/store.rb +7 -3
  112. data/lib/active_record/tasks/database_tasks.rb +24 -15
  113. data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
  114. data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -7
  115. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
  116. data/lib/active_record/test_fixtures.rb +12 -0
  117. data/lib/active_record/testing/query_assertions.rb +2 -2
  118. data/lib/active_record/token_for.rb +1 -1
  119. data/lib/active_record/transactions.rb +1 -3
  120. data/lib/active_record/validations/uniqueness.rb +8 -8
  121. data/lib/active_record.rb +16 -1
  122. data/lib/arel/collectors/bind.rb +1 -1
  123. data/lib/arel/crud.rb +0 -2
  124. data/lib/arel/delete_manager.rb +0 -5
  125. data/lib/arel/nodes/delete_statement.rb +2 -4
  126. data/lib/arel/nodes/update_statement.rb +2 -4
  127. data/lib/arel/select_manager.rb +2 -6
  128. data/lib/arel/update_manager.rb +0 -5
  129. data/lib/arel/visitors/dot.rb +0 -2
  130. data/lib/arel/visitors/sqlite.rb +0 -25
  131. data/lib/arel/visitors/to_sql.rb +1 -3
  132. metadata +14 -11
@@ -23,7 +23,7 @@ module ActiveRecord
23
23
  scope = current_scope
24
24
 
25
25
  if scope
26
- if self == scope.klass
26
+ if self == scope.model
27
27
  scope.clone
28
28
  else
29
29
  relation.merge!(scope)
@@ -191,7 +191,10 @@ module ActiveRecord
191
191
  private
192
192
  def singleton_method_added(name)
193
193
  super
194
- generate_relation_method(name) if Kernel.respond_to?(name) && !ActiveRecord::Relation.method_defined?(name)
194
+ # Most Kernel extends are both singleton and instance methods so
195
+ # respond_to is a fast check, but we don't want to define methods
196
+ # only on the module (ex. Module#name)
197
+ generate_relation_method(name) if Kernel.respond_to?(name) && (Kernel.method_defined?(name) || Kernel.private_method_defined?(name)) && !ActiveRecord::Relation.method_defined?(name)
195
198
  end
196
199
  end
197
200
  end
@@ -30,13 +30,13 @@ module ActiveRecord
30
30
  # {validates_uniqueness_of}[rdoc-ref:Validations::ClassMethods#validates_uniqueness_of] can.
31
31
  # You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
32
32
  #
33
- # ==== Options
33
+ # === Options
34
34
  #
35
- # [+:length+]
35
+ # [:length]
36
36
  # Length of the Secure Random, with a minimum of 24 characters. It will
37
37
  # default to 24.
38
38
  #
39
- # [+:on+]
39
+ # [:on]
40
40
  # The callback when the value is generated. When called with <tt>on:
41
41
  # :initialize</tt>, the value is generated in an
42
42
  # <tt>after_initialize</tt> callback, otherwise the value will be used
@@ -57,12 +57,12 @@ module ActiveRecord
57
57
  end
58
58
  end
59
59
 
60
- # Works like find_signed, but will raise an ActiveSupport::MessageVerifier::InvalidSignature
60
+ # Works like find_signed, but will raise an +ActiveSupport::MessageVerifier::InvalidSignature+
61
61
  # exception if the +signed_id+ has either expired, has a purpose mismatch, is for another record,
62
- # or has been tampered with. It will also raise an ActiveRecord::RecordNotFound exception if
62
+ # or has been tampered with. It will also raise an +ActiveRecord::RecordNotFound+ exception if
63
63
  # the valid signed id can't find a record.
64
64
  #
65
- # ==== Examples
65
+ # === Examples
66
66
  #
67
67
  # User.find_signed! "bad data" # => ActiveSupport::MessageVerifier::InvalidSignature
68
68
  #
@@ -76,9 +76,8 @@ module ActiveRecord
76
76
  end
77
77
 
78
78
  # The verifier instance that all signed ids are generated and verified from. By default, it'll be initialized
79
- # with the class-level +signed_id_verifier_secret+, which within Rails comes from
80
- # {Rails.application.key_generator}[rdoc-ref:Rails::Application#key_generator].
81
- # By default, it's SHA256 for the digest and JSON for the serialization.
79
+ # with the class-level +signed_id_verifier_secret+, which within \Rails comes from the
80
+ # Rails.application.key_generator. By default, it's SHA256 for the digest and JSON for the serialization.
82
81
  def signed_id_verifier
83
82
  @signed_id_verifier ||= begin
84
83
  secret = signed_id_verifier_secret
@@ -94,7 +93,7 @@ module ActiveRecord
94
93
 
95
94
  # Allows you to pass in a custom verifier used for the signed ids. This also allows you to use different
96
95
  # verifiers for different classes. This is also helpful if you need to rotate keys, as you can prepare
97
- # your custom verifier for that in advance. See ActiveSupport::MessageVerifier for details.
96
+ # your custom verifier for that in advance. See +ActiveSupport::MessageVerifier+ for details.
98
97
  def signed_id_verifier=(verifier)
99
98
  @signed_id_verifier = verifier
100
99
  end
@@ -133,23 +133,26 @@ module ActiveRecord
133
133
  relation = (callable || block).call Params.new
134
134
  query_builder, binds = connection.cacheable_query(self, relation.arel)
135
135
  bind_map = BindMap.new(binds)
136
- new(query_builder, bind_map, relation.klass)
136
+ new(query_builder, bind_map, relation.model)
137
137
  end
138
138
 
139
- def initialize(query_builder, bind_map, klass)
139
+ def initialize(query_builder, bind_map, model)
140
140
  @query_builder = query_builder
141
141
  @bind_map = bind_map
142
- @klass = klass
142
+ @model = model
143
143
  end
144
144
 
145
- def execute(params, connection, allow_retry: false, &block)
146
- bind_values = bind_map.bind params
145
+ def execute(params, connection, allow_retry: false, async: false, &block)
146
+ bind_values = @bind_map.bind params
147
+ sql = @query_builder.sql_for bind_values, connection
147
148
 
148
- sql = query_builder.sql_for bind_values, connection
149
-
150
- klass.find_by_sql(sql, bind_values, preparable: true, allow_retry: allow_retry, &block)
149
+ if async
150
+ @model.async_find_by_sql(sql, bind_values, preparable: true, allow_retry: allow_retry, &block)
151
+ else
152
+ @model.find_by_sql(sql, bind_values, preparable: true, allow_retry: allow_retry, &block)
153
+ end
151
154
  rescue ::RangeError
152
- []
155
+ async ? Promise.wrap([]) : []
153
156
  end
154
157
 
155
158
  def self.unsupported_value?(value)
@@ -157,8 +160,5 @@ module ActiveRecord
157
160
  when NilClass, Array, Range, Hash, Relation, Base then true
158
161
  end
159
162
  end
160
-
161
- private
162
- attr_reader :query_builder, :bind_map, :klass
163
163
  end
164
164
  end
@@ -25,8 +25,8 @@ module ActiveRecord
25
25
  # You can set custom coder to encode/decode your serialized attributes to/from different formats.
26
26
  # JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
27
27
  #
28
- # NOTE: If you are using structured database data types (e.g. PostgreSQL +hstore+/+json+, or MySQL 5.7+
29
- # +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
28
+ # NOTE: If you are using structured database data types (e.g. PostgreSQL +hstore+/+json+, MySQL 5.7+
29
+ # +json+, or SQLite 3.38+ +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
30
30
  # Simply use {.store_accessor}[rdoc-ref:ClassMethods#store_accessor] instead to generate
31
31
  # the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
32
32
  # using a symbol.
@@ -217,7 +217,11 @@ module ActiveRecord
217
217
  end
218
218
 
219
219
  def store_accessor_for(store_attribute)
220
- type_for_attribute(store_attribute).accessor
220
+ type_for_attribute(store_attribute).tap do |type|
221
+ unless type.respond_to?(:accessor)
222
+ raise ConfigurationError, "the column '#{store_attribute}' has not been configured as a store. Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your database supports it, use a structured column type like hstore or json."
223
+ end
224
+ end.accessor
221
225
  end
222
226
 
223
227
  class HashAccessor # :nodoc:
@@ -178,22 +178,9 @@ module ActiveRecord
178
178
  dump_db_configs = []
179
179
 
180
180
  each_current_configuration(env) do |db_config|
181
- with_temporary_pool(db_config) do
182
- begin
183
- database_initialized = migration_connection_pool.schema_migration.table_exists?
184
- rescue ActiveRecord::NoDatabaseError
185
- create(db_config)
186
- retry
187
- end
181
+ database_initialized = initialize_database(db_config)
188
182
 
189
- unless database_initialized
190
- if File.exist?(schema_dump_path(db_config))
191
- load_schema(db_config, ActiveRecord.schema_format, nil)
192
- end
193
-
194
- seed = true
195
- end
196
- end
183
+ seed = true if database_initialized
197
184
  end
198
185
 
199
186
  each_current_environment(env) do |environment|
@@ -259,6 +246,8 @@ module ActiveRecord
259
246
 
260
247
  check_target_version
261
248
 
249
+ initialize_database(migration_connection_pool.db_config)
250
+
262
251
  migration_connection_pool.migration_context.migrate(target_version) do |migration|
263
252
  if version.blank?
264
253
  scope.blank? || scope == migration.scope
@@ -667,6 +656,26 @@ module ActiveRecord
667
656
  rescue ActiveRecord::NoDatabaseError
668
657
  end
669
658
  end
659
+
660
+ def initialize_database(db_config)
661
+ with_temporary_pool(db_config) do
662
+ begin
663
+ database_already_initialized = migration_connection_pool.schema_migration.table_exists?
664
+ rescue ActiveRecord::NoDatabaseError
665
+ create(db_config)
666
+ retry
667
+ end
668
+
669
+ unless database_already_initialized
670
+ schema_dump_path = schema_dump_path(db_config)
671
+ if schema_dump_path && File.exist?(schema_dump_path)
672
+ load_schema(db_config, ActiveRecord.schema_format, nil)
673
+ end
674
+ end
675
+
676
+ !database_already_initialized
677
+ end
678
+ end
670
679
  end
671
680
  end
672
681
  end
@@ -3,8 +3,6 @@
3
3
  module ActiveRecord
4
4
  module Tasks # :nodoc:
5
5
  class MySQLDatabaseTasks # :nodoc:
6
- ER_DB_CREATE_EXISTS = 1007
7
-
8
6
  def self.using_database_configurations?
9
7
  true
10
8
  end
@@ -132,13 +132,6 @@ module ActiveRecord
132
132
  tempfile = Tempfile.open("uncommented_structure.sql")
133
133
  begin
134
134
  File.foreach(filename) do |line|
135
- next if line.start_with?("\\restrict ")
136
-
137
- if line.start_with?("\\unrestrict ")
138
- removing_comments = true
139
- next
140
- end
141
-
142
135
  unless removing_comments && (line.start_with?(SQL_COMMENT_BEGIN) || line.blank?)
143
136
  tempfile << line
144
137
  removing_comments = false
@@ -50,9 +50,9 @@ module ActiveRecord
50
50
  if ignore_tables.any?
51
51
  ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
52
52
  condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
53
- args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
53
+ args << "SELECT sql || ';' FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
54
54
  else
55
- args << ".schema"
55
+ args << ".schema --nosys"
56
56
  end
57
57
  run_cmd("sqlite3", args, filename)
58
58
  end
@@ -137,12 +137,15 @@ module ActiveRecord
137
137
  invalidate_already_loaded_fixtures
138
138
  @loaded_fixtures = load_fixtures(config)
139
139
  end
140
+ setup_asynchronous_queries_session
140
141
 
141
142
  # Instantiate fixtures for every test if requested.
142
143
  instantiate_fixtures if use_instantiated_fixtures
143
144
  end
144
145
 
145
146
  def teardown_fixtures
147
+ teardown_asynchronous_queries_session
148
+
146
149
  # Rollback changes if a transaction is active.
147
150
  if run_in_transaction?
148
151
  teardown_transactional_fixtures
@@ -154,6 +157,14 @@ module ActiveRecord
154
157
  ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
155
158
  end
156
159
 
160
+ def setup_asynchronous_queries_session
161
+ @_async_queries_session = ActiveRecord::Base.asynchronous_queries_tracker.start_session
162
+ end
163
+
164
+ def teardown_asynchronous_queries_session
165
+ ActiveRecord::Base.asynchronous_queries_tracker.finalize_session(true) if @_async_queries_session
166
+ end
167
+
157
168
  def invalidate_already_loaded_fixtures
158
169
  @@already_loaded_fixtures.clear
159
170
  end
@@ -190,6 +201,7 @@ module ActiveRecord
190
201
 
191
202
  def teardown_transactional_fixtures
192
203
  ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
204
+
193
205
  unless @fixture_connection_pools.map(&:unpin_connection!).all?
194
206
  # Something caused the transaction to be committed or rolled back
195
207
  # We can no longer trust the database is in a clean state.
@@ -52,7 +52,7 @@ module ActiveRecord
52
52
  # assert_queries_match(/LIMIT \?/) { Post.first }
53
53
  #
54
54
  # If the +:include_schema+ option is provided, any queries (including schema related)
55
- # that match the matcher are considered.
55
+ # that match the matcher are considered.
56
56
  #
57
57
  # assert_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
58
58
  #
@@ -80,7 +80,7 @@ module ActiveRecord
80
80
  # assert_no_queries_match(/SELECT/i) { post.comments }
81
81
  #
82
82
  # If the +:include_schema+ option is provided, any queries (including schema related)
83
- # that match the matcher are counted.
83
+ # that match the matcher are counted.
84
84
  #
85
85
  # assert_no_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
86
86
  #
@@ -40,7 +40,7 @@ module ActiveRecord
40
40
  # +nil+ if the token is invalid or the record was not found.
41
41
  def find_by_token_for(purpose, token)
42
42
  raise UnknownPrimaryKey.new(self) unless model.primary_key
43
- model.token_definitions.fetch(purpose).resolve_token(token) { |id| find_by(model.primary_key => id) }
43
+ model.token_definitions.fetch(purpose).resolve_token(token) { |id| find_by(model.primary_key => [id]) }
44
44
  end
45
45
 
46
46
  # Finds a record using a given +token+ for a predefined +purpose+. Raises
@@ -13,7 +13,7 @@ module ActiveRecord
13
13
  scope: [:kind, :name]
14
14
  end
15
15
 
16
- attr_accessor :_new_record_before_last_commit, :_last_transaction_return_status # :nodoc:
16
+ attr_accessor :_new_record_before_last_commit # :nodoc:
17
17
 
18
18
  # = Active Record \Transactions
19
19
  #
@@ -418,7 +418,6 @@ module ActiveRecord
418
418
  status = yield
419
419
  raise ActiveRecord::Rollback unless status
420
420
  end
421
- @_last_transaction_return_status = status
422
421
  status
423
422
  end
424
423
  end
@@ -434,7 +433,6 @@ module ActiveRecord
434
433
  def init_internals
435
434
  super
436
435
  @_start_transaction_state = nil
437
- @_last_transaction_return_status = nil
438
436
  @_committed_already_called = nil
439
437
  @_new_record_before_last_commit = nil
440
438
  end
@@ -54,17 +54,17 @@ module ActiveRecord
54
54
  private
55
55
  # The check for an existing value should be run from a class that
56
56
  # isn't abstract. This means working down from the current class
57
- # (self), to the first non-abstract class. Since classes don't know
58
- # their subclasses, we have to build the hierarchy between self and
59
- # the record's class.
57
+ # (self), to the first non-abstract class.
60
58
  def find_finder_class_for(record)
61
- class_hierarchy = [record.class]
62
-
63
- while class_hierarchy.first != @klass
64
- class_hierarchy.unshift(class_hierarchy.first.superclass)
59
+ current_class = record.class
60
+ found_class = nil
61
+ loop do
62
+ found_class = current_class unless current_class.abstract_class?
63
+ break if current_class == @klass
64
+ current_class = current_class.superclass
65
65
  end
66
66
 
67
- class_hierarchy.detect { |klass| !klass.abstract_class? }
67
+ found_class
68
68
  end
69
69
 
70
70
  def validation_needed?(klass, record, attribute)
data/lib/active_record.rb CHANGED
@@ -29,6 +29,7 @@ require "active_support/ordered_options"
29
29
  require "active_model"
30
30
  require "arel"
31
31
  require "yaml"
32
+ require "zlib"
32
33
 
33
34
  require "active_record/version"
34
35
  require "active_record/deprecator"
@@ -86,6 +87,7 @@ module ActiveRecord
86
87
  autoload :Timestamp
87
88
  autoload :TokenFor
88
89
  autoload :TouchLater
90
+ autoload :Transaction
89
91
  autoload :Transactions
90
92
  autoload :Translation
91
93
  autoload :Validations
@@ -107,7 +109,6 @@ module ActiveRecord
107
109
  autoload :Result
108
110
  autoload :StatementCache
109
111
  autoload :TableMetadata
110
- autoload :Transaction
111
112
  autoload :Type
112
113
 
113
114
  autoload_under "relation" do
@@ -196,6 +197,20 @@ module ActiveRecord
196
197
  singleton_class.attr_accessor :schema_cache_ignored_tables
197
198
  self.schema_cache_ignored_tables = []
198
199
 
200
+ # Checks to see if the +table_name+ is ignored by checking
201
+ # against the +schema_cache_ignored_tables+ option.
202
+ #
203
+ # ActiveRecord.schema_cache_ignored_table?(:developers)
204
+ #
205
+ def self.schema_cache_ignored_table?(table_name)
206
+ ActiveRecord.schema_cache_ignored_tables.any? do |ignored|
207
+ ignored === table_name
208
+ end
209
+ end
210
+
211
+ singleton_class.attr_accessor :database_cli
212
+ self.database_cli = { postgresql: "psql", mysql: %w[mysql mysql5], sqlite: "sqlite3" }
213
+
199
214
  singleton_class.attr_reader :default_timezone
200
215
 
201
216
  # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
@@ -13,7 +13,7 @@ module Arel # :nodoc: all
13
13
  self
14
14
  end
15
15
 
16
- def add_bind(bind, &block)
16
+ def add_bind(bind, &)
17
17
  @binds << bind
18
18
  self
19
19
  end
data/lib/arel/crud.rb CHANGED
@@ -26,7 +26,6 @@ module Arel # :nodoc: all
26
26
  um.offset(offset)
27
27
  um.order(*orders)
28
28
  um.wheres = constraints
29
- um.comment(comment)
30
29
  um.key = key
31
30
 
32
31
  um.group(group_values_columns) unless group_values_columns.empty?
@@ -40,7 +39,6 @@ module Arel # :nodoc: all
40
39
  dm.offset(offset)
41
40
  dm.order(*orders)
42
41
  dm.wheres = constraints
43
- dm.comment(comment)
44
42
  dm.key = key
45
43
  dm.group(group_values_columns) unless group_values_columns.empty?
46
44
  dm.having(having_clause) unless having_clause.nil?
@@ -28,10 +28,5 @@ module Arel # :nodoc: all
28
28
  @ast.havings << expr
29
29
  self
30
30
  end
31
-
32
- def comment(value)
33
- @ast.comment = value
34
- self
35
- end
36
31
  end
37
32
  end
@@ -3,7 +3,7 @@
3
3
  module Arel # :nodoc: all
4
4
  module Nodes
5
5
  class DeleteStatement < Arel::Nodes::Node
6
- attr_accessor :relation, :wheres, :groups, :havings, :orders, :limit, :offset, :comment, :key
6
+ attr_accessor :relation, :wheres, :groups, :havings, :orders, :limit, :offset, :key
7
7
 
8
8
  def initialize(relation = nil, wheres = [])
9
9
  super()
@@ -14,7 +14,6 @@ module Arel # :nodoc: all
14
14
  @orders = []
15
15
  @limit = nil
16
16
  @offset = nil
17
- @comment = nil
18
17
  @key = nil
19
18
  end
20
19
 
@@ -25,7 +24,7 @@ module Arel # :nodoc: all
25
24
  end
26
25
 
27
26
  def hash
28
- [self.class, @relation, @wheres, @orders, @limit, @offset, @comment, @key].hash
27
+ [self.class, @relation, @wheres, @orders, @limit, @offset, @key].hash
29
28
  end
30
29
 
31
30
  def eql?(other)
@@ -37,7 +36,6 @@ module Arel # :nodoc: all
37
36
  self.havings == other.havings &&
38
37
  self.limit == other.limit &&
39
38
  self.offset == other.offset &&
40
- self.comment == other.comment &&
41
39
  self.key == other.key
42
40
  end
43
41
  alias :== :eql?
@@ -3,7 +3,7 @@
3
3
  module Arel # :nodoc: all
4
4
  module Nodes
5
5
  class UpdateStatement < Arel::Nodes::Node
6
- attr_accessor :relation, :wheres, :values, :groups, :havings, :orders, :limit, :offset, :comment, :key
6
+ attr_accessor :relation, :wheres, :values, :groups, :havings, :orders, :limit, :offset, :key
7
7
 
8
8
  def initialize(relation = nil)
9
9
  super()
@@ -15,7 +15,6 @@ module Arel # :nodoc: all
15
15
  @orders = []
16
16
  @limit = nil
17
17
  @offset = nil
18
- @comment = nil
19
18
  @key = nil
20
19
  end
21
20
 
@@ -26,7 +25,7 @@ module Arel # :nodoc: all
26
25
  end
27
26
 
28
27
  def hash
29
- [@relation, @wheres, @values, @orders, @limit, @offset, @comment, @key].hash
28
+ [@relation, @wheres, @values, @orders, @limit, @offset, @key].hash
30
29
  end
31
30
 
32
31
  def eql?(other)
@@ -39,7 +38,6 @@ module Arel # :nodoc: all
39
38
  self.orders == other.orders &&
40
39
  self.limit == other.limit &&
41
40
  self.offset == other.offset &&
42
- self.comment == other.comment &&
43
41
  self.key == other.key
44
42
  end
45
43
  alias :== :eql?
@@ -250,12 +250,8 @@ module Arel # :nodoc: all
250
250
  end
251
251
 
252
252
  def comment(*values)
253
- if values.any?
254
- @ctx.comment = Nodes::Comment.new(values)
255
- self
256
- else
257
- @ctx.comment
258
- end
253
+ @ctx.comment = Nodes::Comment.new(values)
254
+ self
259
255
  end
260
256
 
261
257
  private
@@ -45,10 +45,5 @@ module Arel # :nodoc: all
45
45
  @ast.havings << expr
46
46
  self
47
47
  end
48
-
49
- def comment(value)
50
- @ast.comment = value
51
- self
52
- end
53
48
  end
54
49
  end
@@ -153,7 +153,6 @@ module Arel # :nodoc: all
153
153
  visit_edge o, "orders"
154
154
  visit_edge o, "limit"
155
155
  visit_edge o, "offset"
156
- visit_edge o, "comment"
157
156
  visit_edge o, "key"
158
157
  end
159
158
 
@@ -163,7 +162,6 @@ module Arel # :nodoc: all
163
162
  visit_edge o, "orders"
164
163
  visit_edge o, "limit"
165
164
  visit_edge o, "offset"
166
- visit_edge o, "comment"
167
165
  visit_edge o, "key"
168
166
  end
169
167
 
@@ -33,31 +33,6 @@ module Arel # :nodoc: all
33
33
  collector << " IS NOT "
34
34
  visit o.right, collector
35
35
  end
36
-
37
- # Queries used in UNION should not be wrapped by parentheses,
38
- # because it is an invalid syntax in SQLite.
39
- def infix_value_with_paren(o, collector, value, suppress_parens = false)
40
- collector << "( " unless suppress_parens
41
-
42
- left = o.left.is_a?(Nodes::Grouping) ? o.left.expr : o.left
43
- collector = if left.class == o.class
44
- infix_value_with_paren(left, collector, value, true)
45
- else
46
- grouping_parentheses left, collector, false
47
- end
48
-
49
- collector << value
50
-
51
- right = o.right.is_a?(Nodes::Grouping) ? o.right.expr : o.right
52
- collector = if right.class == o.class
53
- infix_value_with_paren(right, collector, value, true)
54
- else
55
- grouping_parentheses right, collector, false
56
- end
57
-
58
- collector << " )" unless suppress_parens
59
- collector
60
- end
61
36
  end
62
37
  end
63
38
  end
@@ -35,7 +35,6 @@ module Arel # :nodoc: all
35
35
  collect_nodes_for o.wheres, collector, " WHERE ", " AND "
36
36
  collect_nodes_for o.orders, collector, " ORDER BY "
37
37
  maybe_visit o.limit, collector
38
- maybe_visit o.comment, collector
39
38
  end
40
39
 
41
40
  def visit_Arel_Nodes_UpdateStatement(o, collector)
@@ -49,7 +48,6 @@ module Arel # :nodoc: all
49
48
  collect_nodes_for o.wheres, collector, " WHERE ", " AND "
50
49
  collect_nodes_for o.orders, collector, " ORDER BY "
51
50
  maybe_visit o.limit, collector
52
- maybe_visit o.comment, collector
53
51
  end
54
52
 
55
53
  def visit_Arel_Nodes_InsertStatement(o, collector)
@@ -765,7 +763,7 @@ module Arel # :nodoc: all
765
763
 
766
764
  def visit_Arel_Nodes_SqlLiteral(o, collector)
767
765
  collector.preparable = false
768
- collector.retryable &&= o.retryable
766
+ collector.retryable = o.retryable
769
767
  collector << o.to_s
770
768
  end
771
769