aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--actioncable/test/client_test.rb2
-rw-r--r--actionmailbox/test/dummy/config/initializers/backtrace_silencers.rb2
-rw-r--r--actionmailer/lib/action_mailer/base.rb2
-rw-r--r--actionpack/CHANGELOG.md11
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb2
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb2
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb2
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb2
-rw-r--r--actionpack/lib/action_controller/test_case.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/content_security_policy.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/feature_policy.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/filter_parameters.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/filter_redirect.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb10
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb10
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb2
-rw-r--r--actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb52
-rw-r--r--actionpack/test/controller/integration_test.rb2
-rw-r--r--actionpack/test/controller/log_subscriber_test.rb2
-rw-r--r--actionpack/test/dispatch/mime_type_test.rb18
-rw-r--r--actionpack/test/dispatch/request/json_params_parsing_test.rb2
-rw-r--r--actionpack/test/dispatch/routing_test.rb10
-rw-r--r--actionpack/test/dispatch/ssl_test.rb4
-rw-r--r--actionpack/test/dispatch/system_testing/screenshot_helper_test.rb79
-rw-r--r--actiontext/lib/action_text/attachables/remote_image.rb2
-rw-r--r--actiontext/lib/action_text/attachment_gallery.rb2
-rw-r--r--actiontext/test/dummy/config/initializers/backtrace_silencers.rb2
-rw-r--r--actionview/lib/action_view/helpers/form_options_helper.rb4
-rw-r--r--actionview/lib/action_view/helpers/text_helper.rb2
-rw-r--r--actionview/test/activerecord/relation_cache_test.rb17
-rw-r--r--actionview/test/template/form_options_helper_test.rb2
-rw-r--r--actionview/test/template/output_safety_helper_test.rb8
-rw-r--r--activemodel/lib/active_model/type/helpers/timezone.rb2
-rw-r--r--activemodel/lib/active_model/validations/validates.rb4
-rw-r--r--activerecord/CHANGELOG.md14
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb3
-rw-r--r--activerecord/lib/active_record/errors.rb4
-rw-r--r--activerecord/lib/active_record/fixture_set/file.rb6
-rw-r--r--activerecord/lib/active_record/fixtures.rb45
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb46
-rw-r--r--activerecord/lib/active_record/tasks/database_tasks.rb1
-rw-r--r--activerecord/lib/active_record/tasks/mysql_database_tasks.rb6
-rw-r--r--activerecord/lib/active_record/tasks/postgresql_database_tasks.rb6
-rw-r--r--activerecord/lib/arel/visitors/mysql.rb8
-rw-r--r--activerecord/test/cases/arel/nodes/node_test.rb2
-rw-r--r--activerecord/test/cases/arel/visitors/mysql_test.rb46
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb5
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb5
-rw-r--r--activerecord/test/cases/associations/inner_join_association_test.rb37
-rw-r--r--activerecord/test/cases/enum_test.rb4
-rw-r--r--activerecord/test/cases/fixtures_test.rb29
-rw-r--r--activerecord/test/cases/tasks/mysql_rake_test.rb6
-rw-r--r--activerecord/test/cases/tasks/postgresql_rake_test.rb2
-rw-r--r--activerecord/test/fixtures/other_books.yml26
-rw-r--r--activerecord/test/fixtures/parrots.yml8
-rw-r--r--activestorage/test/dummy/config/initializers/backtrace_silencers.rb2
-rw-r--r--activesupport/lib/active_support/backtrace_cleaner.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/string/access.rb26
-rw-r--r--activesupport/lib/active_support/dependencies.rb1
-rw-r--r--activesupport/lib/active_support/dependencies/zeitwerk_integration.rb13
-rw-r--r--activesupport/lib/active_support/inflector/transliterate.rb2
-rw-r--r--activesupport/lib/active_support/multibyte/chars.rb2
-rw-r--r--activesupport/lib/active_support/parameter_filter.rb2
-rw-r--r--activesupport/lib/active_support/secure_compare_rotator.rb1
-rw-r--r--activesupport/lib/active_support/values/time_zone.rb7
-rw-r--r--activesupport/test/cache/stores/mem_cache_store_test.rb2
-rw-r--r--activesupport/test/cache/stores/redis_cache_store_test.rb2
-rw-r--r--activesupport/test/callbacks_test.rb2
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb32
-rw-r--r--activesupport/test/multibyte_chars_test.rb6
-rw-r--r--activesupport/test/parameter_filter_test.rb4
-rw-r--r--activesupport/test/time_zone_test.rb13
-rw-r--r--guides/rails_guides/kindle.rb2
-rw-r--r--guides/source/action_mailer_basics.md2
-rw-r--r--guides/source/working_with_javascript_in_rails.md6
-rw-r--r--railties/lib/rails/code_statistics_calculator.rb8
-rw-r--r--railties/lib/rails/command/behavior.rb2
-rw-r--r--railties/lib/rails/command/environment_argument.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb2
-rw-r--r--railties/lib/rails/generators/generated_attribute.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt1
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt2
-rw-r--r--railties/lib/rails/test_unit/runner.rb2
-rw-r--r--railties/test/application/assets_test.rb2
-rw-r--r--railties/test/application/configuration_test.rb4
-rw-r--r--railties/test/application/zeitwerk_integration_test.rb29
-rw-r--r--railties/test/generators/app_generator_test.rb6
-rw-r--r--railties/test/railties/engine_test.rb2
96 files changed, 578 insertions, 222 deletions
diff --git a/README.md b/README.md
index 98ade9b445..fe3b5b9d9a 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ the [Active Model](activemodel/README.rdoc) module.
## Controller layer
The _**Controller layer**_ is responsible for handling incoming HTTP requests and
-providing a suitable response. Usually this means returning HTML, but Rails controllers
+providing a suitable response. Usually, this means returning HTML, but Rails controllers
can also generate XML, JSON, PDFs, mobile-specific views, and more. Controllers load and
manipulate models, and render view templates in order to generate the appropriate HTTP response.
In Rails, incoming requests are routed by Action Dispatch to an appropriate controller, and
@@ -37,7 +37,7 @@ are bundled together in [Action Pack](actionpack/README.rdoc).
The _**View layer**_ is composed of "templates" that are responsible for providing
appropriate representations of your application's resources. Templates can
come in a variety of formats, but most view templates are HTML with embedded
-Ruby code (ERB files). Views are typically rendered to generate a controller response,
+Ruby code (ERB files). Views are typically rendered to generate a controller response
or to generate the body of an email. In Rails, View generation is handled by [Action View](actionview/README.rdoc).
## Frameworks and libraries
diff --git a/actioncable/test/client_test.rb b/actioncable/test/client_test.rb
index bf141df458..eed514db10 100644
--- a/actioncable/test/client_test.rb
+++ b/actioncable/test/client_test.rb
@@ -91,7 +91,7 @@ class ClientTest < ActionCable::TestCase
rescue RuntimeError => ex
# Work around https://bugs.ruby-lang.org/issues/13239
- raise unless ex.message =~ /can't modify frozen IOError/
+ raise unless ex.message.match?(/can't modify frozen IOError/)
# Handle this as if it were the IOError: do the same as above.
server.binder.close
diff --git a/actionmailbox/test/dummy/config/initializers/backtrace_silencers.rb b/actionmailbox/test/dummy/config/initializers/backtrace_silencers.rb
index 59385cdf37..3c56b21b3c 100644
--- a/actionmailbox/test/dummy/config/initializers/backtrace_silencers.rb
+++ b/actionmailbox/test/dummy/config/initializers/backtrace_silencers.rb
@@ -1,7 +1,7 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
-# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index eb0885953b..78264d21d1 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -408,7 +408,7 @@ module ActionMailer
# really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name
# of an OpenSSL verify constant (<tt>'none'</tt> or <tt>'peer'</tt>) or directly the constant
# (<tt>OpenSSL::SSL::VERIFY_NONE</tt> or <tt>OpenSSL::SSL::VERIFY_PEER</tt>).
- # <tt>:ssl/:tls</tt> Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection)
+ # * <tt>:ssl/:tls</tt> Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection)
#
# * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method.
# * <tt>:location</tt> - The location of the sendmail executable. Defaults to <tt>/usr/sbin/sendmail</tt>.
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 8bb2c73e52..90217755bc 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,12 @@
+* Allow system test screen shots to be taken more than once in
+ a test by prefixing the file name with an incrementing counter.
+
+ Add an environment variable `RAILS_SYSTEM_TESTING_SCREENSHOT_HTML` to
+ enable saving of HTML during a screenshot in addition to the image.
+ This uses the same image name, with the extension replaced with `.html`
+
+ *Tom Fakes*
+
* Add `Vary: Accept` header when using `Accept` header for response
For some requests like `/users/1`, Rails uses requests' `Accept`
@@ -80,7 +89,7 @@
*Gustavo Gutierrez*
-* Calling `ActionController::Parameters#transform_keys/!` without a block now returns
+* Calling `ActionController::Parameters#transform_keys`/`!` without a block now returns
an enumerator for the parameters instead of the underlying hash.
*Eugene Kenny*
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 6a274d35cb..ec0c9ecc67 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -482,7 +482,7 @@ module ActionController
def raw_params(auth)
_raw_params = auth.sub(TOKEN_REGEX, "").split(/\s*#{AUTHN_PAIR_DELIMITERS}\s*/)
- if !(_raw_params.first =~ %r{\A#{TOKEN_KEY}})
+ if !(%r{\A#{TOKEN_KEY}}.match?(_raw_params.first))
_raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
end
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index 5c6f7fe396..a993c76af9 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -142,7 +142,7 @@ module ActionController #:nodoc:
#
# You can set the variant in a +before_action+:
#
- # request.variant = :tablet if request.user_agent =~ /iPad/
+ # request.variant = :tablet if /iPad/.match?(request.user_agent)
#
# Respond to variants in the action just like you respond to formats:
#
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 5a5c04234b..e923afb17c 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -280,7 +280,7 @@ module ActionController #:nodoc:
# Check for cross-origin JavaScript responses.
def non_xhr_javascript_response? # :doc:
- content_type =~ %r(\A(?:text|application)/javascript) && !request.xhr?
+ %r(\A(?:text|application)/javascript).match?(content_type) && !request.xhr?
end
AUTHENTICITY_TOKEN_LENGTH = 32
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 920ae52f2b..4c9eb20c65 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -225,7 +225,7 @@ module ActionController
class << self
def nested_attribute?(key, value) # :nodoc:
- key =~ /\A-?\d+\z/ && (value.is_a?(Hash) || value.is_a?(Parameters))
+ /\A-?\d+\z/.match?(key) && (value.is_a?(Hash) || value.is_a?(Parameters))
end
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 47e0099f20..1632ac3ae8 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -593,8 +593,8 @@ module ActionController
private
def scrub_env!(env)
- env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
- env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
+ env.delete_if { |k, v| k.match?(/^(action_dispatch|rack)\.request/) }
+ env.delete_if { |k, v| k.match?(/^action_dispatch\.rescue/) }
env.delete "action_dispatch.request.query_parameters"
env.delete "action_dispatch.request.request_parameters"
env["rack.input"] = StringIO.new
diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb
index 9c430b57e3..e8cf1b95a5 100644
--- a/actionpack/lib/action_dispatch/http/content_security_policy.rb
+++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb
@@ -33,7 +33,7 @@ module ActionDispatch #:nodoc:
private
def html_response?(headers)
if content_type = headers[CONTENT_TYPE]
- content_type =~ /html/
+ /html/.match?(content_type)
end
end
diff --git a/actionpack/lib/action_dispatch/http/feature_policy.rb b/actionpack/lib/action_dispatch/http/feature_policy.rb
index 592b6e4393..78e982918d 100644
--- a/actionpack/lib/action_dispatch/http/feature_policy.rb
+++ b/actionpack/lib/action_dispatch/http/feature_policy.rb
@@ -33,7 +33,7 @@ module ActionDispatch #:nodoc:
private
def html_response?(headers)
if content_type = headers[CONTENT_TYPE]
- content_type =~ /html/
+ /html/.match?(content_type)
end
end
diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb
index 7a7a493f64..7ad1ba3e0e 100644
--- a/actionpack/lib/action_dispatch/http/filter_parameters.rb
+++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb
@@ -23,7 +23,7 @@ module ActionDispatch
# change { file: { code: "xxxx"} }
#
# env["action_dispatch.parameter_filter"] = -> (k, v) do
- # v.reverse! if k =~ /secret/i
+ # v.reverse! if k.match?(/secret/i)
# end
# => reverses the value to all keys matching /secret/i
module FilterParameters
diff --git a/actionpack/lib/action_dispatch/http/filter_redirect.rb b/actionpack/lib/action_dispatch/http/filter_redirect.rb
index d780d5f793..3bd1f5109d 100644
--- a/actionpack/lib/action_dispatch/http/filter_redirect.rb
+++ b/actionpack/lib/action_dispatch/http/filter_redirect.rb
@@ -27,7 +27,7 @@ module ActionDispatch
if String === filter
location.include?(filter)
elsif Regexp === filter
- location =~ filter
+ location.match?(filter)
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index ed1d50f3b9..60b78c0582 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -202,7 +202,7 @@ module Mime
# For an input of <tt>'application'</tt>, returns <tt>[Mime[:html], Mime[:js],
# Mime[:xml], Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]</tt>.
def parse_data_with_trailing_star(type)
- Mime::SET.select { |m| m =~ type }
+ Mime::SET.select { |m| m.match?(type) }
end
# This method is opposite of register method.
@@ -283,8 +283,14 @@ module Mime
@synonyms.any? { |synonym| synonym.to_s =~ regexp } || @string =~ regexp
end
+ def match?(mime_type)
+ return false unless mime_type
+ regexp = Regexp.new(Regexp.quote(mime_type.to_s))
+ @synonyms.any? { |synonym| synonym.to_s.match?(regexp) } || @string.match?(regexp)
+ end
+
def html?
- symbol == :html || @string =~ /html/
+ (symbol == :html) || /html/.match?(@string)
end
def all?; false; end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 4ac7c5c2bd..c78cf4ee8c 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -265,7 +265,7 @@ module ActionDispatch
# (case-insensitive), which may need to be manually added depending on the
# choice of JavaScript libraries and frameworks.
def xml_http_request?
- get_header("HTTP_X_REQUESTED_WITH") =~ /XMLHttpRequest/i
+ /XMLHttpRequest/i.match?(get_header("HTTP_X_REQUESTED_WITH"))
end
alias :xhr? :xml_http_request?
@@ -400,7 +400,7 @@ module ActionDispatch
# True if the request came from localhost, 127.0.0.1, or ::1.
def local?
- LOCALHOST =~ remote_addr && LOCALHOST =~ remote_ip
+ LOCALHOST.match?(remote_addr) && LOCALHOST.match?(remote_ip)
end
def request_parameters=(params)
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index 00902ede21..34b213d14e 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -13,7 +13,7 @@ module ActionDispatch
#
# Requests can opt-out of redirection with +exclude+:
#
- # config.ssl_options = { redirect: { exclude: -> request { request.path =~ /healthcheck/ } } }
+ # config.ssl_options = { redirect: { exclude: -> request { /healthcheck/.match?(request.path) } } }
#
# Cookies will not be flagged as secure for excluded requests.
#
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index 1f2f7757a3..875c7f9ba1 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -83,11 +83,11 @@ module ActionDispatch
end
def gzip_encoding_accepted?(request)
- request.accept_encoding.any? { |enc, quality| enc =~ /\bgzip\b/i }
+ request.accept_encoding.any? { |enc, quality| /\bgzip\b/i.match?(enc) }
end
def gzip_file_path(path)
- can_gzip_mime = content_type(path) =~ /\A(?:text\/|application\/javascript)/
+ can_gzip_mime = /\A(?:text\/|application\/javascript)/.match?(content_type(path))
gzip_path = "#{path}.gz"
if can_gzip_mime && File.exist?(File.join(@root, ::Rack::Utils.unescape_path(gzip_path)))
gzip_path
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
index 6e40a18009..bf286c299d 100644
--- a/actionpack/lib/action_dispatch/routing/inspector.rb
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -94,7 +94,7 @@ module ActionDispatch
if filter
@routes.select do |route|
route_wrapper = RouteWrapper.new(route)
- filter.any? { |default, value| route_wrapper.send(default) =~ value }
+ filter.any? { |default, value| value.match?(route_wrapper.send(default)) }
end
else
@routes
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index e3090e7ba2..42e770c5bf 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -367,7 +367,7 @@ module ActionDispatch
def translate_controller(controller)
return controller if Regexp === controller
- return controller.to_s if controller =~ /\A[a-z_0-9][a-z_0-9\/]*\z/
+ return controller.to_s if /\A[a-z_0-9][a-z_0-9\/]*\z/.match?(controller)
yield
end
@@ -403,7 +403,7 @@ module ActionDispatch
# for root cases, where the latter is the correct one.
def self.normalize_path(path)
path = Journey::Router::Utils.normalize_path(path)
- path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/(\(+[^)]+\)){1,}$}
+ path.gsub!(%r{/(\(+)/?}, '\1/') unless %r{^/(\(+[^)]+\)){1,}$}.match?(path)
path
end
@@ -996,7 +996,7 @@ module ActionDispatch
#
# Requests to routes can be constrained based on specific criteria:
#
- # constraints(-> (req) { req.env["HTTP_USER_AGENT"] =~ /iPhone/ }) do
+ # constraints(-> (req) { /iPhone/.match?(req.env["HTTP_USER_AGENT"]) }) do
# resources :iphones
# end
#
@@ -1006,7 +1006,7 @@ module ActionDispatch
#
# class Iphone
# def self.matches?(request)
- # request.env["HTTP_USER_AGENT"] =~ /iPhone/
+ # /iPhone/.match?(request.env["HTTP_USER_AGENT"])
# end
# end
#
@@ -1916,7 +1916,7 @@ module ActionDispatch
end
def using_match_shorthand?(path)
- path =~ %r{^/?[-\w]+/[-\w/]+$}
+ %r{^/?[-\w]+/[-\w/]+$}.match?(path)
end
def decomposed_match(path, controller, options, _path, to, via, formatted, anchor, options_constraints)
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 5b35b68c44..db8c54ba84 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -836,7 +836,7 @@ module ActionDispatch
def recognize_path(path, environment = {})
method = (environment[:method] || "GET").to_s.upcase
- path = Journey::Router::Utils.normalize_path(path) unless path =~ %r{://}
+ path = Journey::Router::Utils.normalize_path(path) unless %r{://}.match?(path)
extras = environment[:extras] || {}
begin
diff --git a/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb b/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
index 056ce51a61..cba053ee4c 100644
--- a/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
+++ b/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
@@ -9,10 +9,16 @@ module ActionDispatch
#
# +take_screenshot+ can be used at any point in your system tests to take
# a screenshot of the current state. This can be useful for debugging or
- # automating visual testing.
+ # automating visual testing. You can take multiple screenshots per test
+ # to investigate changes at different points during your test. These will be
+ # named with a sequential prefix (or 'failed' for failing tests)
#
# The screenshot will be displayed in your console, if supported.
#
+ # You can set the +RAILS_SYSTEM_TESTING_SCREENSHOT_HTML+ environment variable to
+ # save the HTML from the page that is being screenhoted so you can investigate the
+ # elements on the page at the time of the screenshot
+ #
# You can set the +RAILS_SYSTEM_TESTING_SCREENSHOT+ environment variable to
# control the output. Possible values are:
# * [+simple+ (default)] Only displays the screenshot path.
@@ -22,6 +28,8 @@ module ActionDispatch
# * [+artifact+] Display the screenshot in the terminal, using the terminal
# artifact format (https://buildkite.github.io/terminal-to-html/inline-images/).
def take_screenshot
+ increment_unique
+ save_html if save_html?
save_image
puts display_image
end
@@ -38,17 +46,48 @@ module ActionDispatch
end
private
+ attr_accessor :_screenshot_counter
+
+ def save_html?
+ ENV["RAILS_SYSTEM_TESTING_SCREENSHOT_HTML"] == "1"
+ end
+
+ def increment_unique
+ @_screenshot_counter ||= 0
+ @_screenshot_counter += 1
+ end
+
+ def unique
+ failed? ? "failures" : (_screenshot_counter || 0).to_s
+ end
+
def image_name
- name = method_name[0...225]
- failed? ? "failures_#{name}" : name
+ name = "#{unique}_#{method_name}"
+ name[0...225]
end
def image_path
- @image_path ||= absolute_image_path.to_s
+ absolute_image_path.to_s
+ end
+
+ def html_path
+ absolute_html_path.to_s
+ end
+
+ def absolute_path
+ Rails.root.join("tmp/screenshots/#{image_name}")
end
def absolute_image_path
- Rails.root.join("tmp/screenshots/#{image_name}.png")
+ "#{absolute_path}.png"
+ end
+
+ def absolute_html_path
+ "#{absolute_path}.html"
+ end
+
+ def save_html
+ page.save_page(absolute_html_path)
end
def save_image
@@ -66,7 +105,8 @@ module ActionDispatch
end
def display_image
- message = +"[Screenshot]: #{image_path}\n"
+ message = +"[Screenshot Image]: #{image_path}\n"
+ message << +"[Screenshot HTML]: #{html_path}\n" if save_html?
case output_type
when "artifact"
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index cb7c2467ac..4f5f5b71ae 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -606,7 +606,7 @@ class MetalIntegrationTest < ActionDispatch::IntegrationTest
class Poller
def self.call(env)
- if env["PATH_INFO"] =~ /^\/success/
+ if /^\/success/.match?(env["PATH_INFO"])
[200, { "Content-Type" => "text/plain", "Content-Length" => "12" }, ["Hello World!"]]
else
[404, { "Content-Type" => "text/plain", "Content-Length" => "0" }, []]
diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb
index 1a7e7f6cbb..46ab7b4f74 100644
--- a/actionpack/test/controller/log_subscriber_test.rb
+++ b/actionpack/test/controller/log_subscriber_test.rb
@@ -139,7 +139,7 @@ class ACLogSubscriberTest < ActionController::TestCase
def test_process_action_without_parameters
get :show
wait
- assert_nil logs.detect { |l| l =~ /Parameters/ }
+ assert_nil logs.detect { |l| /Parameters/.match?(l) }
end
def test_process_action_with_parameters
diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb
index da417a1604..b0b2aa0cc1 100644
--- a/actionpack/test/dispatch/mime_type_test.rb
+++ b/actionpack/test/dispatch/mime_type_test.rb
@@ -167,12 +167,18 @@ class MimeTypeTest < ActiveSupport::TestCase
end
test "regexp matcher" do
- assert_match Mime[:js], "text/javascript"
- assert_match Mime[:js], "application/javascript"
- assert_no_match Mime[:js], "text/html"
- assert_match Mime[:js], "text/javascript"
- assert_match Mime[:js], "application/javascript"
- assert_match Mime[:html], "application/xhtml+xml"
+ assert Mime[:js] =~ "text/javascript"
+ assert Mime[:js] =~ "application/javascript"
+ assert Mime[:js] !~ "text/html"
+ assert_not (Mime[:js] !~ "text/javascript")
+ assert_not (Mime[:js] !~ "application/javascript")
+ assert Mime[:html] =~ "application/xhtml+xml"
+ end
+
+ test "match?" do
+ assert Mime[:js].match?("text/javascript")
+ assert Mime[:js].match?("application/javascript")
+ assert_not Mime[:js].match?("text/html")
end
test "can be initialized with wildcards" do
diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb
index 2a48a12497..bbf98912f3 100644
--- a/actionpack/test/dispatch/request/json_params_parsing_test.rb
+++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb
@@ -68,7 +68,7 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest
post "/parse", params: json, headers: { "CONTENT_TYPE" => "application/json", "action_dispatch.show_exceptions" => true, "action_dispatch.logger" => ActiveSupport::Logger.new(output) }
assert_response :bad_request
output.rewind && err = output.read
- assert err =~ /Error occurred while parsing request parameters/
+ assert err.match?(/Error occurred while parsing request parameters/)
end
end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index b67b1dd347..d4a667a13a 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -12,7 +12,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
class IpRestrictor
def self.matches?(request)
- request.ip =~ /192\.168\.1\.1\d\d/
+ /192\.168\.1\.1\d\d/.match?(request.ip)
end
end
@@ -3823,7 +3823,7 @@ private
end
def method_missing(method, *args, &block)
- if method.to_s =~ /_(path|url)$/
+ if method.to_s.match?(/_(path|url)$/)
@app.routes.url_helpers.send(method, *args, &block)
else
super
@@ -5137,7 +5137,7 @@ class TestRecognizePath < ActionDispatch::IntegrationTest
end
def matches?(request)
- request.path_parameters[key] =~ pattern
+ pattern.match?(request.path_parameters[key])
end
end
@@ -5147,8 +5147,8 @@ class TestRecognizePath < ActionDispatch::IntegrationTest
get "/hash/:foo", to: "pages#show", constraints: { foo: /foo/ }
get "/hash/:bar", to: "pages#show", constraints: { bar: /bar/ }
- get "/proc/:foo", to: "pages#show", constraints: proc { |r| r.path_parameters[:foo] =~ /foo/ }
- get "/proc/:bar", to: "pages#show", constraints: proc { |r| r.path_parameters[:bar] =~ /bar/ }
+ get "/proc/:foo", to: "pages#show", constraints: proc { |r| /foo/.match?(r.path_parameters[:foo]) }
+ get "/proc/:bar", to: "pages#show", constraints: proc { |r| /bar/.match?(r.path_parameters[:bar]) }
get "/class/:foo", to: "pages#show", constraints: PageConstraint.new(:foo, /foo/)
get "/class/:bar", to: "pages#show", constraints: PageConstraint.new(:bar, /bar/)
diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb
index baf46e7c7e..44fe433c5f 100644
--- a/actionpack/test/dispatch/ssl_test.rb
+++ b/actionpack/test/dispatch/ssl_test.rb
@@ -42,7 +42,7 @@ class RedirectSSLTest < SSLTest
end
test "exclude can avoid redirect" do
- excluding = { exclude: -> request { request.path =~ /healthcheck/ } }
+ excluding = { exclude: -> request { request.path.match?(/healthcheck/) } }
assert_not_redirected "http://example.org/healthcheck", redirect: excluding
assert_redirected from: "http://example.org/", redirect: excluding
@@ -209,7 +209,7 @@ class SecureCookiesTest < SSLTest
end
def test_cookies_as_not_secure_with_exclude
- excluding = { exclude: -> request { request.domain =~ /example/ } }
+ excluding = { exclude: -> request { /example/.match?(request.domain) } }
get headers: { "Set-Cookie" => DEFAULT }, ssl_options: { redirect: excluding }
assert_cookies(*DEFAULT.split("\n"))
diff --git a/actionpack/test/dispatch/system_testing/screenshot_helper_test.rb b/actionpack/test/dispatch/system_testing/screenshot_helper_test.rb
index b0b36f9d74..5d69a887ef 100644
--- a/actionpack/test/dispatch/system_testing/screenshot_helper_test.rb
+++ b/actionpack/test/dispatch/system_testing/screenshot_helper_test.rb
@@ -6,60 +6,93 @@ require "capybara/dsl"
require "selenium/webdriver"
class ScreenshotHelperTest < ActiveSupport::TestCase
+ def setup
+ @new_test = DrivenBySeleniumWithChrome.new("x")
+ @new_test.send("_screenshot_counter=", nil)
+ end
+
test "image path is saved in tmp directory" do
- new_test = DrivenBySeleniumWithChrome.new("x")
+ Rails.stub :root, Pathname.getwd do
+ assert_equal Rails.root.join("tmp/screenshots/0_x.png").to_s, @new_test.send(:image_path)
+ end
+ end
+
+ test "image path unique counter is changed when incremented" do
+ @new_test.send(:increment_unique)
Rails.stub :root, Pathname.getwd do
- assert_equal Rails.root.join("tmp/screenshots/x.png").to_s, new_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/1_x.png").to_s, @new_test.send(:image_path)
end
end
- test "image path includes failures text if test did not pass" do
- new_test = DrivenBySeleniumWithChrome.new("x")
+ # To allow multiple screenshots in same test
+ test "image path unique counter generates different path in same test" do
+ Rails.stub :root, Pathname.getwd do
+ @new_test.send(:increment_unique)
+ assert_equal Rails.root.join("tmp/screenshots/1_x.png").to_s, @new_test.send(:image_path)
+
+ @new_test.send(:increment_unique)
+ assert_equal Rails.root.join("tmp/screenshots/2_x.png").to_s, @new_test.send(:image_path)
+ end
+ end
+ test "image path includes failures text if test did not pass" do
Rails.stub :root, Pathname.getwd do
- new_test.stub :passed?, false do
- assert_equal Rails.root.join("tmp/screenshots/failures_x.png").to_s, new_test.send(:image_path)
+ @new_test.stub :passed?, false do
+ assert_equal Rails.root.join("tmp/screenshots/failures_x.png").to_s, @new_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/failures_x.html").to_s, @new_test.send(:html_path)
end
end
end
test "image path does not include failures text if test skipped" do
- new_test = DrivenBySeleniumWithChrome.new("x")
-
Rails.stub :root, Pathname.getwd do
- new_test.stub :passed?, false do
- new_test.stub :skipped?, true do
- assert_equal Rails.root.join("tmp/screenshots/x.png").to_s, new_test.send(:image_path)
+ @new_test.stub :passed?, false do
+ @new_test.stub :skipped?, true do
+ assert_equal Rails.root.join("tmp/screenshots/0_x.png").to_s, @new_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/0_x.html").to_s, @new_test.send(:html_path)
end
end
end
end
- test "image name truncates names over 225 characters" do
- new_test = DrivenBySeleniumWithChrome.new("x" * 400)
+ test "image name truncates names over 225 characters including counter" do
+ long_test = DrivenBySeleniumWithChrome.new("x" * 400)
Rails.stub :root, Pathname.getwd do
- assert_equal Rails.root.join("tmp/screenshots/#{"x" * 225}.png").to_s, new_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/0_#{"x" * 223}.png").to_s, long_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/0_#{"x" * 223}.html").to_s, long_test.send(:html_path)
end
end
test "defaults to simple output for the screenshot" do
- new_test = DrivenBySeleniumWithChrome.new("x")
- assert_equal "simple", new_test.send(:output_type)
+ assert_equal "simple", @new_test.send(:output_type)
+ end
+
+ test "display_image return html path when RAILS_SYSTEM_TESTING_SCREENSHOT_HTML environment" do
+ original_html_setting = ENV["RAILS_SYSTEM_TESTING_SCREENSHOT_HTML"]
+ ENV["RAILS_SYSTEM_TESTING_SCREENSHOT_HTML"] = "1"
+
+ assert @new_test.send(:save_html?)
+
+ Rails.stub :root, Pathname.getwd do
+ @new_test.stub :passed?, false do
+ assert_match %r|\[Screenshot HTML\].+?tmp/screenshots/failures_x\.html|, @new_test.send(:display_image)
+ end
+ end
+ ensure
+ ENV["RAILS_SYSTEM_TESTING_SCREENSHOT_HTML"] = original_html_setting
end
test "display_image return artifact format when specify RAILS_SYSTEM_TESTING_SCREENSHOT environment" do
original_output_type = ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"]
ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"] = "artifact"
- new_test = DrivenBySeleniumWithChrome.new("x")
-
- assert_equal "artifact", new_test.send(:output_type)
+ assert_equal "artifact", @new_test.send(:output_type)
Rails.stub :root, Pathname.getwd do
- new_test.stub :passed?, false do
- assert_match %r|url=artifact://.+?tmp/screenshots/failures_x\.png|, new_test.send(:display_image)
+ @new_test.stub :passed?, false do
+ assert_match %r|url=artifact://.+?tmp/screenshots/failures_x\.png|, @new_test.send(:display_image)
end
end
ensure
@@ -67,10 +100,8 @@ class ScreenshotHelperTest < ActiveSupport::TestCase
end
test "image path returns the absolute path from root" do
- new_test = DrivenBySeleniumWithChrome.new("x")
-
Rails.stub :root, Pathname.getwd.join("..") do
- assert_equal Rails.root.join("tmp/screenshots/x.png").to_s, new_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/0_x.png").to_s, @new_test.send(:image_path)
end
end
end
diff --git a/actiontext/lib/action_text/attachables/remote_image.rb b/actiontext/lib/action_text/attachables/remote_image.rb
index 650b11862b..c5819ef1f5 100644
--- a/actiontext/lib/action_text/attachables/remote_image.rb
+++ b/actiontext/lib/action_text/attachables/remote_image.rb
@@ -14,7 +14,7 @@ module ActionText
private
def content_type_is_image?(content_type)
- content_type.to_s =~ /^image(\/.+|$)/
+ content_type.to_s.match?(/^image(\/.+|$)/)
end
def attributes_from_node(node)
diff --git a/actiontext/lib/action_text/attachment_gallery.rb b/actiontext/lib/action_text/attachment_gallery.rb
index 45afbff058..48ba9f830c 100644
--- a/actiontext/lib/action_text/attachment_gallery.rb
+++ b/actiontext/lib/action_text/attachment_gallery.rb
@@ -23,7 +23,7 @@ module ActionText
Fragment.wrap(content).find_all(SELECTOR).select do |node|
node.children.all? do |child|
if child.text?
- child.text =~ /\A(\n|\ )*\z/
+ /\A(\n|\ )*\z/.match?(child.text)
else
child.matches? ATTACHMENT_SELECTOR
end
diff --git a/actiontext/test/dummy/config/initializers/backtrace_silencers.rb b/actiontext/test/dummy/config/initializers/backtrace_silencers.rb
index 59385cdf37..3c56b21b3c 100644
--- a/actiontext/test/dummy/config/initializers/backtrace_silencers.rb
+++ b/actiontext/test/dummy/config/initializers/backtrace_silencers.rb
@@ -1,7 +1,7 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
-# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!
diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb
index ad19426fff..cf8f7de931 100644
--- a/actionview/lib/action_view/helpers/form_options_helper.rb
+++ b/actionview/lib/action_view/helpers/form_options_helper.rb
@@ -569,7 +569,7 @@ module ActionView
# be obtained in Active Record as a value object). The +model+ parameter
# must respond to +all+ and return an array of objects that represent time
# zones; each object must respond to +name+. If a Regexp is given it will
- # attempt to match the zones using the <code>=~<code> operator.
+ # attempt to match the zones using <code>match?</code> method.
#
# NOTE: Only the option tags are returned, you have to wrap this call in
# a regular HTML select tag.
@@ -581,7 +581,7 @@ module ActionView
if priority_zones
if priority_zones.is_a?(Regexp)
- priority_zones = zones.select { |z| z =~ priority_zones }
+ priority_zones = zones.select { |z| z.match?(priority_zones) }
end
zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected)
diff --git a/actionview/lib/action_view/helpers/text_helper.rb b/actionview/lib/action_view/helpers/text_helper.rb
index 8203a43239..980a89a7b6 100644
--- a/actionview/lib/action_view/helpers/text_helper.rb
+++ b/actionview/lib/action_view/helpers/text_helper.rb
@@ -228,7 +228,7 @@ module ActionView
# pluralize(2, 'Person', locale: :de)
# # => 2 Personen
def pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale)
- word = if count == 1 || count.to_s =~ /^1(\.0+)?$/
+ word = if count == 1 || count.to_s.match?(/^1(\.0+)?$/)
singular
else
plural || singular.pluralize(locale)
diff --git a/actionview/test/activerecord/relation_cache_test.rb b/actionview/test/activerecord/relation_cache_test.rb
index 6fe83dcb9a..26f3bfbcbc 100644
--- a/actionview/test/activerecord/relation_cache_test.rb
+++ b/actionview/test/activerecord/relation_cache_test.rb
@@ -17,9 +17,24 @@ class RelationCacheTest < ActionView::TestCase
end
def test_cache_relation_other
- cache(Project.all) { concat("Hello World") }
+ assert_queries(1) do
+ cache(Project.all) { concat("Hello World") }
+ end
assert_equal "Hello World", controller.cache_store.read("views/test/hello_world:fa9482a68ce25bf7589b8eddad72f736/projects-#{Project.count}")
end
def view_cache_dependencies; []; end
+
+ def assert_queries(num)
+ ActiveRecord::Base.connection.materialize_transactions
+ count = 0
+
+ ActiveSupport::Notifications.subscribe("sql.active_record") do |_name, _start, _finish, _id, payload|
+ count += 1 unless ["SCHEMA", "TRANSACTION"].include? payload[:name]
+ end
+
+ result = yield
+ assert_equal num, count, "#{count} instead of #{num} queries were executed."
+ result
+ end
end
diff --git a/actionview/test/template/form_options_helper_test.rb b/actionview/test/template/form_options_helper_test.rb
index d7a7b95ab3..273646b077 100644
--- a/actionview/test/template/form_options_helper_test.rb
+++ b/actionview/test/template/form_options_helper_test.rb
@@ -47,6 +47,7 @@ class FormOptionsHelperTest < ActionView::TestCase
FakeZone = Struct.new(:name) do
def to_s; name; end
def =~(_re); end
+ def match?(_re); end
end
module ClassMethods
@@ -1266,6 +1267,7 @@ class FormOptionsHelperTest < ActionView::TestCase
@fake_timezones.each do |tz|
def tz.=~(re); %(A D).include?(name) end
+ def tz.match?(re); %(A D).include?(name) end
end
html = time_zone_select("firm", "time_zone", /A|D/)
diff --git a/actionview/test/template/output_safety_helper_test.rb b/actionview/test/template/output_safety_helper_test.rb
index faeeded1c8..b2c6ae99ed 100644
--- a/actionview/test/template/output_safety_helper_test.rb
+++ b/actionview/test/template/output_safety_helper_test.rb
@@ -43,7 +43,9 @@ class OutputSafetyHelperTest < ActionView::TestCase
joined = safe_join(["a", "b"])
assert_equal "ab", joined
- $, = "|"
+ silence_warnings do
+ $, = "|"
+ end
joined = safe_join(["a", "b"])
assert_equal "a|b", joined
ensure
@@ -108,7 +110,9 @@ class OutputSafetyHelperTest < ActionView::TestCase
test "to_sentence is not affected by $," do
separator_was = $,
- $, = "|"
+ silence_warnings do
+ $, = "|"
+ end
begin
assert_equal "one and two", to_sentence(["one", "two"])
assert_equal "one, two, and three", to_sentence(["one", "two", "three"])
diff --git a/activemodel/lib/active_model/type/helpers/timezone.rb b/activemodel/lib/active_model/type/helpers/timezone.rb
index cf87b9715b..b0477aec32 100644
--- a/activemodel/lib/active_model/type/helpers/timezone.rb
+++ b/activemodel/lib/active_model/type/helpers/timezone.rb
@@ -7,7 +7,7 @@ module ActiveModel
module Helpers # :nodoc: all
module Timezone
def is_utc?
- ::Time.zone_default.nil? || ::Time.zone_default =~ "UTC"
+ ::Time.zone_default.nil? || ::Time.zone_default.match?("UTC")
end
def default_timezone
diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb
index 97612d474d..8906837aa8 100644
--- a/activemodel/lib/active_model/validations/validates.rb
+++ b/activemodel/lib/active_model/validations/validates.rb
@@ -27,7 +27,7 @@ module ActiveModel
# class EmailValidator < ActiveModel::EachValidator
# def validate_each(record, attribute, value)
# record.errors.add attribute, (options[:message] || "is not an email") unless
- # value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
+ # /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i.match?(value)
# end
# end
#
@@ -47,7 +47,7 @@ module ActiveModel
#
# class TitleValidator < ActiveModel::EachValidator
# def validate_each(record, attribute, value)
- # record.errors.add attribute, "must start with 'the'" unless value =~ /\Athe/i
+ # record.errors.add attribute, "must start with 'the'" unless /\Athe/i.match?(value)
# end
# end
#
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 366032c734..56a8796318 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,17 @@
+* Preserve user supplied joins order as much as possible.
+
+ Fixes #36761, #34328, #24281, #12953.
+
+ *Ryuta Kamizono*
+
+* Allow `matches_regex` and `does_not_match_regexp` on the MySQL Arel visitor.
+
+ *James Pearson*
+
+* Allow specifying fixtures to be ignored by setting `ignore` in YAML file's '_fixture' section.
+
+ *Tongfei Gao*
+
* Make the DATABASE_URL env variable only affect the primary connection. Add new env variables for multiple databases.
*John Crepezzi*, *Eileen Uchitelle*
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index 0db0ad8595..404a7c02ba 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -100,7 +100,7 @@ module ActiveRecord
# converting them into an array and iterating through them using
# Array#select.
#
- # person.pets.select { |pet| pet.name =~ /oo/ }
+ # person.pets.select { |pet| /oo/.match?(pet.name) }
# # => [
# # #<Pet id: 2, name: "Spook", person_id: 1>,
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
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 800235a302..0fe16270ed 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -573,6 +573,7 @@ module ActiveRecord
end
# See https://dev.mysql.com/doc/refman/5.7/en/server-error-reference.html
+ ER_DB_CREATE_EXISTS = 1007
ER_DUP_ENTRY = 1062
ER_NOT_NULL_VIOLATION = 1048
ER_NO_REFERENCED_ROW = 1216
@@ -592,6 +593,8 @@ module ActiveRecord
def translate_exception(exception, message:, sql:, binds:)
case error_number(exception)
+ when ER_DB_CREATE_EXISTS
+ DatabaseAlreadyExists.new(message, sql: sql, binds: binds)
when ER_DUP_ENTRY
RecordNotUnique.new(message, sql: sql, binds: binds)
when ER_NO_REFERENCED_ROW, ER_ROW_IS_REFERENCED, ER_ROW_IS_REFERENCED_2, ER_NO_REFERENCED_ROW_2
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 0a7c6d8ac4..f33ba87435 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -467,6 +467,7 @@ module ActiveRecord
UNIQUE_VIOLATION = "23505"
SERIALIZATION_FAILURE = "40001"
DEADLOCK_DETECTED = "40P01"
+ DUPLICATE_DATABASE = "42P04"
LOCK_NOT_AVAILABLE = "55P03"
QUERY_CANCELED = "57014"
@@ -488,6 +489,8 @@ module ActiveRecord
SerializationFailure.new(message, sql: sql, binds: binds)
when DEADLOCK_DETECTED
Deadlocked.new(message, sql: sql, binds: binds)
+ when DUPLICATE_DATABASE
+ DatabaseAlreadyExists.new(message, sql: sql, binds: binds)
when LOCK_NOT_AVAILABLE
LockWaitTimeout.new(message, sql: sql, binds: binds)
when QUERY_CANCELED
diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb
index bf7d99449d..509f21c9a5 100644
--- a/activerecord/lib/active_record/errors.rb
+++ b/activerecord/lib/active_record/errors.rb
@@ -187,6 +187,10 @@ module ActiveRecord
class NoDatabaseError < StatementInvalid
end
+ # Raised when creating a database if it exists.
+ class DatabaseAlreadyExists < StatementInvalid
+ end
+
# Raised when PostgreSQL returns 'cached plan must not change result type' and
# we cannot retry gracefully (e.g. inside a transaction)
class PreparedStatementCacheExpired < StatementInvalid
diff --git a/activerecord/lib/active_record/fixture_set/file.rb b/activerecord/lib/active_record/fixture_set/file.rb
index f1ea0e022f..b2030a5bb9 100644
--- a/activerecord/lib/active_record/fixture_set/file.rb
+++ b/activerecord/lib/active_record/fixture_set/file.rb
@@ -29,6 +29,10 @@ module ActiveRecord
config_row["model_class"]
end
+ def ignored_fixtures
+ config_row["ignore"]
+ end
+
private
def rows
@rows ||= raw_rows.reject { |fixture_name, _| fixture_name == "_fixture" }
@@ -40,7 +44,7 @@ module ActiveRecord
if row
row.last
else
- { 'model_class': nil }
+ { 'model_class': nil, 'ignore': nil }
end
end
end
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 046ed0e95c..3df4b3c87f 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -420,6 +420,29 @@ module ActiveRecord
#
# Any fixture labeled "DEFAULTS" is safely ignored.
#
+ # Besides using "DEFAULTS", you can also specify what fixtures will
+ # be ignored by setting "ignore" in "_fixture" section.
+ #
+ # # users.yml
+ # _fixture:
+ # ignore:
+ # - base
+ # # or use "ignore: base" when there is only one fixture needs to be ignored.
+ #
+ # base: &base
+ # admin: false
+ # introduction: "This is a default description"
+ #
+ # admin:
+ # <<: *base
+ # admin: true
+ #
+ # visitor:
+ # <<: *base
+ #
+ # In the above example, 'base' will be ignored when creating fixtures.
+ # This can be used for common attributes inheriting.
+ #
# == Configure the fixture model class
#
# It's possible to set the fixture's model class directly in the YAML file.
@@ -614,7 +637,7 @@ module ActiveRecord
end
end
- attr_reader :table_name, :name, :fixtures, :model_class, :config
+ attr_reader :table_name, :name, :fixtures, :model_class, :ignored_fixtures, :config
def initialize(_, name, class_name, path, config = ActiveRecord::Base)
@name = name
@@ -647,8 +670,8 @@ module ActiveRecord
# Returns a hash of rows to be inserted. The key is the table, the value is
# a list of rows to insert to that table.
def table_rows
- # allow a standard key to be used for doing defaults in YAML
- fixtures.delete("DEFAULTS")
+ # allow specifying fixtures to be ignored by setting `ignore` in `_fixture` section
+ fixtures.except!(*ignored_fixtures)
TableRows.new(
table_name,
@@ -667,6 +690,21 @@ module ActiveRecord
end
end
+ def ignored_fixtures=(base)
+ @ignored_fixtures =
+ case base
+ when Array
+ base
+ when String
+ [base]
+ else
+ []
+ end
+
+ @ignored_fixtures << "DEFAULTS" unless @ignored_fixtures.include?("DEFAULTS")
+ @ignored_fixtures.compact
+ end
+
# Loads the fixtures from the YAML file at +path+.
# If the file sets the +model_class+ and current instance value is not set,
# it uses the file value.
@@ -678,6 +716,7 @@ module ActiveRecord
yaml_files.each_with_object({}) do |file, fixtures|
FixtureSet::File.open(file) do |fh|
self.model_class ||= fh.model_class if fh.model_class
+ self.ignored_fixtures ||= fh.ignored_fixtures
fh.each do |fixture_name, row|
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
end
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 6957ba052b..29e2e2cedc 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -1095,26 +1095,44 @@ module ActiveRecord
end
def build_left_outer_joins(manager, outer_joins, aliases)
- buckets = { association_join: valid_association_list(outer_joins) }
+ buckets = Hash.new { |h, k| h[k] = [] }
+ buckets[:association_join] = valid_association_list(outer_joins)
build_join_query(manager, buckets, Arel::Nodes::OuterJoin, aliases)
end
def build_joins(manager, joins, aliases)
+ buckets = Hash.new { |h, k| h[k] = [] }
+
unless left_outer_joins_values.empty?
left_joins = valid_association_list(left_outer_joins_values.flatten)
- joins.unshift construct_join_dependency(left_joins, Arel::Nodes::OuterJoin)
+ buckets[:stashed_join] << construct_join_dependency(left_joins, Arel::Nodes::OuterJoin)
end
- buckets = joins.group_by do |join|
+ joins.map! do |join|
+ if join.is_a?(String)
+ table.create_string_join(Arel.sql(join.strip)) unless join.blank?
+ else
+ join
+ end
+ end.compact_blank!
+
+ while joins.first.is_a?(Arel::Nodes::Join)
+ join_node = joins.shift
+ if join_node.is_a?(Arel::Nodes::StringJoin) && !buckets[:stashed_join].empty?
+ buckets[:join_node] << join_node
+ else
+ buckets[:leading_join] << join_node
+ end
+ end
+
+ joins.each do |join|
case join
- when String
- :string_join
when Hash, Symbol, Array
- :association_join
+ buckets[:association_join] << join
when ActiveRecord::Associations::JoinDependency
- :stashed_join
+ buckets[:stashed_join] << join
when Arel::Nodes::Join
- :join_node
+ buckets[:join_node] << join
else
raise "unknown class: %s" % join.class.name
end
@@ -1124,25 +1142,21 @@ module ActiveRecord
end
def build_join_query(manager, buckets, join_type, aliases)
- buckets.default = []
-
association_joins = buckets[:association_join]
stashed_joins = buckets[:stashed_join]
+ leading_joins = buckets[:leading_join].tap(&:uniq!)
join_nodes = buckets[:join_node].tap(&:uniq!)
- string_joins = buckets[:string_join].compact_blank!.map!(&:strip).tap(&:uniq!)
-
- string_joins.map! { |join| table.create_string_join(Arel.sql(join)) }
join_sources = manager.join_sources
- join_sources.concat(join_nodes) unless join_nodes.empty?
+ join_sources.concat(leading_joins) unless leading_joins.empty?
unless association_joins.empty? && stashed_joins.empty?
- alias_tracker = alias_tracker(join_nodes + string_joins, aliases)
+ alias_tracker = alias_tracker(leading_joins + join_nodes, aliases)
join_dependency = construct_join_dependency(association_joins, join_type)
join_sources.concat(join_dependency.join_constraints(stashed_joins, alias_tracker))
end
- join_sources.concat(string_joins) unless string_joins.empty?
+ join_sources.concat(join_nodes) unless join_nodes.empty?
end
def build_select(arel)
diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb
index 5d1ce19829..300e67b0aa 100644
--- a/activerecord/lib/active_record/tasks/database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/database_tasks.rb
@@ -4,7 +4,6 @@ require "active_record/database_configurations"
module ActiveRecord
module Tasks # :nodoc:
- class DatabaseAlreadyExists < StandardError; end # :nodoc:
class DatabaseNotSupported < StandardError; end # :nodoc:
# ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
index e3efeb75b5..b9a8ccb22c 100644
--- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
@@ -15,12 +15,6 @@ module ActiveRecord
establish_connection configuration_without_database
connection.create_database configuration["database"], creation_options
establish_connection configuration
- rescue ActiveRecord::StatementInvalid => error
- if connection.error_number(error.cause) == ER_DB_CREATE_EXISTS
- raise DatabaseAlreadyExists
- else
- raise
- end
end
def drop
diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb
index 626ffdfdf9..fc37db216d 100644
--- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb
@@ -21,12 +21,6 @@ module ActiveRecord
connection.create_database configuration["database"],
configuration.merge("encoding" => encoding)
establish_connection configuration
- rescue ActiveRecord::StatementInvalid => error
- if error.cause.is_a?(PG::DuplicateDatabase)
- raise DatabaseAlreadyExists
- else
- raise
- end
end
def drop
diff --git a/activerecord/lib/arel/visitors/mysql.rb b/activerecord/lib/arel/visitors/mysql.rb
index dd77cfdf66..6cb866715f 100644
--- a/activerecord/lib/arel/visitors/mysql.rb
+++ b/activerecord/lib/arel/visitors/mysql.rb
@@ -48,6 +48,14 @@ module Arel # :nodoc: all
visit_Arel_Nodes_IsNotDistinctFrom o, collector
end
+ def visit_Arel_Nodes_Regexp(o, collector)
+ infix_value o, collector, " REGEXP "
+ end
+
+ def visit_Arel_Nodes_NotRegexp(o, collector)
+ infix_value o, collector, " NOT REGEXP "
+ end
+
# In the simple case, MySQL allows us to place JOINs directly into the UPDATE
# query. However, this does not allow for LIMIT, OFFSET and ORDER. To support
# these, we must use a subquery.
diff --git a/activerecord/test/cases/arel/nodes/node_test.rb b/activerecord/test/cases/arel/nodes/node_test.rb
index f1e0ce1ea9..8a9ecd84ca 100644
--- a/activerecord/test/cases/arel/nodes/node_test.rb
+++ b/activerecord/test/cases/arel/nodes/node_test.rb
@@ -14,7 +14,7 @@ module Arel
}.grep(Class).each do |klass|
next if Nodes::SqlLiteral == klass
next if Nodes::BindParam == klass
- next if klass.name =~ /^Arel::Nodes::(?:Test|.*Test$)/
+ next if /^Arel::Nodes::(?:Test|.*Test$)/.match?(klass.name)
assert klass.ancestors.include?(Nodes::Node), klass.name
end
end
diff --git a/activerecord/test/cases/arel/visitors/mysql_test.rb b/activerecord/test/cases/arel/visitors/mysql_test.rb
index 5f37587957..05dccd126e 100644
--- a/activerecord/test/cases/arel/visitors/mysql_test.rb
+++ b/activerecord/test/cases/arel/visitors/mysql_test.rb
@@ -104,6 +104,52 @@ module Arel
sql.must_be_like %{ NOT "users"."name" <=> NULL }
end
end
+
+ describe "Nodes::Regexp" do
+ before do
+ @table = Table.new(:users)
+ @attr = @table[:id]
+ end
+
+ it "should know how to visit" do
+ node = @table[:name].matches_regexp("foo.*")
+ node.must_be_kind_of Nodes::Regexp
+ compile(node).must_be_like %{
+ "users"."name" REGEXP 'foo.*'
+ }
+ end
+
+ it "can handle subqueries" do
+ subquery = @table.project(:id).where(@table[:name].matches_regexp("foo.*"))
+ node = @attr.in subquery
+ compile(node).must_be_like %{
+ "users"."id" IN (SELECT id FROM "users" WHERE "users"."name" REGEXP 'foo.*')
+ }
+ end
+ end
+
+ describe "Nodes::NotRegexp" do
+ before do
+ @table = Table.new(:users)
+ @attr = @table[:id]
+ end
+
+ it "should know how to visit" do
+ node = @table[:name].does_not_match_regexp("foo.*")
+ node.must_be_kind_of Nodes::NotRegexp
+ compile(node).must_be_like %{
+ "users"."name" NOT REGEXP 'foo.*'
+ }
+ end
+
+ it "can handle subqueries" do
+ subquery = @table.project(:id).where(@table[:name].does_not_match_regexp("foo.*"))
+ node = @attr.in subquery
+ compile(node).must_be_like %{
+ "users"."id" IN (SELECT id FROM "users" WHERE "users"."name" NOT REGEXP 'foo.*')
+ }
+ end
+ end
end
end
end
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index 21286be320..6bd305306f 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -60,10 +60,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
end
def test_belongs_to_does_not_use_order_by
- ActiveRecord::SQLCounter.clear_log
- Client.find(3).firm
- ensure
- sql_log = ActiveRecord::SQLCounter.log
+ sql_log = capture_sql { Client.find(3).firm }
assert sql_log.all? { |sql| !/order by/i.match?(sql) }, "ORDER BY was used in the query: #{sql_log}"
end
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index 9227f10c0e..46498a6dfb 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -37,10 +37,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
end
def test_has_one_does_not_use_order_by
- ActiveRecord::SQLCounter.clear_log
- companies(:first_firm).account
- ensure
- sql_log = ActiveRecord::SQLCounter.log
+ sql_log = capture_sql { companies(:first_firm).account }
assert sql_log.all? { |sql| !/order by/i.match?(sql) }, "ORDER BY was used in the query: #{sql_log}"
end
diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb
index e0dac01f4a..b65af4b819 100644
--- a/activerecord/test/cases/associations/inner_join_association_test.rb
+++ b/activerecord/test/cases/associations/inner_join_association_test.rb
@@ -13,7 +13,7 @@ require "models/tag"
class InnerJoinAssociationTest < ActiveRecord::TestCase
fixtures :authors, :author_addresses, :essays, :posts, :comments, :categories, :categories_posts, :categorizations,
- :taggings, :tags
+ :taggings, :tags, :people
def test_construct_finder_sql_applies_aliases_tables_on_association_conditions
result = Author.joins(:thinking_posts, :welcome_posts).to_a
@@ -36,16 +36,37 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase
end
def test_construct_finder_sql_does_not_table_name_collide_with_string_joins
- sql = Person.joins(:agents).joins("JOIN people agents_people ON agents_people.primary_contact_id = people.id").to_sql
- assert_match(/agents_people_2/i, sql)
+ string_join = <<~SQL
+ JOIN people agents_people ON agents_people.primary_contact_id = agents_people_2.id AND agents_people.id > agents_people_2.id
+ SQL
+
+ expected = people(:susan)
+ assert_sql(/agents_people_2/i) do
+ assert_equal [expected], Person.joins(:agents).joins(string_join)
+ end
end
def test_construct_finder_sql_does_not_table_name_collide_with_aliased_joins
- people = Person.arel_table
- agents = people.alias("agents_people")
- constraint = agents[:primary_contact_id].eq(people[:id])
- sql = Person.joins(:agents).joins(agents.create_join(agents, agents.create_on(constraint))).to_sql
- assert_match(/agents_people_2/i, sql)
+ agents = Person.arel_table.alias("agents_people")
+ agents_2 = Person.arel_table.alias("agents_people_2")
+ constraint = agents[:primary_contact_id].eq(agents_2[:id]).and(agents[:id].gt(agents_2[:id]))
+
+ expected = people(:susan)
+ assert_sql(/agents_people_2/i) do
+ assert_equal [expected], Person.joins(:agents).joins(agents.create_join(agents, agents.create_on(constraint)))
+ end
+ end
+
+ def test_user_supplied_joins_order_should_be_preserved
+ string_join = <<~SQL
+ JOIN people agents_people_2 ON agents_people_2.primary_contact_id = people.id
+ SQL
+ agents = Person.arel_table.alias("agents_people")
+ agents_2 = Person.arel_table.alias("agents_people_2")
+ constraint = agents[:primary_contact_id].eq(agents_2[:id]).and(agents[:id].gt(agents_2[:id]))
+
+ expected = people(:susan)
+ assert_equal [expected], Person.joins(string_join).joins(agents.create_join(agents, agents.create_on(constraint)))
end
def test_construct_finder_sql_ignores_empty_joins_hash
diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb
index 8673a99c45..0ae156320a 100644
--- a/activerecord/test/cases/enum_test.rb
+++ b/activerecord/test/cases/enum_test.rb
@@ -580,7 +580,9 @@ class EnumTest < ActiveRecord::TestCase
def self.name
"Book"
end
- enum status: [:sent, :not_sent]
+ silence_warnings do
+ enum status: [:sent, :not_sent]
+ end
end
assert_match(expected_message, logger.logged(:warn).first)
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index a7f01e898e..0861d938c5 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -67,7 +67,7 @@ class FixturesTest < ActiveRecord::TestCase
end
def call(_, _, _, _, values)
- @events << values[:sql] if values[:sql] =~ /INSERT/
+ @events << values[:sql] if /INSERT/.match?(values[:sql])
end
end
@@ -1279,6 +1279,33 @@ class CustomNameForFixtureOrModelTest < ActiveRecord::TestCase
end
end
+class IgnoreFixturesTest < ActiveRecord::TestCase
+ fixtures :other_books, :parrots
+
+ test "ignores books fixtures" do
+ assert_raise(StandardError) { other_books(:published) }
+ assert_raise(StandardError) { other_books(:published_paperback) }
+ assert_raise(StandardError) { other_books(:published_ebook) }
+
+ assert_equal 2, Book.count
+ assert_equal "Agile Web Development with Rails", other_books(:awdr).name
+ assert_equal "published", other_books(:awdr).status
+ assert_equal "paperback", other_books(:awdr).format
+ assert_equal "english", other_books(:awdr).language
+
+ assert_equal "Ruby for Rails", other_books(:rfr).name
+ assert_equal "ebook", other_books(:rfr).format
+ assert_equal "published", other_books(:rfr).status
+ end
+
+ test "ignores parrots fixtures" do
+ assert_raise(StandardError) { parrots(:DEFAULT) }
+ assert_raise(StandardError) { parrots(:DEAD_PARROT) }
+
+ assert_equal "DeadParrot", parrots(:polly).parrot_sti_class
+ end
+end
+
class FixturesWithDefaultScopeTest < ActiveRecord::TestCase
fixtures :bulbs
diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb
index ac3c5bc26e..4b039395e8 100644
--- a/activerecord/test/cases/tasks/mysql_rake_test.rb
+++ b/activerecord/test/cases/tasks/mysql_rake_test.rb
@@ -93,11 +93,9 @@ if current_adapter?(:Mysql2Adapter)
with_stubbed_connection_establish_connection do
ActiveRecord::Base.connection.stub(
:create_database,
- proc { raise ActiveRecord::StatementInvalid }
+ proc { raise ActiveRecord::DatabaseAlreadyExists }
) do
- ActiveRecord::Base.connection.stub(:error_number, 1007) do
- ActiveRecord::Tasks::DatabaseTasks.create @configuration
- end
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
assert_equal "Database 'my-app-db' already exists\n", $stderr.string
end
diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb
index f9df650687..d74ba0580d 100644
--- a/activerecord/test/cases/tasks/postgresql_rake_test.rb
+++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb
@@ -129,7 +129,7 @@ if current_adapter?(:PostgreSQLAdapter)
with_stubbed_connection_establish_connection do
ActiveRecord::Base.connection.stub(
:create_database,
- proc { raise ActiveRecord::Tasks::DatabaseAlreadyExists }
+ proc { raise ActiveRecord::DatabaseAlreadyExists }
) do
ActiveRecord::Tasks::DatabaseTasks.create @configuration
diff --git a/activerecord/test/fixtures/other_books.yml b/activerecord/test/fixtures/other_books.yml
new file mode 100644
index 0000000000..62806c03d7
--- /dev/null
+++ b/activerecord/test/fixtures/other_books.yml
@@ -0,0 +1,26 @@
+_fixture:
+ model_class: Book
+ ignore:
+ - PUBLISHED
+ - PUBLISHED_PAPERBACK
+ - PUBLISHED_EBOOK
+
+PUBLISHED: &PUBLISHED
+ status: :published
+
+PUBLISHED_PAPERBACK: &PUBLISHED_PAPERBACK
+ <<: *PUBLISHED
+ format: "paperback"
+ language: :english
+
+PUBLISHED_EBOOK: &PUBLISHED_EBOOK
+ <<: *PUBLISHED
+ format: "ebook"
+
+awdr:
+ <<: *PUBLISHED_PAPERBACK
+ name: "Agile Web Development with Rails"
+
+rfr:
+ <<: *PUBLISHED_EBOOK
+ name: "Ruby for Rails"
diff --git a/activerecord/test/fixtures/parrots.yml b/activerecord/test/fixtures/parrots.yml
index 8425ef98e0..4f0a090e03 100644
--- a/activerecord/test/fixtures/parrots.yml
+++ b/activerecord/test/fixtures/parrots.yml
@@ -1,3 +1,9 @@
+_fixture:
+ ignore: DEAD_PARROT
+
+DEAD_PARROT: &DEAD_PARROT
+ parrot_sti_class: DeadParrot
+
george:
name: "Curious George"
treasures: diamond, sapphire
@@ -17,7 +23,7 @@ polly:
name: $LABEL
killer: blackbeard
treasures: sapphire, ruby
- parrot_sti_class: DeadParrot
+ <<: *DEAD_PARROT
DEFAULTS: &DEFAULTS
treasures: sapphire, ruby
diff --git a/activestorage/test/dummy/config/initializers/backtrace_silencers.rb b/activestorage/test/dummy/config/initializers/backtrace_silencers.rb
index d0f0d3b5df..8452ef9236 100644
--- a/activestorage/test/dummy/config/initializers/backtrace_silencers.rb
+++ b/activestorage/test/dummy/config/initializers/backtrace_silencers.rb
@@ -2,7 +2,7 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
-# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!
diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb
index f55e821e10..6273012808 100644
--- a/activesupport/lib/active_support/backtrace_cleaner.rb
+++ b/activesupport/lib/active_support/backtrace_cleaner.rb
@@ -16,7 +16,7 @@ module ActiveSupport
#
# bc = ActiveSupport::BacktraceCleaner.new
# bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
- # bc.add_silencer { |line| line =~ /puma|rubygems/ } # skip any lines from puma or rubygems
+ # bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
# bc.clean(exception.backtrace) # perform the cleanup
#
# To reconfigure an existing BacktraceCleaner (like the default one in Rails)
@@ -65,7 +65,7 @@ module ActiveSupport
# for a given line, it will be excluded from the clean backtrace.
#
# # Will reject all lines that include the word "puma", like "/gems/puma/server.rb" or "/app/my_puma_server/rb"
- # backtrace_cleaner.add_silencer { |line| line =~ /puma/ }
+ # backtrace_cleaner.add_silencer { |line| /puma/.match?(line) }
def add_silencer(&block)
@silencers << block
end
diff --git a/activesupport/lib/active_support/core_ext/string/access.rb b/activesupport/lib/active_support/core_ext/string/access.rb
index 4f70e7f5fc..f6a14c08bc 100644
--- a/activesupport/lib/active_support/core_ext/string/access.rb
+++ b/activesupport/lib/active_support/core_ext/string/access.rb
@@ -62,7 +62,7 @@ class String
# str.from(1).to(-2) # => "ell"
def to(position)
position += size if position < 0
- self[0, position + 1].to_s
+ self[0, position + 1] || +""
end
# Returns the first character. If a limit is supplied, returns a substring
@@ -76,17 +76,7 @@ class String
# str.first(0) # => ""
# str.first(6) # => "hello"
def first(limit = 1)
- ActiveSupport::Deprecation.warn(
- "Calling String#first with a negative integer limit " \
- "will raise an ArgumentError in Rails 6.1."
- ) if limit < 0
- if limit == 0
- ""
- elsif limit >= size
- dup
- else
- to(limit - 1)
- end
+ self[0, limit] || raise(ArgumentError, "negative limit")
end
# Returns the last character of the string. If a limit is supplied, returns a substring
@@ -100,16 +90,6 @@ class String
# str.last(0) # => ""
# str.last(6) # => "hello"
def last(limit = 1)
- ActiveSupport::Deprecation.warn(
- "Calling String#last with a negative integer limit " \
- "will raise an ArgumentError in Rails 6.1."
- ) if limit < 0
- if limit == 0
- ""
- elsif limit >= size
- dup
- else
- from(-limit)
- end
+ self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
end
end
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 923d6ad228..6d71a67a46 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -793,7 +793,6 @@ module ActiveSupport #:nodoc:
end
private
-
# Returns the original name of a class or module even if `name` has been
# overridden.
def real_mod_name(mod)
diff --git a/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb b/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb
index f75083a05a..2cf55713bd 100644
--- a/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb
+++ b/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb
@@ -42,6 +42,17 @@ module ActiveSupport
end
end
+ module RequireDependency
+ def require_dependency(filename)
+ filename = filename.to_path if filename.respond_to?(:to_path)
+ if abspath = ActiveSupport::Dependencies.search_for_file(filename)
+ require abspath
+ else
+ require filename
+ end
+ end
+ end
+
module Inflector
def self.camelize(basename, _abspath)
basename.camelize
@@ -90,7 +101,7 @@ module ActiveSupport
def decorate_dependencies
Dependencies.unhook!
Dependencies.singleton_class.prepend(Decorations)
- Object.class_eval { alias_method :require_dependency, :require }
+ Object.prepend(RequireDependency)
end
end
end
diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb
index 0751f8a3ad..3ba2d93ed8 100644
--- a/activesupport/lib/active_support/inflector/transliterate.rb
+++ b/activesupport/lib/active_support/inflector/transliterate.rb
@@ -116,7 +116,7 @@ module ActiveSupport
# If the optional parameter +locale+ is specified,
# the word will be parameterized as a word of that language.
# By default, this parameter is set to <tt>nil</tt> and it will use
- # the configured <tt>I18n.locale<tt>.
+ # the configured <tt>I18n.locale</tt>.
def parameterize(string, separator: "-", preserve_case: false, locale: nil)
# Replace accented chars with their ASCII equivalents.
parameterized_string = transliterate(string, locale: locale)
diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb
index 2ba3936cae..868cb70423 100644
--- a/activesupport/lib/active_support/multibyte/chars.rb
+++ b/activesupport/lib/active_support/multibyte/chars.rb
@@ -48,7 +48,7 @@ module ActiveSupport #:nodoc:
alias to_s wrapped_string
alias to_str wrapped_string
- delegate :<=>, :=~, :acts_like_string?, to: :wrapped_string
+ delegate :<=>, :=~, :match?, :acts_like_string?, to: :wrapped_string
# Creates a new Chars instance by wrapping _string_.
def initialize(string)
diff --git a/activesupport/lib/active_support/parameter_filter.rb b/activesupport/lib/active_support/parameter_filter.rb
index e1cd7c46c1..f4c4f2d2fb 100644
--- a/activesupport/lib/active_support/parameter_filter.rb
+++ b/activesupport/lib/active_support/parameter_filter.rb
@@ -22,7 +22,7 @@ module ActiveSupport
# change { file: { code: "xxxx"} }
#
# ActiveSupport::ParameterFilter.new([-> (k, v) do
- # v.reverse! if k =~ /secret/i
+ # v.reverse! if /secret/i.match?(k)
# end])
# => reverses the value to all keys matching /secret/i
class ParameterFilter
diff --git a/activesupport/lib/active_support/secure_compare_rotator.rb b/activesupport/lib/active_support/secure_compare_rotator.rb
index 97110d41f7..269703c34a 100644
--- a/activesupport/lib/active_support/secure_compare_rotator.rb
+++ b/activesupport/lib/active_support/secure_compare_rotator.rb
@@ -44,7 +44,6 @@ module ActiveSupport
end
private
-
def build_rotation(previous_value, _options)
self.class.new(previous_value)
end
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index d9e033e23b..90830b89bd 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -334,6 +334,13 @@ module ActiveSupport
re === name || re === MAPPING[name]
end
+ # Compare #name and TZInfo identifier to a supplied regexp, returning +true+
+ # if a match is found.
+ def match?(re)
+ (re == name) || (re == MAPPING[name]) ||
+ ((Regexp === re) && (re.match?(name) || re.match?(MAPPING[name])))
+ end
+
# Returns a textual representation of this time zone.
def to_s
"(GMT#{formatted_offset}) #{name}"
diff --git a/activesupport/test/cache/stores/mem_cache_store_test.rb b/activesupport/test/cache/stores/mem_cache_store_test.rb
index 3917d14d1c..0a5e20ed46 100644
--- a/activesupport/test/cache/stores/mem_cache_store_test.rb
+++ b/activesupport/test/cache/stores/mem_cache_store_test.rb
@@ -9,7 +9,7 @@ require "dalli"
# connection pool testing.
class SlowDalliClient < Dalli::Client
def get(key, options = {})
- if key =~ /latency/
+ if /latency/.match?(key)
sleep 3
else
super
diff --git a/activesupport/test/cache/stores/redis_cache_store_test.rb b/activesupport/test/cache/stores/redis_cache_store_test.rb
index a2177e0476..0ea37b15d5 100644
--- a/activesupport/test/cache/stores/redis_cache_store_test.rb
+++ b/activesupport/test/cache/stores/redis_cache_store_test.rb
@@ -15,7 +15,7 @@ Redis::Connection.drivers.append(driver)
# connection pool testing.
class SlowRedis < Redis
def get(key, options = {})
- if key =~ /latency/
+ if /latency/.match?(key)
sleep 3
else
super
diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb
index cc37c4fa99..221a8a5731 100644
--- a/activesupport/test/callbacks_test.rb
+++ b/activesupport/test/callbacks_test.rb
@@ -256,7 +256,7 @@ module CallbacksTest
end
def respond_to_missing?(sym)
- sym =~ /^(log|wrap)_/ || super
+ sym.match?(/^(log|wrap)_/) || super
end
end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index b1ab9533e7..af8f9c9b09 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -482,12 +482,16 @@ class StringAccessTest < ActiveSupport::TestCase
assert_not_same different_string, string
end
- test "#first with negative Integer is deprecated" do
- string = "hello"
- message = "Calling String#first with a negative integer limit " \
- "will raise an ArgumentError in Rails 6.1."
- assert_deprecated(message) do
- string.first(-1)
+ test "#first with Integer returns a non-frozen string" do
+ string = "he"
+ (0..string.length + 1).each do |limit|
+ assert_not string.first(limit).frozen?
+ end
+ end
+
+ test "#first with negative Integer raises ArgumentError" do
+ assert_raise ArgumentError do
+ "hello".first(-1)
end
end
@@ -509,12 +513,16 @@ class StringAccessTest < ActiveSupport::TestCase
assert_not_same different_string, string
end
- test "#last with negative Integer is deprecated" do
- string = "hello"
- message = "Calling String#last with a negative integer limit " \
- "will raise an ArgumentError in Rails 6.1."
- assert_deprecated(message) do
- string.last(-1)
+ test "#last with Integer returns a non-frozen string" do
+ string = "he"
+ (0..string.length + 1).each do |limit|
+ assert_not string.last(limit).frozen?
+ end
+ end
+
+ test "#last with negative Integer raises ArgumentError" do
+ assert_raise ArgumentError do
+ "hello".last(-1)
end
end
diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb
index e0e0d9afc0..b0027047df 100644
--- a/activesupport/test/multibyte_chars_test.rb
+++ b/activesupport/test/multibyte_chars_test.rb
@@ -204,6 +204,12 @@ class MultibyteCharsUTF8BehaviourTest < ActiveSupport::TestCase
assert_equal 3, (@chars =~ /わ/u)
end
+ def test_match_should_return_boolean_for_regexp_match
+ assert_not @chars.match?(/wrong/u)
+ assert @chars.match?(/こに/u)
+ assert @chars.match?(/ち/u)
+ end
+
def test_should_use_character_offsets_for_insert_offsets
assert_equal "", (+"").mb_chars.insert(0, "")
assert_equal "こわにちわ", @chars.insert(1, "わ")
diff --git a/activesupport/test/parameter_filter_test.rb b/activesupport/test/parameter_filter_test.rb
index e680a22479..510921cf95 100644
--- a/activesupport/test/parameter_filter_test.rb
+++ b/activesupport/test/parameter_filter_test.rb
@@ -22,7 +22,7 @@ class ParameterFilterTest < ActiveSupport::TestCase
filter_words << "blah"
filter_words << lambda { |key, value|
- value.reverse! if key =~ /bargain/
+ value.reverse! if /bargain/.match?(key)
}
filter_words << lambda { |key, value, original_params|
value.replace("world!") if original_params["barg"]["blah"] == "bar" && key == "hello"
@@ -61,7 +61,7 @@ class ParameterFilterTest < ActiveSupport::TestCase
filter_words << "blah"
filter_words << lambda { |key, value|
- value.reverse! if key =~ /bargain/
+ value.reverse! if /bargain/.match?(key)
}
filter_words << lambda { |key, value, original_params|
value.replace("world!") if original_params["barg"]["blah"] == "bar" && key == "hello"
diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb
index 0c3a10995c..6ca3afd561 100644
--- a/activesupport/test/time_zone_test.rb
+++ b/activesupport/test/time_zone_test.rb
@@ -712,9 +712,16 @@ class TimeZoneTest < ActiveSupport::TestCase
def test_zone_match
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
- assert_match zone, /Eastern/
- assert_match zone, /New_York/
- assert_no_match zone, /Nonexistent_Place/
+ assert zone =~ /Eastern/
+ assert zone =~ /New_York/
+ assert zone !~ /Nonexistent_Place/
+ end
+
+ def test_zone_match?
+ zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
+ assert zone.match?(/Eastern/)
+ assert zone.match?(/New_York/)
+ assert_not zone.match?(/Nonexistent_Place/)
end
def test_to_s
diff --git a/guides/rails_guides/kindle.rb b/guides/rails_guides/kindle.rb
index 8a0361ff4c..fc8e6b97e6 100644
--- a/guides/rails_guides/kindle.rb
+++ b/guides/rails_guides/kindle.rb
@@ -36,7 +36,7 @@ module Kindle
frontmatter = []
html_pages.delete_if { |x|
if /(toc|welcome|copyright).html/.match?(x)
- frontmatter << x unless x =~ /toc/
+ frontmatter << x unless /toc/.match?(x)
true
end
}
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index f600cf29ce..9f4a567f96 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -743,7 +743,7 @@ files (environment.rb, production.rb, etc...)
| Configuration | Description |
|---------------|-------------|
|`logger`|Generates information on the mailing run if available. Can be set to `nil` for no logging. Compatible with both Ruby's own `Logger` and `Log4r` loggers.|
-|`smtp_settings`|Allows detailed configuration for `:smtp` delivery method:<ul><li>`:address` - Allows you to use a remote mail server. Just change it from its default `"localhost"` setting.</li><li>`:port` - On the off chance that your mail server doesn't run on port 25, you can change it.</li><li>`:domain` - If you need to specify a HELO domain, you can do it here.</li><li>`:user_name` - If your mail server requires authentication, set the username in this setting.</li><li>`:password` - If your mail server requires authentication, set the password in this setting.</li><li>`:authentication` - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of `:plain` (will send the password in the clear), `:login` (will send password Base64 encoded) or `:cram_md5` (combines a Challenge/Response mechanism to exchange information and a cryptographic Message Digest 5 algorithm to hash important information)</li><li>`:enable_starttls_auto` - Detects if STARTTLS is enabled in your SMTP server and starts to use it. Defaults to `true`.</li><li>`:openssl_verify_mode` - When using TLS, you can set how OpenSSL checks the certificate. This is really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name of an OpenSSL verify constant ('none' or 'peer') or directly the constant (`OpenSSL::SSL::VERIFY_NONE` or `OpenSSL::SSL::VERIFY_PEER`).</li></ul>|
+|`smtp_settings`|Allows detailed configuration for `:smtp` delivery method:<ul><li>`:address` - Allows you to use a remote mail server. Just change it from its default `"localhost"` setting.</li><li>`:port` - On the off chance that your mail server doesn't run on port 25, you can change it.</li><li>`:domain` - If you need to specify a HELO domain, you can do it here.</li><li>`:user_name` - If your mail server requires authentication, set the username in this setting.</li><li>`:password` - If your mail server requires authentication, set the password in this setting.</li><li>`:authentication` - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of `:plain` (will send the password in the clear), `:login` (will send password Base64 encoded) or `:cram_md5` (combines a Challenge/Response mechanism to exchange information and a cryptographic Message Digest 5 algorithm to hash important information)</li><li>`:enable_starttls_auto` - Detects if STARTTLS is enabled in your SMTP server and starts to use it. Defaults to `true`.</li><li>`:openssl_verify_mode` - When using TLS, you can set how OpenSSL checks the certificate. This is really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name of an OpenSSL verify constant ('none' or 'peer') or directly the constant (`OpenSSL::SSL::VERIFY_NONE` or `OpenSSL::SSL::VERIFY_PEER`).</li><li>`:ssl/:tls` - Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection)</li></ul>|
|`sendmail_settings`|Allows you to override options for the `:sendmail` delivery method.<ul><li>`:location` - The location of the sendmail executable. Defaults to `/usr/sbin/sendmail`.</li><li>`:arguments` - The command line arguments to be passed to sendmail. Defaults to `-i`.</li></ul>|
|`raise_delivery_errors`|Whether or not errors should be raised if the email fails to be delivered. This only works if the external email server is configured for immediate delivery.|
|`delivery_method`|Defines a delivery method. Possible values are:<ul><li>`:smtp` (default), can be configured by using `config.action_mailer.smtp_settings`.</li><li>`:sendmail`, can be configured by using `config.action_mailer.sendmail_settings`.</li><li>`:file`: save emails to files; can be configured by using `config.action_mailer.file_settings`.</li><li>`:test`: save emails to `ActionMailer::Base.deliveries` array.</li></ul>See [API docs](https://api.rubyonrails.org/classes/ActionMailer/Base.html) for more info.|
diff --git a/guides/source/working_with_javascript_in_rails.md b/guides/source/working_with_javascript_in_rails.md
index b740e933ba..28af1cd88d 100644
--- a/guides/source/working_with_javascript_in_rails.md
+++ b/guides/source/working_with_javascript_in_rails.md
@@ -536,9 +536,9 @@ the token:
var token = document.getElementsByName('csrf-token')[0].content
```
-You can then submit this token as a X-CSRF-Token in your header for your
-Ajax requst. You do not need to add a CSRF for GET requests, only non-GET
-requests.
+You can then submit this token as a `X-CSRF-Token` header for your
+Ajax request. You do not need to add a CSRF token for GET requests,
+only non-GET ones.
You can read more about about Cross-Site Request Forgery in [Security](https://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf)
diff --git a/railties/lib/rails/code_statistics_calculator.rb b/railties/lib/rails/code_statistics_calculator.rb
index 3925e4faeb..8dd415d9d1 100644
--- a/railties/lib/rails/code_statistics_calculator.rb
+++ b/railties/lib/rails/code_statistics_calculator.rb
@@ -58,19 +58,19 @@ class CodeStatisticsCalculator #:nodoc:
@lines += 1
if comment_started
- if patterns[:end_block_comment] && line =~ patterns[:end_block_comment]
+ if patterns[:end_block_comment] && patterns[:end_block_comment].match?(line)
comment_started = false
end
next
else
- if patterns[:begin_block_comment] && line =~ patterns[:begin_block_comment]
+ if patterns[:begin_block_comment] && patterns[:begin_block_comment].match?(line)
comment_started = true
next
end
end
- @classes += 1 if patterns[:class] && line =~ patterns[:class]
- @methods += 1 if patterns[:method] && line =~ patterns[:method]
+ @classes += 1 if patterns[:class] && patterns[:class].match?(line)
+ @methods += 1 if patterns[:method] && patterns[:method].match?(line)
if !line.match?(/^\s*$/) && (patterns[:line_comment].nil? || !line.match?(patterns[:line_comment]))
@code_lines += 1
end
diff --git a/railties/lib/rails/command/behavior.rb b/railties/lib/rails/command/behavior.rb
index 7fb2a99e67..90650059f4 100644
--- a/railties/lib/rails/command/behavior.rb
+++ b/railties/lib/rails/command/behavior.rb
@@ -44,7 +44,7 @@ module Rails
require path
return
rescue LoadError => e
- raise unless e.message =~ /#{Regexp.escape(path)}$/
+ raise unless /#{Regexp.escape(path)}$/.match?(e.message)
rescue Exception => e
warn "[WARNING] Could not load #{command_type} #{path.inspect}. Error: #{e.message}.\n#{e.backtrace.join("\n")}"
end
diff --git a/railties/lib/rails/command/environment_argument.rb b/railties/lib/rails/command/environment_argument.rb
index 9945fd1430..df3cc1b2bb 100644
--- a/railties/lib/rails/command/environment_argument.rb
+++ b/railties/lib/rails/command/environment_argument.rb
@@ -28,7 +28,7 @@ module Rails
if available_environments.include? env
env
else
- %w( production development test ).detect { |e| e =~ /^#{env}/ } || env
+ %w( production development test ).detect { |e| /^#{env}/.match?(e) } || env
end
end
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index dbfb7337f0..ed0215bda9 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -400,7 +400,7 @@ module Rails
end
def os_supports_listen_out_of_the_box?
- RbConfig::CONFIG["host_os"] =~ /darwin|linux/
+ /darwin|linux/.match?(RbConfig::CONFIG["host_os"])
end
def run_bundle
diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb
index 4e348be9be..377a5dfc65 100644
--- a/railties/lib/rails/generators/generated_attribute.rb
+++ b/railties/lib/rails/generators/generated_attribute.rb
@@ -131,7 +131,7 @@ module Rails
end
def foreign_key?
- !!(name =~ /_id$/)
+ /_id$/.match?(name)
end
def reference?
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt
index cf5462f7dc..f13dab59b1 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt
@@ -72,7 +72,7 @@ group :test do
# Easy installation and use of web drivers to run system tests with browsers
gem 'webdrivers'
end
-<%- end -%>
+<%- end -%>
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
index b8c1f21c0b..437bf84ce3 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
@@ -2,6 +2,7 @@
<html>
<head>
<title><%= camelized %></title>
+ <meta name="viewport" content="width=device-width,initial-scale=1">
<%%= csrf_meta_tags %>
<%%= csp_meta_tag %>
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt
index 59385cdf37..3c56b21b3c 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt
@@ -1,7 +1,7 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
-# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!
diff --git a/railties/lib/rails/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb
index 7b294751fc..b8bce8c772 100644
--- a/railties/lib/rails/test_unit/runner.rb
+++ b/railties/lib/rails/test_unit/runner.rb
@@ -61,7 +61,7 @@ module Rails
private
def extract_filters(argv)
# Extract absolute and relative paths but skip -n /.*/ regexp filters.
- argv.select { |arg| arg =~ %r%^/?\w+/% && !arg.end_with?("/") }.map do |path|
+ argv.select { |arg| %r%^/?\w+/%.match?(arg) && !arg.end_with?("/") }.map do |path|
case
when /(:\d+)+$/.match?(path)
file, *lines = path.split(":")
diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb
index a7dd233f3d..651897d8f3 100644
--- a/railties/test/application/assets_test.rb
+++ b/railties/test/application/assets_test.rb
@@ -311,7 +311,7 @@ module ApplicationTests
manifest = Dir["#{app_path}/public/assets/.sprockets-manifest-*.json"].first
assets = ActiveSupport::JSON.decode(File.read(manifest))
- assert asset_path = assets["assets"].find { |(k, _)| k && k =~ /.png/ }[1]
+ assert asset_path = assets["assets"].find { |(k, _)| /.png/.match?(k) }[1]
# Load app env
app "development"
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 38dda20bec..cca86bc13a 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -456,7 +456,7 @@ module ApplicationTests
test "filter_parameters should be able to set via config.filter_parameters" do
add_to_config <<-RUBY
config.filter_parameters += [ :foo, 'bar', lambda { |key, value|
- value = value.reverse if key =~ /baz/
+ value = value.reverse if /baz/.match?(key)
}]
RUBY
@@ -790,7 +790,7 @@ module ApplicationTests
end
get "/"
- assert last_response.body =~ /csrf\-param/
+ assert /csrf\-param/.match?(last_response.body)
end
test "default form builder specified as a string" do
diff --git a/railties/test/application/zeitwerk_integration_test.rb b/railties/test/application/zeitwerk_integration_test.rb
index ff8c06b479..d03fa3d0c6 100644
--- a/railties/test/application/zeitwerk_integration_test.rb
+++ b/railties/test/application/zeitwerk_integration_test.rb
@@ -150,6 +150,35 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase
assert_empty deps.autoloaded_constants
end
+ [true, false].each do |add_aps_to_lp|
+ test "require_dependency looks autoload paths up (#{add_aps_to_lp})" do
+ add_to_config "config.add_autoload_paths_to_load_path = #{add_aps_to_lp}"
+ app_file "app/models/user.rb", "class User; end"
+ boot
+
+ assert require_dependency("user")
+ end
+
+ test "require_dependency handles absolute paths correctly (#{add_aps_to_lp})" do
+ add_to_config "config.add_autoload_paths_to_load_path = #{add_aps_to_lp}"
+ app_file "app/models/user.rb", "class User; end"
+ boot
+
+ assert require_dependency("#{app_path}/app/models/user.rb")
+ end
+
+ test "require_dependency supports arguments that repond to to_path (#{add_aps_to_lp})" do
+ add_to_config "config.add_autoload_paths_to_load_path = #{add_aps_to_lp}"
+ app_file "app/models/user.rb", "class User; end"
+ boot
+
+ user = Object.new
+ def user.to_path; "user"; end
+
+ assert require_dependency(user)
+ end
+ end
+
test "eager loading loads the application code" do
$zeitwerk_integration_test_user = false
$zeitwerk_integration_test_post = false
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 5b439fdcba..43461036f3 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -678,7 +678,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_inclusion_of_listen_related_configuration_by_default
run_generator
- if RbConfig::CONFIG["host_os"] =~ /darwin|linux/
+ if /darwin|linux/.match?(RbConfig::CONFIG["host_os"])
assert_listen_related_configuration
else
assert_no_listen_related_configuration
@@ -690,7 +690,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
Object.const_set(:RUBY_ENGINE, "MyRuby")
run_generator
- if RbConfig::CONFIG["host_os"] =~ /darwin|linux/
+ if /darwin|linux/.match?(RbConfig::CONFIG["host_os"])
assert_listen_related_configuration
else
assert_no_listen_related_configuration
@@ -708,7 +708,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_evented_file_update_checker_config
run_generator
assert_file "config/environments/development.rb" do |content|
- if RbConfig::CONFIG["host_os"] =~ /darwin|linux/
+ if /darwin|linux/.match?(RbConfig::CONFIG["host_os"])
assert_match(/^\s*config\.file_watcher = ActiveSupport::EventedFileUpdateChecker/, content)
else
assert_match(/^\s*# config\.file_watcher = ActiveSupport::EventedFileUpdateChecker/, content)
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 7f05b9d9cf..06836844f0 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -110,7 +110,7 @@ module RailtiesTest
assert_no_match(/\d+_create_users/, output.join("\n"))
- bukkits_migration_order = output.index(output.detect { |o| /NOTE: Migration \d+_create_sessions\.rb from bukkits has been skipped/ =~ o })
+ bukkits_migration_order = output.index(output.detect { |o| /NOTE: Migration \d+_create_sessions\.rb from bukkits has been skipped/.match?(o) })
assert_not_nil bukkits_migration_order, "Expected migration to be skipped"
end
end