aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/associations/association.rb4
-rw-r--r--activerecord/lib/active_record/associations/singular_association.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb21
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/transaction.rb18
-rw-r--r--activerecord/lib/active_record/connection_adapters/connection_specification.rb21
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_creation.rb36
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb30
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb38
-rw-r--r--activerecord/lib/active_record/core.rb9
-rw-r--r--activerecord/lib/active_record/gem_version.rb2
-rw-r--r--activerecord/lib/active_record/integration.rb15
-rw-r--r--activerecord/lib/active_record/migration.rb7
-rw-r--r--activerecord/lib/active_record/migration/compatibility.rb4
-rw-r--r--activerecord/lib/active_record/railtie.rb41
-rw-r--r--activerecord/lib/active_record/railties/databases.rake4
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb20
-rw-r--r--activerecord/lib/active_record/relation/delegation.rb9
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb10
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb23
-rw-r--r--activerecord/lib/active_record/relation/query_attribute.rb19
-rw-r--r--activerecord/lib/active_record/sanitization.rb37
-rw-r--r--activerecord/lib/active_record/statement_cache.rb2
-rw-r--r--activerecord/lib/active_record/timestamp.rb7
-rw-r--r--activerecord/lib/active_record/validations/uniqueness.rb2
-rw-r--r--activerecord/lib/arel/nodes/bind_param.rb4
-rw-r--r--activerecord/lib/arel/nodes/case.rb2
-rw-r--r--activerecord/lib/arel/predications.rb24
-rw-r--r--activerecord/lib/arel/visitors/to_sql.rb12
29 files changed, 169 insertions, 262 deletions
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index fb205d9ba5..5d0927f17d 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -190,9 +190,7 @@ module ActiveRecord
end
binds = AssociationScope.get_bind_values(owner, reflection.chain)
- sc.execute(binds, conn) do |record|
- set_inverse_instance(record)
- end
+ sc.execute(binds, conn) { |record| set_inverse_instance(record) } || []
end
# The scope for this association.
diff --git a/activerecord/lib/active_record/associations/singular_association.rb b/activerecord/lib/active_record/associations/singular_association.rb
index c296f9882e..a92932fa4b 100644
--- a/activerecord/lib/active_record/associations/singular_association.rb
+++ b/activerecord/lib/active_record/associations/singular_association.rb
@@ -37,8 +37,6 @@ module ActiveRecord
def find_target
super.first
- rescue ::RangeError
- nil
end
def replace(record)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
index 79d71bfb5d..aa2ecee74a 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -173,13 +173,6 @@ module ActiveRecord
exec_delete(sql, name, binds)
end
- # Returns +true+ when the connection adapter supports prepared statement
- # caching, otherwise returns +false+
- def supports_statement_cache? # :nodoc:
- true
- end
- deprecate :supports_statement_cache?
-
# Runs the given block in a database transaction, and returns the result
# of the block.
#
@@ -336,7 +329,7 @@ module ActiveRecord
# Inserts the given fixture into the table. Overridden in adapters that require
# something beyond a simple insert (eg. Oracle).
- # Most of adapters should implement `insert_fixtures` that leverages bulk SQL insert.
+ # Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
# We keep this method to provide fallback
# for databases like sqlite that do not support bulk inserts.
def insert_fixture(fixture, table_name)
@@ -365,18 +358,6 @@ module ActiveRecord
execute manager.to_sql, "Fixture Insert"
end
- # Inserts a set of fixtures into the table. Overridden in adapters that require
- # something beyond a simple insert (eg. Oracle).
- def insert_fixtures(fixtures, table_name)
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- `insert_fixtures` is deprecated and will be removed in the next version of Rails.
- Consider using `insert_fixtures_set` for performance improvement.
- MSG
- return if fixtures.empty?
-
- execute(build_fixture_sql(fixtures, table_name), "Fixtures Insert")
- end
-
def insert_fixtures_set(fixture_set, tables_to_delete = [])
fixture_inserts = fixture_set.map do |table_name, fixtures|
next if fixtures.empty?
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
index 718910b090..112f376d0a 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
@@ -40,24 +40,6 @@ module ActiveRecord
committed? || rolledback?
end
- def set_state(state)
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- The set_state method is deprecated and will be removed in
- Rails 6.0. Please use rollback! or commit! to set transaction
- state directly.
- MSG
- case state
- when :rolledback
- rollback!
- when :committed
- commit!
- when nil
- nullify!
- else
- raise ArgumentError, "Invalid transaction state: #{state}"
- end
- end
-
def rollback!
@children.each { |c| c.rollback! }
@state = :rolledback
diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
index f60d8469cc..9eaf9d9a89 100644
--- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -248,10 +248,29 @@ module ActiveRecord
if db_config
resolve_connection(db_config.config).merge("name" => pool_name.to_s)
else
- raise(AdapterNotSpecified, "'#{env_name}' database is not configured. Available: #{configurations.configurations.map(&:env_name).join(", ")}")
+ raise AdapterNotSpecified, <<~MSG
+ The `#{env_name}` database is not configured for the `#{ActiveRecord::ConnectionHandling::DEFAULT_ENV.call}` environment.
+
+ Available databases configurations are:
+
+ #{build_configuration_sentence}
+ MSG
end
end
+ def build_configuration_sentence # :nodoc:
+ configs = configurations.configs_for(include_replicas: true)
+
+ configs.group_by(&:env_name).map do |env, config|
+ namespaces = config.map(&:spec_name)
+ if namespaces.size > 1
+ "#{env}: #{namespaces.join(", ")}"
+ else
+ env
+ end
+ end.join("\n")
+ end
+
# Accepts a hash. Expands the "url" key that contains a
# URL database connection to a full connection
# hash and merges with the rest of the hash.
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_creation.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_creation.rb
index ceb8b40bd9..84dd28907b 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_creation.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_creation.rb
@@ -17,6 +17,42 @@ module ActiveRecord
"VALIDATE CONSTRAINT #{quote_column_name(name)}"
end
+ def visit_ChangeColumnDefinition(o)
+ column = o.column
+ column.sql_type = type_to_sql(column.type, column.options)
+ quoted_column_name = quote_column_name(o.name)
+
+ change_column_sql = +"ALTER COLUMN #{quoted_column_name} TYPE #{column.sql_type}"
+
+ options = column_options(column)
+
+ if options[:collation]
+ change_column_sql << " COLLATE \"#{options[:collation]}\""
+ end
+
+ if options[:using]
+ change_column_sql << " USING #{options[:using]}"
+ elsif options[:cast_as]
+ cast_as_type = type_to_sql(options[:cast_as], options)
+ change_column_sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
+ end
+
+ if options.key?(:default)
+ if options[:default].nil?
+ change_column_sql << ", ALTER COLUMN #{quoted_column_name} DROP DEFAULT"
+ else
+ quoted_default = quote_default_expression(options[:default], column)
+ change_column_sql << ", ALTER COLUMN #{quoted_column_name} SET DEFAULT #{quoted_default}"
+ end
+ end
+
+ if options.key?(:null)
+ change_column_sql << ", ALTER COLUMN #{quoted_column_name} #{options[:null] ? 'DROP' : 'SET'} NOT NULL"
+ end
+
+ change_column_sql
+ end
+
def add_column_options!(sql, options)
if options[:collation]
sql << " COLLATE \"#{options[:collation]}\""
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 3516bef75a..7cf371be68 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -683,38 +683,20 @@ module ActiveRecord
end
end
- def change_column_sql(table_name, column_name, type, options = {})
- quoted_column_name = quote_column_name(column_name)
- sql_type = type_to_sql(type, options)
- sql = +"ALTER COLUMN #{quoted_column_name} TYPE #{sql_type}"
- if options[:collation]
- sql << " COLLATE \"#{options[:collation]}\""
- end
- if options[:using]
- sql << " USING #{options[:using]}"
- elsif options[:cast_as]
- cast_as_type = type_to_sql(options[:cast_as], options)
- sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
- end
-
- sql
- end
-
def add_column_for_alter(table_name, column_name, type, options = {})
return super unless options.key?(:comment)
[super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }]
end
def change_column_for_alter(table_name, column_name, type, options = {})
- sqls = [change_column_sql(table_name, column_name, type, options)]
- sqls << change_column_default_for_alter(table_name, column_name, options[:default]) if options.key?(:default)
- sqls << change_column_null_for_alter(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
+ td = create_table_definition(table_name)
+ cd = td.new_column_definition(column_name, type, options)
+ sqls = [schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))]
sqls << Proc.new { change_column_comment(table_name, column_name, options[:comment]) } if options.key?(:comment)
sqls
end
- # Changes the default value of a table column.
- def change_column_default_for_alter(table_name, column_name, default_or_changes) # :nodoc:
+ def change_column_default_for_alter(table_name, column_name, default_or_changes)
column = column_for(table_name, column_name)
return unless column
@@ -729,8 +711,8 @@ module ActiveRecord
end
end
- def change_column_null_for_alter(table_name, column_name, null, default = nil) #:nodoc:
- "ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
+ def change_column_null_for_alter(table_name, column_name, null, default = nil)
+ "ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
end
def add_timestamps_for_alter(table_name, options = {})
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb
index 29f0e19a98..cb9d32a577 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb
@@ -30,19 +30,19 @@ module ActiveRecord
end
def quoted_true
- ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "1" : "'t'"
+ "1"
end
def unquoted_true
- ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 1 : "t"
+ 1
end
def quoted_false
- ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "0" : "'f'"
+ "0"
end
def unquoted_false
- ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 0 : "f"
+ 0
end
private
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 44c6e99112..14dbd20bcd 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -76,22 +76,15 @@ module ActiveRecord
json: { name: "json" },
}
- ##
- # :singleton-method:
- # Indicates whether boolean values are stored in sqlite3 databases as 1
- # and 0 or 't' and 'f'. Leaving <tt>ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer</tt>
- # set to false is deprecated. SQLite databases have used 't' and 'f' to
- # serialize boolean values and must have old data converted to 1 and 0
- # (its native boolean serialization) before setting this flag to true.
- # Conversion can be accomplished by setting up a rake task which runs
- #
- # ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
- # ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
- # for all models and all boolean columns, after which the flag must be set
- # to true by adding the following to your <tt>application.rb</tt> file:
- #
- # Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
- class_attribute :represent_boolean_as_integer, default: false
+ def self.represent_boolean_as_integer=(value) # :nodoc:
+ if value == false
+ raise "`.represent_boolean_as_integer=` is now always true, so make sure your application can work with it and remove this settings."
+ end
+
+ ActiveSupport::Deprecation.warn(
+ "`.represent_boolean_as_integer=` is now always true, so setting this is deprecated and will be removed in Rails 6.1."
+ )
+ end
class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
private
@@ -314,11 +307,6 @@ module ActiveRecord
rename_table_indexes(table_name, new_name)
end
- def valid_alter_table_type?(type, options = {})
- !invalid_alter_table_type?(type, options)
- end
- deprecate :valid_alter_table_type?
-
def add_column(table_name, column_name, type, options = {}) #:nodoc:
if invalid_alter_table_type?(type, options)
alter_table(table_name) do |definition|
@@ -390,14 +378,6 @@ module ActiveRecord
end
end
- def insert_fixtures(rows, table_name)
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- `insert_fixtures` is deprecated and will be removed in the next version of Rails.
- Consider using `insert_fixtures_set` for performance improvement.
- MSG
- insert_fixtures_set(table_name => rows)
- end
-
def insert_fixtures_set(fixture_set, tables_to_delete = [])
disable_referential_integrity do
transaction(requires_new: true) do
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 600825659b..369d63e40a 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -169,15 +169,12 @@ module ActiveRecord
where(key => params.bind).limit(1)
}
- record = statement.execute([id], connection).first
+ record = statement.execute([id], connection)&.first
unless record
raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
name, primary_key, id)
end
record
- rescue ::RangeError
- raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
- name, primary_key)
end
def find_by(*args) # :nodoc:
@@ -201,11 +198,9 @@ module ActiveRecord
where(wheres).limit(1)
}
begin
- statement.execute(hash.values, connection).first
+ statement.execute(hash.values, connection)&.first
rescue TypeError
raise ActiveRecord::StatementInvalid
- rescue ::RangeError
- nil
end
end
diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb
index 72035a986b..16dff9c2b0 100644
--- a/activerecord/lib/active_record/gem_version.rb
+++ b/activerecord/lib/active_record/gem_version.rb
@@ -10,7 +10,7 @@ module ActiveRecord
MAJOR = 6
MINOR = 0
TINY = 0
- PRE = "alpha"
+ PRE = "beta1"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/activerecord/lib/active_record/integration.rb b/activerecord/lib/active_record/integration.rb
index 90fb10a1f1..fa6f0d36ec 100644
--- a/activerecord/lib/active_record/integration.rb
+++ b/activerecord/lib/active_record/integration.rb
@@ -61,23 +61,14 @@ module ActiveRecord
#
# Product.cache_versioning = false
# Product.find(5).cache_key # => "products/5-20071224150000" (updated_at available)
- def cache_key(*timestamp_names)
+ def cache_key
if new_record?
"#{model_name.cache_key}/new"
else
- if cache_version && timestamp_names.none?
+ if cache_version
"#{model_name.cache_key}/#{id}"
else
- timestamp = if timestamp_names.any?
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- Specifying a timestamp name for #cache_key has been deprecated in favor of
- the explicit #cache_version method that can be overwritten.
- MSG
-
- max_updated_column_timestamp(timestamp_names)
- else
- max_updated_column_timestamp
- end
+ timestamp = max_updated_column_timestamp
if timestamp
timestamp = timestamp.utc.to_s(cache_timestamp_format)
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index eca64eb380..4b2e9ed81c 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -1169,13 +1169,6 @@ module ActiveRecord
class << self
attr_accessor :migrations_paths
- def migrations_path=(path)
- ActiveSupport::Deprecation.warn \
- "`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \
- "You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
- self.migrations_paths = [path]
- end
-
# For cases where a table doesn't exist like loading from schema cache
def current_version
MigrationContext.new(migrations_paths).current_version
diff --git a/activerecord/lib/active_record/migration/compatibility.rb b/activerecord/lib/active_record/migration/compatibility.rb
index 8f6fcfcaea..608182e363 100644
--- a/activerecord/lib/active_record/migration/compatibility.rb
+++ b/activerecord/lib/active_record/migration/compatibility.rb
@@ -36,9 +36,7 @@ module ActiveRecord
class V5_1 < V5_2
def change_column(table_name, column_name, type, options = {})
if adapter_name == "PostgreSQL"
- clear_cache!
- sql = connection.send(:change_column_sql, table_name, column_name, type, options)
- execute "ALTER TABLE #{quote_table_name(table_name)} #{sql}"
+ super(table_name, column_name, type, options.except(:default, :null, :comment))
change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index 2ee6119158..6346a95d57 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -167,8 +167,18 @@ end_error
initializer "active_record.set_configs" do |app|
ActiveSupport.on_load(:active_record) do
- configs = app.config.active_record.dup
+ configs = app.config.active_record
+
+ represent_boolean_as_integer = configs.sqlite3.delete(:represent_boolean_as_integer)
+
+ unless represent_boolean_as_integer.nil?
+ ActiveSupport.on_load(:active_record_sqlite3adapter) do
+ ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
+ end
+ end
+
configs.delete(:sqlite3)
+
configs.each do |k, v|
send "#{k}=", v
end
@@ -236,35 +246,6 @@ end_error
end
end
- initializer "active_record.check_represent_sqlite3_boolean_as_integer" do
- config.after_initialize do
- ActiveSupport.on_load(:active_record_sqlite3adapter) do
- represent_boolean_as_integer = Rails.application.config.active_record.sqlite3.delete(:represent_boolean_as_integer)
- unless represent_boolean_as_integer.nil?
- ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
- end
-
- unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
- ActiveSupport::Deprecation.warn <<-MSG
-Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
-set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
-boolean values and must have old data converted to 1 and 0 (its native boolean
-serialization) before setting this flag to true. Conversion can be accomplished
-by setting up a rake task which runs
-
- ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
- ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
-
-for all models and all boolean columns, after which the flag must be set to
-true by adding the following to your application.rb file:
-
- Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
-MSG
- end
- end
- end
- end
-
initializer "active_record.set_filter_attributes" do
ActiveSupport.on_load(:active_record) do
self.filter_attributes += Rails.application.config.filter_parameters
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index d24324ecce..8de06e8466 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -407,6 +407,10 @@ namespace :railties do
if railtie.respond_to?(:paths) && (path = railtie.paths["db/migrate"].first)
railties[railtie.railtie_name] = path
end
+
+ unless ENV["MIGRATIONS_PATH"].blank?
+ railties[railtie.railtie_name] = railtie.root + ENV["MIGRATIONS_PATH"]
+ end
end
on_skip = Proc.new do |name, migration|
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index c2c4a5a882..cef31bea94 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -41,15 +41,13 @@ module ActiveRecord
def count(column_name = nil)
if block_given?
unless column_name.nil?
- ActiveSupport::Deprecation.warn \
- "When `count' is called with a block, it ignores other arguments. " \
- "This behavior is now deprecated and will result in an ArgumentError in Rails 6.0."
+ raise ArgumentError, "Column name argument is not supported when a block is passed."
end
- return super()
+ super()
+ else
+ calculate(:count, column_name)
end
-
- calculate(:count, column_name)
end
# Calculates the average value on a given column. Returns +nil+ if there's
@@ -86,15 +84,13 @@ module ActiveRecord
def sum(column_name = nil)
if block_given?
unless column_name.nil?
- ActiveSupport::Deprecation.warn \
- "When `sum' is called with a block, it ignores other arguments. " \
- "This behavior is now deprecated and will result in an ArgumentError in Rails 6.0."
+ raise ArgumentError, "Column name argument is not supported when a block is passed."
end
- return super()
+ super()
+ else
+ calculate(:sum, column_name)
end
-
- calculate(:sum, column_name)
end
# This calculates aggregate values in the given column. Methods for #count, #sum, #average,
diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb
index 6f67dd3784..6e8a1fcad4 100644
--- a/activerecord/lib/active_record/relation/delegation.rb
+++ b/activerecord/lib/active_record/relation/delegation.rb
@@ -112,15 +112,6 @@ module ActiveRecord
if @klass.respond_to?(method)
self.class.delegate_to_scoped_klass(method)
scoping { @klass.public_send(method, *args, &block) }
- elsif @delegate_to_klass && @klass.respond_to?(method, true)
- ActiveSupport::Deprecation.warn \
- "Delegating missing #{method} method to #{@klass}. " \
- "Accessibility of private/protected class methods in :scope is deprecated and will be removed in Rails 6.0."
- @klass.send(method, *args, &block)
- elsif arel.respond_to?(method)
- ActiveSupport::Deprecation.warn \
- "Delegating #{method} to arel is deprecated and will be removed in Rails 6.0."
- arel.public_send(method, *args, &block)
else
super
end
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index fd84f9c46b..8f1065c1e7 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -79,17 +79,12 @@ module ActiveRecord
# Post.find_by "published_at < ?", 2.weeks.ago
def find_by(arg, *args)
where(arg, *args).take
- rescue ::RangeError
- nil
end
# Like #find_by, except that if no record is found, raises
# an ActiveRecord::RecordNotFound error.
def find_by!(arg, *args)
where(arg, *args).take!
- rescue ::RangeError
- raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value",
- @klass.name, @klass.primary_key)
end
# Gives a record (or N records if a parameter is supplied) without any implied
@@ -322,8 +317,6 @@ module ActiveRecord
relation = construct_relation_for_exists(conditions)
skip_query_cache_if_necessary { connection.select_value(relation.arel, "#{name} Exists") } ? true : false
- rescue ::RangeError
- false
end
# This method is called whenever no records are found with either a single
@@ -434,9 +427,6 @@ module ActiveRecord
else
find_some(ids)
end
- rescue ::RangeError
- error_message = "Couldn't find #{model_name} with an out of range ID"
- raise RecordNotFound.new(error_message, model_name, primary_key, ids)
end
def find_one(id)
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index b59ff912fe..240de3bb69 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -90,16 +90,21 @@ module ActiveRecord
queries.reduce(&:or)
elsif table.aggregated_with?(key)
mapping = table.reflect_on_aggregation(key).mapping
- queries = Array.wrap(value).map do |object|
- mapping.map do |field_attr, aggregate_attr|
- if mapping.size == 1 && !object.respond_to?(aggregate_attr)
- build(table.arel_attribute(field_attr), object)
- else
- build(table.arel_attribute(field_attr), object.send(aggregate_attr))
- end
- end.reduce(&:and)
+ values = value.nil? ? [nil] : Array.wrap(value)
+ if mapping.length == 1 || values.empty?
+ column_name, aggr_attr = mapping.first
+ values = values.map do |object|
+ object.respond_to?(aggr_attr) ? object.public_send(aggr_attr) : object
+ end
+ build(table.arel_attribute(column_name), values)
+ else
+ queries = values.map do |object|
+ mapping.map do |field_attr, aggregate_attr|
+ build(table.arel_attribute(field_attr), object.try!(aggregate_attr))
+ end.reduce(&:and)
+ end
+ queries.reduce(&:or)
end
- queries.reduce(&:or)
else
build(table.arel_attribute(key), value)
end
diff --git a/activerecord/lib/active_record/relation/query_attribute.rb b/activerecord/lib/active_record/relation/query_attribute.rb
index b45326bdda..5e0b4ac160 100644
--- a/activerecord/lib/active_record/relation/query_attribute.rb
+++ b/activerecord/lib/active_record/relation/query_attribute.rb
@@ -20,18 +20,23 @@ module ActiveRecord
def nil?
!value_before_type_cast.is_a?(StatementCache::Substitute) &&
(value_before_type_cast.nil? || value_for_database.nil?)
+ rescue ::RangeError
end
- def boundable?
- return @_boundable if defined?(@_boundable)
- nil?
- @_boundable = true
+ def infinite?
+ infinity?(value_before_type_cast) || infinity?(value_for_database)
rescue ::RangeError
- @_boundable = false
end
- def infinite?
- infinity?(value_before_type_cast) || boundable? && infinity?(value_for_database)
+ def unboundable?
+ if defined?(@_unboundable)
+ @_unboundable
+ else
+ value_for_database
+ @_unboundable = nil
+ end
+ rescue ::RangeError
+ @_unboundable = type.cast(value_before_type_cast) <=> 0
end
private
diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb
index 3485d9e557..e6197752bc 100644
--- a/activerecord/lib/active_record/sanitization.rb
+++ b/activerecord/lib/active_record/sanitization.rb
@@ -134,43 +134,6 @@ module ActiveRecord
end
private
- # Accepts a hash of SQL conditions and replaces those attributes
- # that correspond to a {#composed_of}[rdoc-ref:Aggregations::ClassMethods#composed_of]
- # relationship with their expanded aggregate attribute values.
- #
- # Given:
- #
- # class Person < ActiveRecord::Base
- # composed_of :address, class_name: "Address",
- # mapping: [%w(address_street street), %w(address_city city)]
- # end
- #
- # Then:
- #
- # { address: Address.new("813 abc st.", "chicago") }
- # # => { address_street: "813 abc st.", address_city: "chicago" }
- def expand_hash_conditions_for_aggregates(attrs) # :doc:
- expanded_attrs = {}
- attrs.each do |attr, value|
- if aggregation = reflect_on_aggregation(attr.to_sym)
- mapping = aggregation.mapping
- mapping.each do |field_attr, aggregate_attr|
- expanded_attrs[field_attr] = if value.is_a?(Array)
- value.map { |it| it.send(aggregate_attr) }
- elsif mapping.size == 1 && !value.respond_to?(aggregate_attr)
- value
- else
- value.send(aggregate_attr)
- end
- end
- else
- expanded_attrs[attr] = value
- end
- end
- expanded_attrs
- end
- deprecate :expand_hash_conditions_for_aggregates
-
def replace_bind_variables(statement, values)
raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size)
bound = values.dup
diff --git a/activerecord/lib/active_record/statement_cache.rb b/activerecord/lib/active_record/statement_cache.rb
index 1b1736dcab..95984e7ada 100644
--- a/activerecord/lib/active_record/statement_cache.rb
+++ b/activerecord/lib/active_record/statement_cache.rb
@@ -132,6 +132,8 @@ module ActiveRecord
sql = query_builder.sql_for bind_values, connection
klass.find_by_sql(sql, bind_values, preparable: true, &block)
+ rescue ::RangeError
+ nil
end
def self.unsupported_value?(value)
diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb
index e19077eb88..2345db7138 100644
--- a/activerecord/lib/active_record/timestamp.rb
+++ b/activerecord/lib/active_record/timestamp.rb
@@ -133,11 +133,10 @@ module ActiveRecord
self.class.send(:current_time_from_proper_timezone)
end
- def max_updated_column_timestamp(timestamp_names = timestamp_attributes_for_update_in_model)
- timestamp_names
- .map { |attr| self[attr] }
+ def max_updated_column_timestamp
+ timestamp_attributes_for_update_in_model
+ .map { |attr| self[attr]&.to_time }
.compact
- .map(&:to_time)
.max
end
diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb
index 111b6c9a64..fb745af125 100644
--- a/activerecord/lib/active_record/validations/uniqueness.rb
+++ b/activerecord/lib/active_record/validations/uniqueness.rb
@@ -58,7 +58,7 @@ module ActiveRecord
def build_relation(klass, attribute, value)
relation = klass.unscoped
comparison = relation.bind_attribute(attribute, value) do |attr, bind|
- return relation.none! unless bind.boundable?
+ return relation.none! if bind.unboundable?
if bind.nil?
attr.eq(bind)
diff --git a/activerecord/lib/arel/nodes/bind_param.rb b/activerecord/lib/arel/nodes/bind_param.rb
index f145e44ae3..344e46479f 100644
--- a/activerecord/lib/arel/nodes/bind_param.rb
+++ b/activerecord/lib/arel/nodes/bind_param.rb
@@ -28,8 +28,8 @@ module Arel # :nodoc: all
value.respond_to?(:infinite?) && value.infinite?
end
- def boundable?
- !value.respond_to?(:boundable?) || value.boundable?
+ def unboundable?
+ value.respond_to?(:unboundable?) && value.unboundable?
end
end
end
diff --git a/activerecord/lib/arel/nodes/case.rb b/activerecord/lib/arel/nodes/case.rb
index 654a54825e..b8f83128c8 100644
--- a/activerecord/lib/arel/nodes/case.rb
+++ b/activerecord/lib/arel/nodes/case.rb
@@ -3,6 +3,8 @@
module Arel # :nodoc: all
module Nodes
class Case < Arel::Nodes::Node
+ include Arel::AliasPredication
+
attr_accessor :case, :conditions, :default
def initialize(expression = nil, default = nil)
diff --git a/activerecord/lib/arel/predications.rb b/activerecord/lib/arel/predications.rb
index 2a62c53aa3..7dafde4952 100644
--- a/activerecord/lib/arel/predications.rb
+++ b/activerecord/lib/arel/predications.rb
@@ -35,15 +35,17 @@ module Arel # :nodoc: all
end
def between(other)
- if infinity?(other.begin)
- if other.end.nil? || infinity?(other.end)
+ if unboundable?(other.begin) == 1 || unboundable?(other.end) == -1
+ self.in([])
+ elsif open_ended?(other.begin)
+ if other.end.nil? || open_ended?(other.end)
not_in([])
elsif other.exclude_end?
lt(other.end)
else
lteq(other.end)
end
- elsif other.end.nil? || infinity?(other.end)
+ elsif other.end.nil? || open_ended?(other.end)
gteq(other.begin)
elsif other.exclude_end?
gteq(other.begin).and(lt(other.end))
@@ -81,15 +83,17 @@ Passing a range to `#in` is deprecated. Call `#between`, instead.
end
def not_between(other)
- if infinity?(other.begin)
- if other.end.nil? || infinity?(other.end)
+ if unboundable?(other.begin) == 1 || unboundable?(other.end) == -1
+ not_in([])
+ elsif open_ended?(other.begin)
+ if other.end.nil? || open_ended?(other.end)
self.in([])
elsif other.exclude_end?
gteq(other.end)
else
gt(other.end)
end
- elsif other.end.nil? || infinity?(other.end)
+ elsif other.end.nil? || open_ended?(other.end)
lt(other.begin)
else
left = lt(other.begin)
@@ -241,5 +245,13 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
def infinity?(value)
value.respond_to?(:infinite?) && value.infinite?
end
+
+ def unboundable?(value)
+ value.respond_to?(:unboundable?) && value.unboundable?
+ end
+
+ def open_ended?(value)
+ infinity?(value) || unboundable?(value)
+ end
end
end
diff --git a/activerecord/lib/arel/visitors/to_sql.rb b/activerecord/lib/arel/visitors/to_sql.rb
index b5a960ce68..d0dec63860 100644
--- a/activerecord/lib/arel/visitors/to_sql.rb
+++ b/activerecord/lib/arel/visitors/to_sql.rb
@@ -576,7 +576,7 @@ module Arel # :nodoc: all
def visit_Arel_Nodes_In(o, collector)
if Array === o.right && !o.right.empty?
- o.right.keep_if { |value| boundable?(value) }
+ o.right.delete_if { |value| unboundable?(value) }
end
if Array === o.right && o.right.empty?
@@ -590,7 +590,7 @@ module Arel # :nodoc: all
def visit_Arel_Nodes_NotIn(o, collector)
if Array === o.right && !o.right.empty?
- o.right.keep_if { |value| boundable?(value) }
+ o.right.delete_if { |value| unboundable?(value) }
end
if Array === o.right && o.right.empty?
@@ -629,6 +629,8 @@ module Arel # :nodoc: all
def visit_Arel_Nodes_Equality(o, collector)
right = o.right
+ return collector << "1=0" if unboundable?(right)
+
collector = visit o.left, collector
if right.nil?
@@ -662,6 +664,8 @@ module Arel # :nodoc: all
def visit_Arel_Nodes_NotEqual(o, collector)
right = o.right
+ return collector << "1=1" if unboundable?(right)
+
collector = visit o.left, collector
if right.nil?
@@ -812,8 +816,8 @@ module Arel # :nodoc: all
}
end
- def boundable?(value)
- !value.respond_to?(:boundable?) || value.boundable?
+ def unboundable?(value)
+ value.respond_to?(:unboundable?) && value.unboundable?
end
def has_join_sources?(o)