diff options
16 files changed, 67 insertions, 68 deletions
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb index cf8c0159e2..8c16308ce7 100644 --- a/actionpack/lib/action_controller/renderer.rb +++ b/actionpack/lib/action_controller/renderer.rb @@ -74,7 +74,7 @@ module ActionController # * <tt>:partial</tt> - See <tt>ActionView::PartialRenderer</tt> for details. # * <tt>:file</tt> - Renders an explicit template file. Add <tt>:locals</tt> to pass in, if so desired. # It shouldn’t be used directly with unsanitized user input due to lack of validation. - # * <tt>:inline</tt> - Renders a ERB template string. + # * <tt>:inline</tt> - Renders an ERB template string. # * <tt>:plain</tt> - Renders provided text and sets the content type as <tt>text/plain</tt>. # * <tt>:html</tt> - Renders the provided HTML safe string, otherwise # performs HTML escape on the string first. Sets the content type as <tt>text/html</tt>. diff --git a/actiontext/app/helpers/action_text/content_helper.rb b/actiontext/app/helpers/action_text/content_helper.rb index b3335601f9..2005033d5c 100644 --- a/actiontext/app/helpers/action_text/content_helper.rb +++ b/actiontext/app/helpers/action_text/content_helper.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "rails-html-sanitizer" + module ActionText module ContentHelper SANITIZER = Rails::Html::Sanitizer.white_list_sanitizer diff --git a/actionview/test/ujs/public/vendor/jquery-2.2.0.js b/actionview/test/ujs/public/vendor/jquery-2.2.0.js index 1e0ba99740..2c545b8ff3 100644 --- a/actionview/test/ujs/public/vendor/jquery-2.2.0.js +++ b/actionview/test/ujs/public/vendor/jquery-2.2.0.js @@ -5578,7 +5578,7 @@ var iframe, }; /** - * Retrieve the actual display of a element + * Retrieve the actual display of an element * @param {String} name nodeName of the element * @param {Object} doc Document object */ diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index c2087b8216..202187a047 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -522,7 +522,7 @@ module ActiveRecord end def default_uniqueness_comparison(attribute, value, klass) # :nodoc: - case_sensitive_comparison(attribute, value) + attribute.eq(value) end def case_sensitive_comparison(attribute, value) # :nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index d99c9b9d02..a518b897a0 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -461,15 +461,16 @@ module ActiveRecord def default_uniqueness_comparison(attribute, value, klass) # :nodoc: column = column_for_attribute(attribute) - if column.collation && !column.case_sensitive? + if column.collation && !column.case_sensitive? && !value.nil? ActiveSupport::Deprecation.warn(<<~MSG.squish) Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1. To continue case sensitive comparison on the :#{attribute.name} attribute in #{klass} model, pass `case_sensitive: true` option explicitly to the uniqueness validator. MSG + attribute.eq(Arel::Nodes::Bin.new(value)) + else + super end - - super end def case_sensitive_comparison(attribute, value) # :nodoc: diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 72ccf7739f..a09b5f0e96 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -93,7 +93,7 @@ module ActiveRecord # record or pass <tt>returning: false</tt> to omit the clause. # # [:unique_by] - # (Postgres and SQLite only) In a table with more than one unique constaint or index, + # (Postgres and SQLite only) In a table with more than one unique constraint or index, # new records may considered duplicates according to different criteria. By default, # new rows will be skipped if they violate _any_ unique constraint/index. By defining # <tt>:unique_by</tt>, you can skip rows that would create duplicates according to the given @@ -218,7 +218,7 @@ module ActiveRecord # record or pass <tt>returning: false</tt> to omit the clause. # # [:unique_by] - # (Postgres and SQLite only) In a table with more than one unique constaint or index, + # (Postgres and SQLite only) In a table with more than one unique constraint or index, # new records may considered duplicates according to different criteria. For MySQL, # an upsert will take place if a new record violates _any_ unique constraint. For # Postgres and SQLite, new rows will replace existing rows when the new row has the diff --git a/activerecord/lib/active_record/querying.rb b/activerecord/lib/active_record/querying.rb index 79af51bdba..36e2134c46 100644 --- a/activerecord/lib/active_record/querying.rb +++ b/activerecord/lib/active_record/querying.rb @@ -2,19 +2,23 @@ module ActiveRecord module Querying - delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all - delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, :third_to_last, :third_to_last!, :second_to_last, :second_to_last!, to: :all - delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all - delegate :find_or_create_by, :find_or_create_by!, :create_or_find_by, :create_or_find_by!, :find_or_initialize_by, to: :all - delegate :find_by, :find_by!, to: :all - delegate :destroy_all, :delete_all, :update_all, :destroy_by, :delete_by, to: :all - delegate :find_each, :find_in_batches, :in_batches, to: :all - delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or, - :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending, - :having, :create_with, :distinct, :references, :none, :unscope, :merge, - :reselect, to: :all - delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all - delegate :pluck, :pick, :ids, to: :all + QUERYING_METHODS = [ + :find, :find_by, :find_by!, :take, :take!, :first, :first!, :last, :last!, + :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, + :forty_two, :forty_two!, :third_to_last, :third_to_last!, :second_to_last, :second_to_last!, + :exists?, :any?, :many?, :none?, :one?, + :first_or_create, :first_or_create!, :first_or_initialize, + :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, + :create_or_find_by, :create_or_find_by!, + :destroy_all, :delete_all, :update_all, :destroy_by, :delete_by, + :find_each, :find_in_batches, :in_batches, + :select, :reselect, :order, :reorder, :group, :limit, :offset, :joins, :left_joins, :left_outer_joins, + :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending, :or, + :having, :create_with, :distinct, :references, :none, :unscope, :merge, :except, + :count, :average, :minimum, :maximum, :sum, :calculate, + :pluck, :pick, :ids + ].freeze # :nodoc: + delegate(*QUERYING_METHODS, to: :all) # Executes a custom SQL query against your database and returns all the results. The results will # be returned as an array, with the requested columns encapsulated as attributes of the model you call diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 9425332321..0f2cff4c9c 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -243,10 +243,10 @@ module ActiveRecord # Allows you to change a previously set select statement. # # Post.select(:title, :body) - # # SELECT `posts.title`, `posts.body` FROM `posts` + # # SELECT `posts`.`title`, `posts`.`body` FROM `posts` # # Post.select(:title, :body).reselect(:created_at) - # # SELECT `posts.created_at` FROM `posts` + # # SELECT `posts`.`created_at` FROM `posts` # # This is short-hand for <tt>unscope(:select).select(fields)</tt>. # Note that we're unscoping the entire select statement. diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 7451c15938..2c3a2fb797 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -60,9 +60,7 @@ module ActiveRecord comparison = relation.bind_attribute(attribute, value) do |attr, bind| return relation.none! if bind.unboundable? - if bind.nil? - attr.eq(bind) - elsif !options.key?(:case_sensitive) + if !options.key?(:case_sensitive) || bind.nil? klass.connection.default_uniqueness_comparison(attr, bind, klass) elsif options[:case_sensitive] klass.connection.case_sensitive_comparison(attr, bind) diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb index da82f62406..ba21923d79 100644 --- a/activerecord/test/cases/migration/foreign_key_test.rb +++ b/activerecord/test/cases/migration/foreign_key_test.rb @@ -20,7 +20,9 @@ if ActiveRecord::Base.connection.supports_foreign_keys? end end - module ForeignKeyChangeColumnSharedTest + class ForeignKeyChangeColumnTest < ActiveRecord::TestCase + self.use_transactional_tests = false + class Rocket < ActiveRecord::Base has_many :astronauts end @@ -141,17 +143,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? end end - class ForeignKeyChangeColumnTest < ActiveRecord::TestCase - include ForeignKeyChangeColumnSharedTest - - self.use_transactional_tests = false - end - - class ForeignKeyChangeColumnWithPrefixTest < ActiveRecord::TestCase - include ForeignKeyChangeColumnSharedTest - - self.use_transactional_tests = false - + class ForeignKeyChangeColumnWithPrefixTest < ForeignKeyChangeColumnTest setup do ActiveRecord::Base.table_name_prefix = "p_" end @@ -161,11 +153,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? end end - class ForeignKeyChangeColumnWithSuffixTest < ActiveRecord::TestCase - include ForeignKeyChangeColumnSharedTest - - self.use_transactional_tests = false - + class ForeignKeyChangeColumnWithSuffixTest < ForeignKeyChangeColumnTest setup do ActiveRecord::Base.table_name_suffix = "_p" end diff --git a/activerecord/test/cases/relation/delegation_test.rb b/activerecord/test/cases/relation/delegation_test.rb index 31e7a4b8f4..d04c409cb5 100644 --- a/activerecord/test/cases/relation/delegation_test.rb +++ b/activerecord/test/cases/relation/delegation_test.rb @@ -44,26 +44,28 @@ module ActiveRecord end class QueryingMethodsDelegationTest < ActiveRecord::TestCase - QUERYING_METHODS = [ - :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, - :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, :third_to_last, :third_to_last!, :second_to_last, :second_to_last!, - :first_or_create, :first_or_create!, :first_or_initialize, - :find_or_create_by, :find_or_create_by!, :create_or_find_by, :create_or_find_by!, :find_or_initialize_by, - :find_by, :find_by!, - :destroy_all, :delete_all, :update_all, :delete_by, :destroy_by, - :find_each, :find_in_batches, :in_batches, - :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or, - :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending, - :having, :create_with, :distinct, :references, :none, :unscope, :merge, - :count, :average, :minimum, :maximum, :sum, :calculate, - :pluck, :pick, :ids, :reselect, - ] + QUERYING_METHODS = + ActiveRecord::Batches.public_instance_methods(false) + + ActiveRecord::Calculations.public_instance_methods(false) + + ActiveRecord::FinderMethods.public_instance_methods(false) - [:raise_record_not_found_exception!] + + ActiveRecord::SpawnMethods.public_instance_methods(false) - [:spawn, :merge!, :only] + + ActiveRecord::QueryMethods.public_instance_methods(false).reject { |method| + method.to_s.end_with?("=", "!", "value", "values", "clause") + } - [:reverse_order, :arel, :extensions] + [ + :any?, :many?, :none?, :one?, + :first_or_create, :first_or_create!, :first_or_initialize, + :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, + :create_or_find_by, :create_or_find_by!, + :destroy_all, :delete_all, :update_all, :delete_by, :destroy_by + ] def test_delegate_querying_methods klass = Class.new(ActiveRecord::Base) do self.table_name = "posts" end + assert_equal QUERYING_METHODS.sort, ActiveRecord::Querying::QUERYING_METHODS.sort + QUERYING_METHODS.each do |method| assert_respond_to klass.all, method assert_respond_to klass, method diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb index c9eecc55f9..10e4c6b09d 100644 --- a/activesupport/lib/active_support/core_ext/array/access.rb +++ b/activesupport/lib/active_support/core_ext/array/access.rb @@ -31,21 +31,21 @@ class Array # Returns a new array that includes the passed elements. # - # Example: [ 1, 2, 3 ].including(4, 5) => [ 1, 2, 3, 4, 5 ] + # [ 1, 2, 3 ].including(4, 5) => [ 1, 2, 3, 4, 5 ] + # [ [ 0, 1 ] ].including([ [ 1, 0 ] ]) => [ [ 0, 1 ], [ 1, 0 ] ] def including(*elements) - self + elements.flatten + self + elements.flatten(1) end # Returns a copy of the Array excluding the specified elements. # - # people = ["David", "Rafael", "Aaron", "Todd"] - # people.excluding "Aaron", "Todd" - # # => ["David", "Rafael"] + # ["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") => ["David", "Rafael"] + # [ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) => [ [ 0, 1 ] ] # # Note: This is an optimization of <tt>Enumerable#excluding</tt> that uses <tt>Array#-</tt> # instead of <tt>Array#reject</tt> for performance reasons. def excluding(*elements) - self - elements.flatten + self - elements.flatten(1) end # Alias for #excluding. diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb index d6fb89e588..4675c41936 100644 --- a/activesupport/lib/active_support/core_ext/enumerable.rb +++ b/activesupport/lib/active_support/core_ext/enumerable.rb @@ -125,7 +125,7 @@ module Enumerable # {foo: 1, bar: 2, baz: 3}.excluding :bar # # => {foo: 1, baz: 3} def excluding(*elements) - elements.flatten! + elements.flatten!(1) reject { |element| elements.include?(element) } end diff --git a/activesupport/test/core_ext/array/access_test.rb b/activesupport/test/core_ext/array/access_test.rb index 8f89c3f25c..427b058925 100644 --- a/activesupport/test/core_ext/array/access_test.rb +++ b/activesupport/test/core_ext/array/access_test.rb @@ -35,11 +35,13 @@ class AccessTest < ActiveSupport::TestCase def test_including assert_equal [1, 2, 3, 4, 5], [1, 2, 4].including(3, 5).sort assert_equal [1, 2, 3, 4, 5], [1, 2, 4].including([3, 5]).sort + assert_equal [[0, 1], [1, 0]], [[0, 1]].including([[1, 0]]) end def test_excluding assert_equal [1, 2, 4], [1, 2, 3, 4, 5].excluding(3, 5) assert_equal [1, 2, 4], [1, 2, 3, 4, 5].excluding([3, 5]) + assert_equal [[0, 1]], [[0, 1], [1, 0]].excluding([[1, 0]]) end def test_without diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb index 4e9cf3848d..381b5a1f32 100644 --- a/activesupport/test/core_ext/enumerable_test.rb +++ b/activesupport/test/core_ext/enumerable_test.rb @@ -220,6 +220,7 @@ class EnumerableTests < ActiveSupport::TestCase def test_excluding assert_equal [1, 2, 4], GenericEnumerable.new((1..5).to_a).excluding(3, 5) assert_equal [3, 4, 5], GenericEnumerable.new((1..5).to_a).excluding([1, 2]) + assert_equal [[0, 1]], GenericEnumerable.new([[0, 1], [1, 0]]).excluding([[1, 0]]) assert_equal [1, 2, 4], (1..5).to_a.excluding(3, 5) assert_equal [1, 2, 4], (1..5).to_set.excluding(3, 5) assert_equal({ foo: 1, baz: 3 }, { foo: 1, bar: 2, baz: 3 }.excluding(:bar)) diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md index 30493038e7..24dea0ec46 100644 --- a/guides/source/active_record_querying.md +++ b/guides/source/active_record_querying.md @@ -611,7 +611,8 @@ If you want to call `order` multiple times, subsequent orders will be appended t Client.order("orders_count ASC").order("created_at DESC") # SELECT * FROM clients ORDER BY orders_count ASC, created_at DESC ``` -WARNING: If you are using **MySQL 5.7.5** and above, then on selecting fields from a result set using methods like `select`, `pluck` and `ids`; the `order` method will raise an `ActiveRecord::StatementInvalid` exception unless the field(s) used in `order` clause are included in the select list. See the next section for selecting fields from the result set. + +WARNING: In most database systems, on selecting fields with `distinct` from a result set using methods like `select`, `pluck` and `ids`; the `order` method will raise an `ActiveRecord::StatementInvalid` exception unless the field(s) used in `order` clause are included in the select list. See the next section for selecting fields from the result set. Selecting Specific Fields ------------------------- @@ -818,19 +819,19 @@ Post.select(:title, :body).reselect(:created_at) The SQL that would be executed: ```sql -SELECT `posts.created_at` FROM `posts` +SELECT `posts`.`created_at` FROM `posts` ``` In case the `reselect` clause is not used, ```ruby -Post.select(:title, :body) +Post.select(:title, :body).select(:created_at) ``` the SQL executed would be: ```sql -SELECT `posts.title`, `posts.body` FROM `posts` +SELECT `posts`.`title`, `posts`.`body`, `posts`.`created_at` FROM `posts` ``` ### `reorder` |