aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activemodel/lib/active_model/conversion.rb4
-rw-r--r--activerecord/CHANGELOG.md10
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb5
-rw-r--r--activerecord/lib/active_record/schema_dumper.rb53
-rw-r--r--activerecord/test/cases/comment_test.rb4
-rw-r--r--activerecord/test/cases/migration/create_join_table_test.rb7
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb20
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/object/blank.rb10
-rw-r--r--guides/source/5_0_release_notes.md3
-rw-r--r--guides/source/autoloading_and_reloading_constants.md4
-rw-r--r--railties/lib/rails/tasks/misc.rake2
12 files changed, 82 insertions, 47 deletions
diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb
index 9de6ea65be..a932ada45c 100644
--- a/activemodel/lib/active_model/conversion.rb
+++ b/activemodel/lib/active_model/conversion.rb
@@ -40,8 +40,8 @@ module ActiveModel
self
end
- # Returns an Array of all key attributes if any is set, regardless if
- # the object is persisted or not. Returns +nil+ if there are no key attributes.
+ # Returns an Array of all key attributes if any of the attributes is set, whether or not
+ # the object is persisted. Returns +nil+ if there are no key attributes.
#
# class Person
# include ActiveModel::Conversion
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 16ce131cf4..2a9694080e 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,13 @@
+* Schema dumper: Indexes are now included in the `create_table` block
+ instead of listed afterward as separate `add_index` lines.
+
+ This tidies up schema.rb and makes it easy to read as a list of tables.
+
+ Bonus: Allows databases that support it (MySQL) to perform as single
+ `CREATE TABLE` query, no additional query per index.
+
+ *Ryuta Kamizono*
+
* SQLite: Fix uniqueness validation when values exceed the column limit.
SQLite doesn't impose length restrictions on strings, BLOBs, or numeric
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index 4f361fed6b..104ca54793 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -342,12 +342,13 @@ module ActiveRecord
column_options = options.delete(:column_options) || {}
column_options.reverse_merge!(null: false)
+ type = column_options.delete(:type) || :integer
t1_column, t2_column = [table_1, table_2].map{ |t| t.to_s.singularize.foreign_key }
create_table(join_table_name, options.merge!(id: false)) do |td|
- td.integer t1_column, column_options
- td.integer t2_column, column_options
+ td.send type, t1_column, column_options
+ td.send type, t2_column, column_options
yield td if block_given?
end
end
diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb
index c2662ec476..301718b874 100644
--- a/activerecord/lib/active_record/schema_dumper.rb
+++ b/activerecord/lib/active_record/schema_dumper.rb
@@ -179,11 +179,11 @@ HEADER
tbl.puts
end
+ indexes_in_create(table, tbl)
+
tbl.puts " end"
tbl.puts
- indexes(table, tbl)
-
tbl.rewind
stream.print tbl.read
rescue => e
@@ -195,27 +195,12 @@ HEADER
stream
end
+ # Keep it for indexing materialized views
def indexes(table, stream)
if (indexes = @connection.indexes(table)).any?
add_index_statements = indexes.map do |index|
- statement_parts = [
- "add_index #{remove_prefix_and_suffix(index.table).inspect}",
- index.columns.inspect,
- "name: #{index.name.inspect}",
- ]
- statement_parts << 'unique: true' if index.unique
-
- index_lengths = (index.lengths || []).compact
- statement_parts << "length: #{Hash[index.columns.zip(index.lengths)].inspect}" if index_lengths.any?
-
- index_orders = index.orders || {}
- statement_parts << "order: #{index.orders.inspect}" if index_orders.any?
- statement_parts << "where: #{index.where.inspect}" if index.where
- statement_parts << "using: #{index.using.inspect}" if index.using
- statement_parts << "type: #{index.type.inspect}" if index.type
- statement_parts << "comment: #{index.comment.inspect}" if index.comment
-
- " #{statement_parts.join(', ')}"
+ table_name = remove_prefix_and_suffix(index.table).inspect
+ " add_index #{([table_name]+index_parts(index)).join(', ')}"
end
stream.puts add_index_statements.sort.join("\n")
@@ -223,6 +208,34 @@ HEADER
end
end
+ def indexes_in_create(table, stream)
+ if (indexes = @connection.indexes(table)).any?
+ index_statements = indexes.map do |index|
+ " t.index #{index_parts(index).join(', ')}"
+ end
+ stream.puts index_statements.sort.join("\n")
+ end
+ end
+
+ def index_parts(index)
+ index_parts = [
+ index.columns.inspect,
+ "name: #{index.name.inspect}",
+ ]
+ index_parts << 'unique: true' if index.unique
+
+ index_lengths = (index.lengths || []).compact
+ index_parts << "length: #{Hash[index.columns.zip(index.lengths)].inspect}" if index_lengths.any?
+
+ index_orders = index.orders || {}
+ index_parts << "order: #{index.orders.inspect}" if index_orders.any?
+ index_parts << "where: #{index.where.inspect}" if index.where
+ index_parts << "using: #{index.using.inspect}" if index.using
+ index_parts << "type: #{index.type.inspect}" if index.type
+ index_parts << "comment: #{index.comment.inspect}" if index.comment
+ index_parts
+ end
+
def foreign_keys(table, stream)
if (foreign_keys = @connection.foreign_keys(table)).any?
add_foreign_key_statements = foreign_keys.map do |foreign_key|
diff --git a/activerecord/test/cases/comment_test.rb b/activerecord/test/cases/comment_test.rb
index 298d171cdf..37d951ad88 100644
--- a/activerecord/test/cases/comment_test.rb
+++ b/activerecord/test/cases/comment_test.rb
@@ -103,8 +103,8 @@ class CommentTest < ActiveRecord::TestCase
assert_match %r[t\.string\s+"obvious"\n], output
assert_match %r[t\.string\s+"content",\s+comment: "Whoa, content describes itself!"], output
assert_match %r[t\.integer\s+"rating",\s+comment: "I am running out of imagination"], output
- assert_match %r[add_index\s+.+\s+comment: "\\\"Very important\\\" index that powers all the performance.\\nAnd it's fun!"], output
- assert_match %r[add_index\s+.+\s+name: "idx_obvious",.+\s+comment: "We need to see obvious comments"], output
+ assert_match %r[t\.index\s+.+\s+comment: "\\\"Very important\\\" index that powers all the performance.\\nAnd it's fun!"], output
+ assert_match %r[t\.index\s+.+\s+name: "idx_obvious",.+\s+comment: "We need to see obvious comments"], output
end
def test_schema_dump_omits_blank_comments
diff --git a/activerecord/test/cases/migration/create_join_table_test.rb b/activerecord/test/cases/migration/create_join_table_test.rb
index 0a7b57455c..920c472c73 100644
--- a/activerecord/test/cases/migration/create_join_table_test.rb
+++ b/activerecord/test/cases/migration/create_join_table_test.rb
@@ -132,6 +132,13 @@ module ActiveRecord
end
end
+ if current_adapter?(:PostgreSQLAdapter)
+ def test_create_join_table_with_uuid
+ connection.create_join_table :artists, :musics, column_options: { type: :uuid }
+ assert_equal [:uuid, :uuid], connection.columns(:artists_musics).map(&:type)
+ end
+ end
+
private
def with_table_cleanup
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 4498c96029..c7db77b426 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -171,24 +171,24 @@ class SchemaDumperTest < ActiveRecord::TestCase
end
def test_schema_dumps_index_columns_in_right_order
- index_definition = standard_dump.split(/\n/).grep(/add_index.*companies/).first.strip
+ index_definition = standard_dump.split(/\n/).grep(/t\.index.*company_index/).first.strip
if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
- assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index", using: :btree', index_definition
+ assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index", using: :btree', index_definition
else
- assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index"', index_definition
+ assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index"', index_definition
end
end
def test_schema_dumps_partial_indices
- index_definition = standard_dump.split(/\n/).grep(/add_index.*company_partial_index/).first.strip
+ index_definition = standard_dump.split(/\n/).grep(/t\.index.*company_partial_index/).first.strip
if current_adapter?(:PostgreSQLAdapter)
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition
elsif current_adapter?(:Mysql2Adapter)
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", using: :btree', index_definition
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", using: :btree', index_definition
elsif current_adapter?(:SQLite3Adapter) && ActiveRecord::Base.connection.supports_partial_index?
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "rating > 10"', index_definition
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "rating > 10"', index_definition
else
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index"', index_definition
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index"', index_definition
end
end
@@ -235,8 +235,8 @@ class SchemaDumperTest < ActiveRecord::TestCase
def test_schema_dumps_index_type
output = standard_dump
- assert_match %r{add_index "key_tests", \["awesome"\], name: "index_key_tests_on_awesome", type: :fulltext}, output
- assert_match %r{add_index "key_tests", \["pizza"\], name: "index_key_tests_on_pizza", using: :btree}, output
+ assert_match %r{t\.index \["awesome"\], name: "index_key_tests_on_awesome", type: :fulltext}, output
+ assert_match %r{t\.index \["pizza"\], name: "index_key_tests_on_pizza", using: :btree}, output
end
end
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index 0d46248582..24450cd221 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -149,14 +149,11 @@ class Module
#
# The target method must be public, otherwise it will raise +NoMethodError+.
#
- def delegate(*methods)
- options = methods.pop
- unless options.is_a?(Hash) && to = options[:to]
+ def delegate(*methods, to: nil, prefix: nil, allow_nil: nil)
+ unless to
raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
end
- prefix, allow_nil = options.values_at(:prefix, :allow_nil)
-
if prefix == true && to =~ /^[^a-z_]/
raise ArgumentError, 'Can only automatically set the delegation prefix when delegating to a method.'
end
diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb
index 039c50a4a2..d6bad98376 100644
--- a/activesupport/lib/active_support/core_ext/object/blank.rb
+++ b/activesupport/lib/active_support/core_ext/object/blank.rb
@@ -97,8 +97,6 @@ class Hash
end
class String
- BLANK_RE = /\A[[:space:]]*\z/
-
# A string is blank if it's empty or contains whitespaces only:
#
# ''.blank? # => true
@@ -112,7 +110,13 @@ class String
#
# @return [true, false]
def blank?
- BLANK_RE === self
+ # In practice, the majority of blank strings are empty. The predicate is
+ # about 3.5x faster than the regexp check so we first test empty?, and then
+ # fallback. Penalty for the rest of strings is marginal.
+ #
+ # Double negation in the second operand is also a performance tweak, it is
+ # faster than the positive \A[[:space:]]*\z due to lack of backtracking.
+ empty? || !(/[[:^space:]]/ === self)
end
end
diff --git a/guides/source/5_0_release_notes.md b/guides/source/5_0_release_notes.md
index 28f653b634..5f14a5a3f9 100644
--- a/guides/source/5_0_release_notes.md
+++ b/guides/source/5_0_release_notes.md
@@ -227,6 +227,9 @@ Please refer to the [Changelog][action-pack] for detailed changes.
`RedirectBackError`.
([Pull Request](https://github.com/rails/rails/pull/22506))
+* `ActionDispatch::IntegrationTest` and `ActionController::TestCase` deprecate positional arguments in favor of
+ keyword arguments. ([Pull Request](https://github.com/rails/rails/pull/18323))
+
### Notable changes
* Added `ActionController::Renderer` to render arbitrary templates
diff --git a/guides/source/autoloading_and_reloading_constants.md b/guides/source/autoloading_and_reloading_constants.md
index de0fa2fdc0..246fde69d5 100644
--- a/guides/source/autoloading_and_reloading_constants.md
+++ b/guides/source/autoloading_and_reloading_constants.md
@@ -524,7 +524,7 @@ On the contrary, if `ApplicationController` is unknown, the constant is
considered missing and an autoload is going to be attempted by Rails.
In order to load `ApplicationController`, Rails iterates over `autoload_paths`.
-First checks if `app/assets/application_controller.rb` exists. If it does not,
+First it checks if `app/assets/application_controller.rb` exists. If it does not,
which is normally the case, it continues and finds
`app/controllers/application_controller.rb`.
@@ -624,7 +624,7 @@ file is loaded. If the file actually defines `Post` all is fine, otherwise
### Qualified References
When a qualified constant is missing Rails does not look for it in the parent
-namespaces. But there is a caveat: When a constant is missing, Rails is
+namespaces. But there is a caveat: when a constant is missing, Rails is
unable to tell if the trigger was a relative reference or a qualified one.
For example, consider
diff --git a/railties/lib/rails/tasks/misc.rake b/railties/lib/rails/tasks/misc.rake
index 371bcb8fe0..e6b13cc077 100644
--- a/railties/lib/rails/tasks/misc.rake
+++ b/railties/lib/rails/tasks/misc.rake
@@ -10,7 +10,7 @@ task about: :environment do
end
namespace :time do
- desc 'List all time zones, list by two-letter country code (`rake time:zones[US]`), or list by UTC offset (`rake time:zones[-8]`)'
+ desc 'List all time zones, list by two-letter country code (`rails time:zones[US]`), or list by UTC offset (`rails time:zones[-8]`)'
task :zones, :country_or_offset do |t, args|
zones, offset = ActiveSupport::TimeZone.all, nil