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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +192 -1261
- data/README.rdoc +2 -2
- data/lib/active_record/associations/alias_tracker.rb +4 -6
- data/lib/active_record/associations/association.rb +25 -5
- data/lib/active_record/associations/belongs_to_association.rb +2 -18
- data/lib/active_record/associations/builder/association.rb +7 -6
- data/lib/active_record/associations/collection_association.rb +4 -4
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +4 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +50 -32
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods.rb +19 -24
- data/lib/active_record/attributes.rb +26 -37
- data/lib/active_record/autosave_association.rb +81 -49
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -75
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +14 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +2 -6
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +27 -9
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +27 -57
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +28 -58
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -15
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -16
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +12 -14
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +51 -9
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +44 -101
- data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -13
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +60 -22
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -18
- data/lib/active_record/connection_handling.rb +29 -11
- data/lib/active_record/core.rb +15 -60
- data/lib/active_record/counter_cache.rb +1 -1
- data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -3
- data/lib/active_record/delegated_type.rb +18 -18
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +5 -5
- data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
- data/lib/active_record/encryption/encryptor.rb +35 -29
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +8 -1
- data/lib/active_record/enum.rb +12 -13
- data/lib/active_record/errors.rb +16 -8
- data/lib/active_record/fixture_set/table_row.rb +2 -19
- data/lib/active_record/fixtures.rb +0 -1
- data/lib/active_record/future_result.rb +14 -10
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/insert_all.rb +1 -1
- data/lib/active_record/marshalling.rb +1 -4
- data/lib/active_record/migration/command_recorder.rb +22 -5
- data/lib/active_record/migration/compatibility.rb +5 -2
- data/lib/active_record/migration.rb +36 -35
- data/lib/active_record/model_schema.rb +1 -1
- data/lib/active_record/nested_attributes.rb +4 -6
- data/lib/active_record/persistence.rb +128 -130
- data/lib/active_record/query_cache.rb +5 -4
- data/lib/active_record/query_logs.rb +98 -44
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +10 -10
- data/lib/active_record/railtie.rb +5 -6
- data/lib/active_record/railties/databases.rake +1 -2
- data/lib/active_record/reflection.rb +9 -7
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +132 -72
- data/lib/active_record/relation/calculations.rb +55 -55
- data/lib/active_record/relation/delegation.rb +25 -14
- data/lib/active_record/relation/finder_methods.rb +31 -32
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +0 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +5 -0
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +90 -91
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +2 -8
- data/lib/active_record/relation.rb +77 -76
- data/lib/active_record/result.rb +68 -7
- data/lib/active_record/sanitization.rb +7 -6
- data/lib/active_record/schema_dumper.rb +16 -29
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +6 -7
- data/lib/active_record/statement_cache.rb +12 -12
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +24 -15
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
- data/lib/active_record/test_fixtures.rb +12 -0
- data/lib/active_record/testing/query_assertions.rb +2 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transactions.rb +1 -3
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +16 -1
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/crud.rb +0 -2
- data/lib/arel/delete_manager.rb +0 -5
- data/lib/arel/nodes/delete_statement.rb +2 -4
- data/lib/arel/nodes/update_statement.rb +2 -4
- data/lib/arel/select_manager.rb +2 -6
- data/lib/arel/update_manager.rb +0 -5
- data/lib/arel/visitors/dot.rb +0 -2
- data/lib/arel/visitors/sqlite.rb +0 -25
- data/lib/arel/visitors/to_sql.rb +1 -3
- metadata +14 -11
|
@@ -23,7 +23,7 @@ module ActiveRecord
|
|
|
23
23
|
scope = current_scope
|
|
24
24
|
|
|
25
25
|
if scope
|
|
26
|
-
if self == scope.
|
|
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
|
-
|
|
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
|
-
#
|
|
33
|
+
# === Options
|
|
34
34
|
#
|
|
35
|
-
# [
|
|
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
|
-
# [
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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.
|
|
136
|
+
new(query_builder, bind_map, relation.model)
|
|
137
137
|
end
|
|
138
138
|
|
|
139
|
-
def initialize(query_builder, bind_map,
|
|
139
|
+
def initialize(query_builder, bind_map, model)
|
|
140
140
|
@query_builder = query_builder
|
|
141
141
|
@bind_map = bind_map
|
|
142
|
-
@
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
data/lib/active_record/store.rb
CHANGED
|
@@ -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+,
|
|
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).
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
@@ -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
|
-
#
|
|
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
|
-
#
|
|
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
|
|
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.
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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
|
data/lib/arel/collectors/bind.rb
CHANGED
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?
|
data/lib/arel/delete_manager.rb
CHANGED
|
@@ -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, :
|
|
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, @
|
|
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, :
|
|
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, @
|
|
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?
|
data/lib/arel/select_manager.rb
CHANGED
|
@@ -250,12 +250,8 @@ module Arel # :nodoc: all
|
|
|
250
250
|
end
|
|
251
251
|
|
|
252
252
|
def comment(*values)
|
|
253
|
-
|
|
254
|
-
|
|
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
|
data/lib/arel/update_manager.rb
CHANGED
data/lib/arel/visitors/dot.rb
CHANGED
|
@@ -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
|
|
data/lib/arel/visitors/sqlite.rb
CHANGED
|
@@ -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
|
data/lib/arel/visitors/to_sql.rb
CHANGED
|
@@ -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
|
|
766
|
+
collector.retryable = o.retryable
|
|
769
767
|
collector << o.to_s
|
|
770
768
|
end
|
|
771
769
|
|