aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/quoting.rb14
-rw-r--r--activerecord/lib/active_record/database_configurations.rb2
-rw-r--r--activerecord/lib/active_record/insert_all.rb62
-rw-r--r--activerecord/test/cases/bind_parameter_test.rb2
-rw-r--r--guides/source/6_0_release_notes.md63
-rw-r--r--railties/CHANGELOG.md4
-rw-r--r--railties/test/isolation/abstract_unit.rb2
7 files changed, 110 insertions, 39 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index eefe621feb..9d24d839c1 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -138,15 +138,15 @@ module ActiveRecord
"'#{quote_string(value.to_s)}'"
end
- def type_casted_binds(binds) # :nodoc:
- if binds.first.is_a?(Array)
- binds.map { |column, value| type_cast(value, column) }
- else
- binds.map { |attr| type_cast(attr.value_for_database) }
+ private
+ def type_casted_binds(binds)
+ if binds.first.is_a?(Array)
+ binds.map { |column, value| type_cast(value, column) }
+ else
+ binds.map { |attr| type_cast(attr.value_for_database) }
+ end
end
- end
- private
def lookup_cast_type(sql_type)
type_map.lookup(sql_type)
end
diff --git a/activerecord/lib/active_record/database_configurations.rb b/activerecord/lib/active_record/database_configurations.rb
index a6c702cbbc..4656045fe5 100644
--- a/activerecord/lib/active_record/database_configurations.rb
+++ b/activerecord/lib/active_record/database_configurations.rb
@@ -106,7 +106,7 @@ module ActiveRecord
build_db_config = configs.each_pair.flat_map do |env_name, config|
walk_configs(env_name.to_s, "primary", config)
- end.compact
+ end.flatten.compact
if url = ENV["DATABASE_URL"]
build_url_config(url, build_db_config)
diff --git a/activerecord/lib/active_record/insert_all.rb b/activerecord/lib/active_record/insert_all.rb
index 3833cb2fcf..98c98d61cd 100644
--- a/activerecord/lib/active_record/insert_all.rb
+++ b/activerecord/lib/active_record/insert_all.rb
@@ -2,12 +2,14 @@
module ActiveRecord
class InsertAll
- attr_reader :model, :connection, :inserts, :on_duplicate, :returning, :unique_by
+ attr_reader :model, :connection, :inserts, :keys
+ attr_reader :on_duplicate, :returning, :unique_by
def initialize(model, inserts, on_duplicate:, returning: nil, unique_by: nil)
raise ArgumentError, "Empty list of attributes passed" if inserts.blank?
- @model, @connection, @inserts, @on_duplicate, @returning, @unique_by = model, model.connection, inserts, on_duplicate, returning, unique_by
+ @model, @connection, @inserts, @keys = model, model.connection, inserts, inserts.first.keys.map(&:to_s).to_set
+ @on_duplicate, @returning, @unique_by = on_duplicate, returning, unique_by
@returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
@returning = false if @returning == []
@@ -21,10 +23,6 @@ module ActiveRecord
connection.exec_query to_sql, "Bulk Insert"
end
- def keys
- inserts.first.keys.map(&:to_s)
- end
-
def updatable_columns
keys - readonly_columns - unique_by_columns
end
@@ -37,6 +35,17 @@ module ActiveRecord
on_duplicate == :update
end
+ def map_key_with_value
+ inserts.map do |attributes|
+ attributes = attributes.stringify_keys
+ verify_attributes(attributes)
+
+ keys.map do |key|
+ yield key, attributes[key]
+ end
+ end
+ end
+
private
def ensure_valid_options_for_connection!
if returning && !connection.supports_insert_returning?
@@ -76,6 +85,12 @@ module ActiveRecord
Array.wrap(model.primary_key)
end
+ def verify_attributes(attributes)
+ if keys != attributes.keys.to_set
+ raise ArgumentError, "All objects being inserted must have the same keys"
+ end
+ end
+
class Builder
attr_reader :model
@@ -91,29 +106,11 @@ module ActiveRecord
end
def values_list
- columns = connection.schema_cache.columns_hash(model.table_name)
-
- column_names = columns.keys.to_set
- keys = insert_all.keys.to_set
- unknown_columns = keys - column_names
+ types = extract_types_from_columns_on(model.table_name, keys: insert_all.keys)
- unless unknown_columns.empty?
- raise UnknownAttributeError.new(model.new, unknown_columns.first)
- end
-
- types = keys.map { |key| [ key, connection.lookup_cast_type_from_column(columns[key]) ] }.to_h
-
- values_list = insert_all.inserts.map do |attributes|
- attributes = attributes.stringify_keys
-
- unless attributes.keys.to_set == keys
- raise ArgumentError, "All objects being inserted must have the same keys"
- end
-
- keys.map do |key|
- bind = Relation::QueryAttribute.new(key, attributes[key], types[key])
- connection.with_yaml_fallback(bind.value_for_database)
- end
+ values_list = insert_all.map_key_with_value do |key, value|
+ bind = Relation::QueryAttribute.new(key, value, types[key])
+ connection.with_yaml_fallback(bind.value_for_database)
end
Arel::InsertManager.new.create_values_list(values_list).to_sql
@@ -141,6 +138,15 @@ module ActiveRecord
quote_columns(insert_all.keys).join(",")
end
+ def extract_types_from_columns_on(table_name, keys:)
+ columns = connection.schema_cache.columns_hash(table_name)
+
+ unknown_column = (keys - columns.keys).first
+ raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
+
+ keys.map { |key| [ key, connection.lookup_cast_type_from_column(columns[key]) ] }.to_h
+ end
+
def quote_columns(columns)
columns.map(&connection.method(:quote_column_name))
end
diff --git a/activerecord/test/cases/bind_parameter_test.rb b/activerecord/test/cases/bind_parameter_test.rb
index eb8b45431f..85685d1d00 100644
--- a/activerecord/test/cases/bind_parameter_test.rb
+++ b/activerecord/test/cases/bind_parameter_test.rb
@@ -184,7 +184,7 @@ if ActiveRecord::Base.connection.prepared_statements
name: "SQL",
sql: "select * from topics where id = ?",
binds: binds,
- type_casted_binds: @connection.type_casted_binds(binds)
+ type_casted_binds: @connection.send(:type_casted_binds, binds)
}
event = ActiveSupport::Notifications::Event.new(
diff --git a/guides/source/6_0_release_notes.md b/guides/source/6_0_release_notes.md
index b6a8536b38..0cf9ca09c7 100644
--- a/guides/source/6_0_release_notes.md
+++ b/guides/source/6_0_release_notes.md
@@ -77,10 +77,73 @@ Please refer to the [Changelog][railties] for detailed changes.
### Removals
+* Remove deprecated `after_bundle` helper inside plugins templates.
+ ([Commit](https://github.com/rails/rails/commit/4d51efe24e461a2a3ed562787308484cd48370c7))
+
+* Remove deprecated support to `config.ru` that uses the application
+ class as argument of `run`.
+ ([Commit](https://github.com/rails/rails/commit/553b86fc751c751db504bcbe2d033eb2bb5b6a0b))
+
+* Remove deprecated `environment` argument from the rails commands.
+ ([Commit](https://github.com/rails/rails/commit/e20589c9be09c7272d73492d4b0f7b24e5595571))
+
+* Remove deprecated `capify!` method in generators and templates.
+ ([Commit](https://github.com/rails/rails/commit/9d39f81d512e0d16a27e2e864ea2dd0e8dc41b17))
+
+* Remove deprecated `config.secret_token`.
+ ([Commit](https://github.com/rails/rails/commit/46ac5fe69a20d4539a15929fe48293e1809a26b0))
+
### Deprecations
+* Deprecate passing Rack server name as a regular argument to `rails server`.
+ ([Pull Request](https://github.com/rails/rails/pull/32058))
+
+* Deprecate support for using `HOST` environment to specify server IP.
+ ([Pull Request](https://github.com/rails/rails/pull/32540))
+
+* Deprecate accessing hashes returned by `config_for` by non-symbol keys.
+ ([Pull Request](https://github.com/rails/rails/pull/35198))
+
### Notable changes
+* Add an explicit option `--using` or `-u` for specifying the server for the
+ `rails server` command.
+ ([Pull Request](https://github.com/rails/rails/pull/32058))
+
+* Add ability to see the output of `rails routes` in expanded format.
+ ([Pull Request](https://github.com/rails/rails/pull/32130))
+
+* Run the seed database task using inline Active Job adapter.
+ ([Pull Request](https://github.com/rails/rails/pull/34953))
+
+* Add a command `rails db:system:change` to change the database of the application.
+ ([Pull Request](https://github.com/rails/rails/pull/34832))
+
+* Add `rails test:channels` command to test only Action Cable channels.
+ ([Pull Request](https://github.com/rails/rails/pull/34947))
+
+* Introduce guard against DNS rebinding attacks.
+ ([Pull Request](https://github.com/rails/rails/pull/33145))
+
+* Add ability to abort on failure while running generator commands.
+ ([Pull Request](https://github.com/rails/rails/pull/34420))
+
+* Make Webpacker the default JavaScript compiler for Rails 6.
+ ([Pull Request](https://github.com/rails/rails/pull/33079))
+
+* Add multiple database support for `rails db:migrate:status` command.
+ ([Pull Request](https://github.com/rails/rails/pull/34137))
+
+* Add ability to use different migration paths from multiple databases in
+ the generators.
+ ([Pull Request](https://github.com/rails/rails/pull/34021))
+
+* Add support for multi environment credentials=.
+ ([Pull Request](https://github.com/rails/rails/pull/33521))
+
+* Make `null_store` as default cache store in test environment.
+ ([Pull Request](https://github.com/rails/rails/pull/33773))
+
Action Cable
------------
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 264e72bc59..226b949b34 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -79,9 +79,9 @@
*George Claghorn*
-* Introduce guard against DNS rebinding attacks
+* Introduce guard against DNS rebinding attacks.
- The `ActionDispatch::HostAuthorization` is a new middleware that prevent
+ The `ActionDispatch::HostAuthorization` is a new middleware that prevents
against DNS rebinding and other `Host` header attacks. It is included in
the development environment by default with the following configuration:
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 14cdf1ab7c..3fcfaa9623 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -123,6 +123,8 @@ module TestHelpers
adapter: sqlite3
pool: 5
timeout: 5000
+ variables:
+ statement_timeout: 1000
development:
primary:
<<: *default