diff options
548 files changed, 1824 insertions, 1180 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index 22161b1e16..e310351bf5 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -61,6 +61,10 @@ Layout/EndAlignment: Layout/EmptyLineAfterMagicComment: Enabled: true +Layout/EmptyLinesAroundAccessModifier: + Enabled: true + EnforcedStyle: only_before + Layout/EmptyLinesAroundBlockBody: Enabled: true @@ -10,7 +10,7 @@ gemspec gem "rake", ">= 11.1" gem "capybara", ">= 2.15" -gem "selenium-webdriver", ">= 3.5.0" +gem "selenium-webdriver", ">= 3.141.592" gem "rack-cache", "~> 1.2" gem "sass-rails" diff --git a/Gemfile.lock b/Gemfile.lock index 39ea426ed9..eb7dbf6877 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -71,7 +71,7 @@ PATH i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) - zeitwerk (~> 2.1, >= 2.1.4) + zeitwerk (~> 2.1, >= 2.1.8) rails (6.1.0.alpha) actioncable (= 6.1.0.alpha) actionmailbox (= 6.1.0.alpha) @@ -337,15 +337,14 @@ GEM mysql2 (0.5.2) mysql2 (0.5.2-x64-mingw32) mysql2 (0.5.2-x86-mingw32) - net_http_ssl_fix (0.0.10) nio4r (2.3.1) nio4r (2.3.1-java) - nokogiri (1.9.1) + nokogiri (1.10.3) mini_portile2 (~> 2.4.0) - nokogiri (1.9.1-java) - nokogiri (1.9.1-x64-mingw32) + nokogiri (1.10.3-java) + nokogiri (1.10.3-x64-mingw32) mini_portile2 (~> 2.4.0) - nokogiri (1.9.1-x86-mingw32) + nokogiri (1.10.3-x86-mingw32) mini_portile2 (~> 2.4.0) os (1.0.0) parallel (1.17.0) @@ -504,8 +503,7 @@ GEM json (>= 1.8) nokogiri (~> 1.6) wdm (0.1.1) - webdrivers (3.7.0) - net_http_ssl_fix + webdrivers (4.0.0) nokogiri (~> 1.6) rubyzip (~> 1.0) selenium-webdriver (~> 3.0) @@ -525,7 +523,7 @@ GEM websocket-extensions (0.1.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.1.4) + zeitwerk (2.1.8) PLATFORMS java @@ -584,7 +582,7 @@ DEPENDENCIES rubocop-rails sass-rails sdoc (~> 1.0) - selenium-webdriver (>= 3.5.0) + selenium-webdriver (>= 3.141.592) sequel sidekiq sneakers diff --git a/actioncable/lib/action_cable/server/broadcasting.rb b/actioncable/lib/action_cable/server/broadcasting.rb index bc54d784b3..b73cfa7d1f 100644 --- a/actioncable/lib/action_cable/server/broadcasting.rb +++ b/actioncable/lib/action_cable/server/broadcasting.rb @@ -40,7 +40,7 @@ module ActionCable end def broadcast(message) - server.logger.debug "[ActionCable] Broadcasting to #{broadcasting}: #{message.inspect}" + server.logger.debug { "[ActionCable] Broadcasting to #{broadcasting}: #{message.inspect}" } payload = { broadcasting: broadcasting, message: message, coder: coder } ActiveSupport::Notifications.instrument("broadcast.action_cable", payload) do diff --git a/actioncable/lib/action_cable/server/worker.rb b/actioncable/lib/action_cable/server/worker.rb index 187c8f7939..b918d4ae72 100644 --- a/actioncable/lib/action_cable/server/worker.rb +++ b/actioncable/lib/action_cable/server/worker.rb @@ -66,7 +66,6 @@ module ActionCable end private - def logger ActionCable.server.logger end diff --git a/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller.rb b/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller.rb index d051dfe665..8713f545f5 100644 --- a/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller.rb +++ b/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller.rb @@ -21,6 +21,7 @@ module Rails private def new_mail Mail.new(params.require(:mail).permit(:from, :to, :cc, :bcc, :in_reply_to, :subject, :body).to_h).tap do |mail| + mail[:bcc]&.include_in_headers = true params[:mail][:attachments].to_a.each do |attachment| mail.add_file(filename: attachment.path, content: attachment.read) end diff --git a/actionmailbox/test/controllers/rails/action_mailbox/inbound_emails_controller_test.rb b/actionmailbox/test/controllers/rails/action_mailbox/inbound_emails_controller_test.rb index fcd9ad839f..6fc39c2433 100644 --- a/actionmailbox/test/controllers/rails/action_mailbox/inbound_emails_controller_test.rb +++ b/actionmailbox/test/controllers/rails/action_mailbox/inbound_emails_controller_test.rb @@ -10,6 +10,8 @@ class Rails::Conductor::ActionMailbox::InboundEmailsControllerTest < ActionDispa mail: { from: "Jason Fried <jason@37signals.com>", to: "Replies <replies@example.com>", + cc: "CC <cc@example.com>", + bcc: "Bcc <bcc@example.com>", in_reply_to: "<4e6e35f5a38b4_479f13bb90078178@small-app-01.mail>", subject: "Hey there", body: "How's it going?" @@ -20,6 +22,8 @@ class Rails::Conductor::ActionMailbox::InboundEmailsControllerTest < ActionDispa mail = ActionMailbox::InboundEmail.last.mail assert_equal %w[ jason@37signals.com ], mail.from assert_equal %w[ replies@example.com ], mail.to + assert_equal %w[ cc@example.com ], mail.cc + assert_equal %w[ bcc@example.com ], mail.bcc assert_equal "4e6e35f5a38b4_479f13bb90078178@small-app-01.mail", mail.in_reply_to assert_equal "Hey there", mail.subject assert_equal "How's it going?", mail.body.decoded diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index c1ac9c2ad1..ba914c4813 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -591,7 +591,6 @@ module ActionMailer end private - def set_payload_for_mail(payload, mail) payload[:mail] = mail.encoded payload[:mailer] = name @@ -873,7 +872,6 @@ module ActionMailer end private - # Used by #mail to set the content type of the message. # # It will use the given +user_content_type+, or multipart if the mail diff --git a/actionmailer/lib/action_mailer/preview.rb b/actionmailer/lib/action_mailer/preview.rb index 500b3bede0..a763b9776c 100644 --- a/actionmailer/lib/action_mailer/preview.rb +++ b/actionmailer/lib/action_mailer/preview.rb @@ -55,7 +55,6 @@ module ActionMailer end private - def interceptor_class_for(interceptor) case interceptor when String, Symbol diff --git a/actionmailer/lib/action_mailer/test_case.rb b/actionmailer/lib/action_mailer/test_case.rb index ee5a864847..97afd87840 100644 --- a/actionmailer/lib/action_mailer/test_case.rb +++ b/actionmailer/lib/action_mailer/test_case.rb @@ -22,7 +22,6 @@ module ActionMailer end private - def clear_test_deliveries if ActionMailer::Base.delivery_method == :test ActionMailer::Base.deliveries.clear @@ -76,7 +75,6 @@ module ActionMailer end private - def initialize_test_deliveries set_delivery_method :test @old_perform_deliveries = ActionMailer::Base.perform_deliveries diff --git a/actionmailer/lib/action_mailer/test_helper.rb b/actionmailer/lib/action_mailer/test_helper.rb index e222301dff..988db2491c 100644 --- a/actionmailer/lib/action_mailer/test_helper.rb +++ b/actionmailer/lib/action_mailer/test_helper.rb @@ -152,7 +152,6 @@ module ActionMailer end private - def delivery_job_filter(job) job_class = job.is_a?(Hash) ? job.fetch(:job) : job.class diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index c07fca5b5e..4ea5634cd0 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -939,7 +939,6 @@ class BaseTest < ActiveSupport::TestCase end private - # Execute the block setting the given values and restoring old values after # the block is executed. def swap(klass, new_values) diff --git a/actionmailer/test/caching_test.rb b/actionmailer/test/caching_test.rb index b658c96ec7..c3a3e418d0 100644 --- a/actionmailer/test/caching_test.rb +++ b/actionmailer/test/caching_test.rb @@ -189,7 +189,6 @@ class FunctionalFragmentCachingTest < BaseCachingTest end private - def template_digest(name, format) ActionView::Digestor.digest(name: name, format: format, finder: @mailer.lookup_context) end diff --git a/actionmailer/test/i18n_with_controller_test.rb b/actionmailer/test/i18n_with_controller_test.rb index 6e75cff347..eea72e06ba 100644 --- a/actionmailer/test/i18n_with_controller_test.rb +++ b/actionmailer/test/i18n_with_controller_test.rb @@ -67,7 +67,6 @@ class ActionMailerI18nWithControllerTest < ActionDispatch::IntegrationTest end private - def with_translation(locale, data) I18n.backend.store_translations(locale, data) yield diff --git a/actionmailer/test/legacy_delivery_job_test.rb b/actionmailer/test/legacy_delivery_job_test.rb index 3a3872df47..a9b2a160d4 100644 --- a/actionmailer/test/legacy_delivery_job_test.rb +++ b/actionmailer/test/legacy_delivery_job_test.rb @@ -69,7 +69,6 @@ class LegacyDeliveryJobTest < ActiveSupport::TestCase end private - def with_delivery_job(job) old_params_delivery_job = ParamsMailer.delivery_job old_regular_delivery_job = DelayedMailer.delivery_job diff --git a/actionmailer/test/mail_helper_test.rb b/actionmailer/test/mail_helper_test.rb index 51d6ccb10f..a8ab19a95c 100644 --- a/actionmailer/test/mail_helper_test.rb +++ b/actionmailer/test/mail_helper_test.rb @@ -68,7 +68,6 @@ The second end private - def mail_with_defaults(&block) mail(to: "test@localhost", from: "tester@example.com", subject: "using helpers", &block) diff --git a/actionmailer/test/mailers/proc_mailer.rb b/actionmailer/test/mailers/proc_mailer.rb index 76e730bb79..75ee5dd9b6 100644 --- a/actionmailer/test/mailers/proc_mailer.rb +++ b/actionmailer/test/mailers/proc_mailer.rb @@ -18,7 +18,6 @@ class ProcMailer < ActionMailer::Base end private - def give_a_greeting "Thanks for signing up this afternoon" end diff --git a/actionmailer/test/parameterized_test.rb b/actionmailer/test/parameterized_test.rb index 7dd6156744..62dd671f48 100644 --- a/actionmailer/test/parameterized_test.rb +++ b/actionmailer/test/parameterized_test.rb @@ -81,7 +81,6 @@ class ParameterizedTest < ActiveSupport::TestCase end private - def with_delivery_job(job) old_delivery_job = ParamsMailer.delivery_job ParamsMailer.delivery_job = job diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 55592585ea..0dd170fd28 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,9 @@ +* Add the ability to set the CSP nonce only to the specified directives. + + Fixes #35137. + + *Yuji Yaginuma* + * Keep part when scope option has value. When a route was defined within an optional scope, if that route didn't diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index bb42f2e119..3ff922029b 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -176,7 +176,6 @@ module AbstractController end private - # Returns true if the name can be considered an action because # it has a method defined in the controller. # diff --git a/actionpack/lib/abstract_controller/collector.rb b/actionpack/lib/abstract_controller/collector.rb index d4a078ab32..0af546cc96 100644 --- a/actionpack/lib/abstract_controller/collector.rb +++ b/actionpack/lib/abstract_controller/collector.rb @@ -22,7 +22,6 @@ module AbstractController end private - def method_missing(symbol, &block) unless mime_constant = Mime[symbol] raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \ diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index bf3b00a7b7..83e3e0c37c 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -30,7 +30,6 @@ module ActionController end private - def instrument_payload(key) { controller: controller_name, diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 9ca0bbb9db..ec2207b8da 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -35,7 +35,6 @@ module ActionController end private - INCLUDE = ->(list, action) { list.include? action } EXCLUDE = ->(list, action) { !list.include? action } NULL = ->(list, action) { true } diff --git a/actionpack/lib/action_controller/metal/content_security_policy.rb b/actionpack/lib/action_controller/metal/content_security_policy.rb index b8fab4ebe3..ebd90f07c8 100644 --- a/actionpack/lib/action_controller/metal/content_security_policy.rb +++ b/actionpack/lib/action_controller/metal/content_security_policy.rb @@ -36,7 +36,6 @@ module ActionController #:nodoc: end private - def content_security_policy? request.content_security_policy end diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb index 51fac08749..6f7fc0d624 100644 --- a/actionpack/lib/action_controller/metal/instrumentation.rb +++ b/actionpack/lib/action_controller/metal/instrumentation.rb @@ -69,7 +69,6 @@ module ActionController end private - # A hook invoked every time a before callback is halted. def halted_callback_hook(filter) ActiveSupport::Notifications.instrument("halted_callback.action_controller", filter: filter) diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index dd69930e25..4454ba1e3d 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -107,7 +107,6 @@ module ActionController end private - def perform_write(json, options) current_options = @options.merge(options).stringify_keys @@ -205,7 +204,6 @@ module ActionController end private - def each_chunk(&block) loop do str = nil @@ -220,7 +218,6 @@ module ActionController class Response < ActionDispatch::Response #:nodoc: all private - def before_committed super jar = request.cookie_jar @@ -286,7 +283,6 @@ module ActionController end private - # Spawn a new thread to serve up the controller in. This is to get # around the fact that Rack isn't based around IOs and we need to use # a thread to stream data from the response bodies. Nobody should call diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb index e635abec8e..150ae2666c 100644 --- a/actionpack/lib/action_controller/metal/params_wrapper.rb +++ b/actionpack/lib/action_controller/metal/params_wrapper.rb @@ -246,7 +246,6 @@ module ActionController end private - # Returns the wrapper key which will be used to store wrapped parameters. def _wrapper_key _wrapper_options.name diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index 7f7c736965..efa5de313c 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -53,7 +53,6 @@ module ActionController end private - def _process_variant(options) if defined?(request) && !request.nil? && request.variant.present? options[:variant] = request.variant diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 4bf8d90b69..5a5c04234b 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -151,7 +151,6 @@ module ActionController #:nodoc: end private - def protection_method_class(name) ActionController::RequestForgeryProtection::ProtectionMethods.const_get(name.to_s.classify) rescue NameError @@ -175,7 +174,6 @@ module ActionController #:nodoc: end private - class NullSessionHash < Rack::Session::Abstract::SessionHash #:nodoc: def initialize(req) super(nil, req) diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb index 8dc01a5eb9..94a62e5cab 100644 --- a/actionpack/lib/action_controller/metal/streaming.rb +++ b/actionpack/lib/action_controller/metal/streaming.rb @@ -196,7 +196,6 @@ module ActionController #:nodoc: extend ActiveSupport::Concern private - # Set proper cache control and transfer encoding when streaming def _process_options(options) super diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 57921f32b7..47e0099f20 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -158,7 +158,6 @@ module ActionController end.new private - def params_parsers super.merge @custom_param_parsers end @@ -208,7 +207,6 @@ module ActionController end private - def load! @id end @@ -594,7 +592,6 @@ module ActionController end private - def scrub_env!(env) env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ } env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ } diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index 8cc84ff36c..7be30be77a 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -123,7 +123,6 @@ module ActionDispatch end private - DATE = "Date" LAST_MODIFIED = "Last-Modified" SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public private must-revalidate]) diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb index b1e5a28be5..7dedecef34 100644 --- a/actionpack/lib/action_dispatch/http/content_security_policy.rb +++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb @@ -22,15 +22,15 @@ module ActionDispatch #:nodoc: if policy = request.content_security_policy nonce = request.content_security_policy_nonce + nonce_directives = request.content_security_policy_nonce_directives context = request.controller_instance || request - headers[header_name(request)] = policy.build(context, nonce) + headers[header_name(request)] = policy.build(context, nonce, nonce_directives) end response end private - def html_response?(headers) if content_type = headers[CONTENT_TYPE] content_type =~ /html/ @@ -55,6 +55,7 @@ module ActionDispatch #:nodoc: POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only" NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator" NONCE = "action_dispatch.content_security_policy_nonce" + NONCE_DIRECTIVES = "action_dispatch.content_security_policy_nonce_directives" def content_security_policy get_header(POLICY) @@ -80,6 +81,14 @@ module ActionDispatch #:nodoc: set_header(NONCE_GENERATOR, generator) end + def content_security_policy_nonce_directives + get_header(NONCE_DIRECTIVES) + end + + def content_security_policy_nonce_directives=(generator) + set_header(NONCE_DIRECTIVES, generator) + end + def content_security_policy_nonce if content_security_policy_nonce_generator if nonce = get_header(NONCE) @@ -91,7 +100,6 @@ module ActionDispatch #:nodoc: end private - def generate_content_security_policy_nonce content_security_policy_nonce_generator.call(self) end @@ -133,9 +141,9 @@ module ActionDispatch #:nodoc: worker_src: "worker-src" }.freeze - NONCE_DIRECTIVES = %w[script-src style-src].freeze + DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze - private_constant :MAPPINGS, :DIRECTIVES, :NONCE_DIRECTIVES + private_constant :MAPPINGS, :DIRECTIVES, :DEFAULT_NONCE_DIRECTIVES attr_reader :directives @@ -204,8 +212,9 @@ module ActionDispatch #:nodoc: end end - def build(context = nil, nonce = nil) - build_directives(context, nonce).compact.join("; ") + def build(context = nil, nonce = nil, nonce_directives = nil) + nonce_directives = DEFAULT_NONCE_DIRECTIVES if nonce_directives.nil? + build_directives(context, nonce, nonce_directives).compact.join("; ") end private @@ -228,10 +237,10 @@ module ActionDispatch #:nodoc: end end - def build_directives(context, nonce) + def build_directives(context, nonce, nonce_directives) @directives.map do |directive, sources| if sources.is_a?(Array) - if nonce && nonce_directive?(directive) + if nonce && nonce_directive?(directive, nonce_directives) "#{directive} #{build_directive(sources, context).join(' ')} 'nonce-#{nonce}'" else "#{directive} #{build_directive(sources, context).join(' ')}" @@ -266,8 +275,8 @@ module ActionDispatch #:nodoc: end end - def nonce_directive?(directive) - NONCE_DIRECTIVES.include?(directive) + def nonce_directive?(directive, nonce_directives) + nonce_directives.include?(directive) end end end diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index cbb772175c..7a7a493f64 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -56,7 +56,6 @@ module ActionDispatch end private - def parameter_filter # :doc: parameter_filter_for fetch_header("action_dispatch.parameter_filter") { return NULL_PARAM_FILTER diff --git a/actionpack/lib/action_dispatch/http/filter_redirect.rb b/actionpack/lib/action_dispatch/http/filter_redirect.rb index 8c4e852235..d780d5f793 100644 --- a/actionpack/lib/action_dispatch/http/filter_redirect.rb +++ b/actionpack/lib/action_dispatch/http/filter_redirect.rb @@ -14,7 +14,6 @@ module ActionDispatch end private - def location_filters if request request.get_header("action_dispatch.redirect_filter") || [] diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb index 6c7d24d2d0..6ab913bfd0 100644 --- a/actionpack/lib/action_dispatch/http/headers.rb +++ b/actionpack/lib/action_dispatch/http/headers.rb @@ -116,7 +116,6 @@ module ActionDispatch def env; @req.env.dup; end private - # Converts an HTTP header name to an environment variable name if it is # not contained within the headers hash. def env_name(key) diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index 4e81ba12a5..a2cac49082 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -154,7 +154,6 @@ module ActionDispatch end private - BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/ def valid_accept_header # :doc: diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 88b3a93211..ed1d50f3b9 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -290,11 +290,9 @@ module Mime def all?; false; end protected - attr_reader :string, :synonyms private - def to_ary; end def to_a; end diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb index 13d0963a33..3c16817af3 100644 --- a/actionpack/lib/action_dispatch/http/parameters.rb +++ b/actionpack/lib/action_dispatch/http/parameters.rb @@ -85,7 +85,6 @@ module ActionDispatch end private - def set_binary_encoding(params, controller, action) return params unless controller && controller.valid_encoding? diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index e5cffccf35..ea3692951f 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -86,6 +86,7 @@ module ActionDispatch # :nodoc: cattr_accessor :default_charset, default: "utf-8" cattr_accessor :default_headers + cattr_accessor :return_only_media_type_on_content_type, default: false include Rack::Response::Helpers # Aliasing these off because AD::Http::Cache::Response defines them. @@ -143,7 +144,6 @@ module ActionDispatch # :nodoc: end private - def each_chunk(&block) @buf.each(&block) end @@ -244,7 +244,17 @@ module ActionDispatch # :nodoc: # Content type of response. def content_type - super.presence + if self.class.return_only_media_type_on_content_type + ActiveSupport::Deprecation.warn( + "Rails 6.1 will return Content-Type header without modification." \ + " If you want just the MIME type, please use `#media_type` instead." + ) + + content_type = super + content_type ? content_type.split(/;\s*charset=/)[0].presence : content_type + else + super.presence + end end # Media type of response. @@ -409,7 +419,6 @@ module ActionDispatch # :nodoc: end private - ContentTypeHeader = Struct.new :mime_type, :charset NullContentTypeHeader = ContentTypeHeader.new nil, nil diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 8227749986..3b0f6378ea 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -78,7 +78,6 @@ module ActionDispatch end private - def add_params(path, params) params = { params: params } unless params.is_a?(Hash) params.reject! { |_, v| v.to_param.nil? } diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb index 53c404ee7c..a4861719f8 100644 --- a/actionpack/lib/action_dispatch/journey/formatter.rb +++ b/actionpack/lib/action_dispatch/journey/formatter.rb @@ -62,7 +62,6 @@ module ActionDispatch end private - def extract_parameterized_parts(route, options, recall, parameterize = nil) parameterized_parts = recall.merge(options) diff --git a/actionpack/lib/action_dispatch/journey/gtg/builder.rb b/actionpack/lib/action_dispatch/journey/gtg/builder.rb index 44c31053cb..2600e7fb70 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/builder.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/builder.rb @@ -128,7 +128,6 @@ module ActionDispatch end private - def followpos_table @followpos ||= build_followpos end diff --git a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb index ea647e051a..5003e92f43 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb @@ -141,7 +141,6 @@ module ActionDispatch end private - def states_hash_for(sym) case sym when String diff --git a/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb b/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb index fe55861507..b36003089d 100644 --- a/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb +++ b/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb @@ -94,7 +94,6 @@ module ActionDispatch end private - def inverted return @inverted if @inverted diff --git a/actionpack/lib/action_dispatch/journey/path/pattern.rb b/actionpack/lib/action_dispatch/journey/path/pattern.rb index dee2980eb1..e4ba82ebdd 100644 --- a/actionpack/lib/action_dispatch/journey/path/pattern.rb +++ b/actionpack/lib/action_dispatch/journey/path/pattern.rb @@ -174,7 +174,6 @@ module ActionDispatch end private - def regexp_visitor @anchored ? AnchoredRegexp : UnanchoredRegexp end diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb index 89a164f968..4a6639af74 100644 --- a/actionpack/lib/action_dispatch/journey/router.rb +++ b/actionpack/lib/action_dispatch/journey/router.rb @@ -81,7 +81,6 @@ module ActionDispatch end private - def partitioned_routes routes.partition { |r| r.path.anchored && r.ast.grep(Nodes::Symbol).all? { |n| n.default_regexp? } diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb index 3ba8361d77..3f055db66d 100644 --- a/actionpack/lib/action_dispatch/journey/routes.rb +++ b/actionpack/lib/action_dispatch/journey/routes.rb @@ -71,7 +71,6 @@ module ActionDispatch end private - def clear_cache! @ast = nil @simulator = nil diff --git a/actionpack/lib/action_dispatch/journey/scanner.rb b/actionpack/lib/action_dispatch/journey/scanner.rb index 2a075862e9..eb6fd17aa7 100644 --- a/actionpack/lib/action_dispatch/journey/scanner.rb +++ b/actionpack/lib/action_dispatch/journey/scanner.rb @@ -33,7 +33,6 @@ module ActionDispatch end private - # takes advantage of String @- deduping capabilities in Ruby 2.5 upwards # see: https://bugs.ruby-lang.org/issues/13077 def dedup_scan(regex) diff --git a/actionpack/lib/action_dispatch/journey/visitors.rb b/actionpack/lib/action_dispatch/journey/visitors.rb index d2619cbf3a..ff26c9a3b0 100644 --- a/actionpack/lib/action_dispatch/journey/visitors.rb +++ b/actionpack/lib/action_dispatch/journey/visitors.rb @@ -59,7 +59,6 @@ module ActionDispatch end private - def visit(node) send(DISPATCH_CACHE[node.type], node) end @@ -168,7 +167,6 @@ module ActionDispatch class String < FunctionalVisitor # :nodoc: private - def binary(node, seed) visit(node.right, visit(node.left, seed)) end @@ -214,7 +212,6 @@ module ActionDispatch end private - def binary(node, seed) seed.last.concat node.children.map { |c| "#{node.object_id} -> #{c.object_id};" diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index dac60a13c6..642f155085 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -252,7 +252,6 @@ module ActionDispatch end private - def upgrade_legacy_hmac_aes_cbc_cookies? request.secret_key_base.present? && request.encrypted_signed_cookie_salt.present? && @@ -428,7 +427,6 @@ module ActionDispatch mattr_accessor :always_write_cookie, default: false private - def escape(string) ::Rack::Utils.escape(string) end diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb index 59113e13f4..f8937a2faf 100644 --- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb @@ -42,7 +42,6 @@ module ActionDispatch end private - def invoke_interceptors(request, exception) backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner") wrapper = ExceptionWrapper.new(backtrace_cleaner, exception) diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb index 0cc56f5013..2da0ef9600 100644 --- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb +++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb @@ -130,7 +130,6 @@ module ActionDispatch end private - def backtrace Array(@exception.backtrace) end diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index b7dff1df41..de7739b9b6 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -30,7 +30,6 @@ module ActionDispatch end private - def sanitize_hosts(hosts) Array(hosts).map do |host| case host @@ -87,7 +86,6 @@ module ActionDispatch end private - def authorized?(request) origin_host = request.get_header("HTTP_HOST").to_s.sub(/:\d+\z/, "") forwarded_host = request.x_forwarded_host.to_s.split(/,\s?/).last.to_s.sub(/:\d+\z/, "") diff --git a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb index a88ad40f21..3a2a1d7334 100644 --- a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb @@ -32,7 +32,6 @@ module ActionDispatch end private - def render(status, content_type, body) format = "to_#{content_type.to_sym}" if content_type if format && body.respond_to?(format) diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb index a5667573f4..c5d4a0bd31 100644 --- a/actionpack/lib/action_dispatch/middleware/remote_ip.rb +++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb @@ -156,7 +156,6 @@ module ActionDispatch end private - def ips_from(header) # :doc: return [] unless header # Split the comma-separated list into an array of strings. diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 5b0be96223..3815971acb 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -30,7 +30,6 @@ module ActionDispatch end private - def initialize_sid # :doc: @default_options.delete(:sidbits) @default_options.delete(:secure_random) @@ -83,7 +82,6 @@ module ActionDispatch include SessionObject private - def set_cookie(request, session_id, cookie) request.cookie_jar[key] = cookie end diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index 7c43c781c7..892d88803e 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -67,7 +67,6 @@ module ActionDispatch end private - def extract_session_id(req) stale_session_check! do unpacked_cookie_data(req)["session_id"] diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 767143a368..a35c0da3d9 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -40,7 +40,6 @@ module ActionDispatch end private - def render_exception(request, exception) backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner" wrapper = ExceptionWrapper.new(backtrace_cleaner, exception) diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index 57e4adb457..775110d95e 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -134,7 +134,6 @@ module ActionDispatch end private - def assert_index(index, where) i = index.is_a?(Integer) ? index : middlewares.index { |m| m.klass == index } raise "No such middleware to insert #{where}: #{index.inspect}" unless i diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index 5f711c7348..66f90980b9 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -23,6 +23,7 @@ module ActionDispatch config.action_dispatch.use_authenticated_cookie_encryption = false config.action_dispatch.use_cookies_with_metadata = false config.action_dispatch.perform_deep_munge = true + config.action_dispatch.return_only_media_type_on_content_type = true config.action_dispatch.default_headers = { "X-Frame-Options" => "SAMEORIGIN", @@ -43,6 +44,7 @@ module ActionDispatch ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge ActionDispatch::Response.default_charset = app.config.action_dispatch.default_charset || app.config.encoding ActionDispatch::Response.default_headers = app.config.action_dispatch.default_headers + ActionDispatch::Response.return_only_media_type_on_content_type = app.config.action_dispatch.return_only_media_type_on_content_type ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses) ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates) diff --git a/actionpack/lib/action_dispatch/request/session.rb b/actionpack/lib/action_dispatch/request/session.rb index bc5e0670e0..8faedf15b9 100644 --- a/actionpack/lib/action_dispatch/request/session.rb +++ b/actionpack/lib/action_dispatch/request/session.rb @@ -216,7 +216,6 @@ module ActionDispatch end private - def load_for_read! load! if !loaded? && exists? end diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb index 413e524ef6..6e40a18009 100644 --- a/actionpack/lib/action_dispatch/routing/inspector.rb +++ b/actionpack/lib/action_dispatch/routing/inspector.rb @@ -177,7 +177,6 @@ module ActionDispatch end private - def draw_section(routes) header_lengths = ["Prefix", "Verb", "URI Pattern"].map(&:length) name_width, verb_width, path_width = widths(routes).zip(header_lengths).map(&:max) @@ -210,7 +209,6 @@ module ActionDispatch end private - def draw_expanded_section(routes) routes.map.each_with_index do |r, i| <<~MESSAGE.chomp diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0aba484a45..d1100089b1 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1673,7 +1673,6 @@ module ActionDispatch end private - def parent_resource @scope[:scope_level_resource] end diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 4de5f9e2f7..e3322e99ab 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -156,7 +156,6 @@ module ActionDispatch end private - def polymorphic_url_for_action(action, record_or_hash, options) polymorphic_url(record_or_hash, options.merge(action: action)) end @@ -323,7 +322,6 @@ module ActionDispatch end private - def polymorphic_mapping(target, record) if record.respond_to?(:to_model) target._routes.polymorphic_mappings[record.to_model.model_name.name] diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index bbb5762b3c..5b35b68c44 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -40,7 +40,6 @@ module ActionDispatch end private - def controller(req) req.controller_class rescue NameError => e @@ -59,7 +58,6 @@ module ActionDispatch end private - def controller(_); @controller_class; end end @@ -215,7 +213,6 @@ module ActionDispatch end private - def optimized_helper(args) params = parameterize_args(args) do raise_generation_error(args) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index fcb8ae296b..e02a6541c1 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -215,13 +215,11 @@ module ActionDispatch end protected - def optimize_routes_generation? _routes.optimize_routes_generation? && default_url_options.empty? end private - def _with_routes(routes) # :doc: old_routes, @_routes = @_routes, routes yield diff --git a/actionpack/lib/action_dispatch/system_test_case.rb b/actionpack/lib/action_dispatch/system_test_case.rb index a7fb5fa330..29864c0f8e 100644 --- a/actionpack/lib/action_dispatch/system_test_case.rb +++ b/actionpack/lib/action_dispatch/system_test_case.rb @@ -4,6 +4,7 @@ gem "capybara", ">= 2.15" require "capybara/dsl" require "capybara/minitest" +require "selenium/webdriver" require "action_controller" require "action_dispatch/system_testing/driver" require "action_dispatch/system_testing/browser" diff --git a/actionpack/lib/action_dispatch/system_testing/browser.rb b/actionpack/lib/action_dispatch/system_testing/browser.rb index c34907b6cb..e861e52f09 100644 --- a/actionpack/lib/action_dispatch/system_testing/browser.rb +++ b/actionpack/lib/action_dispatch/system_testing/browser.rb @@ -39,6 +39,29 @@ module ActionDispatch end end + # driver_path can be configured as a proc. The webdrivers gem uses this + # proc to update web drivers. Running this proc early allows us to only + # update the webdriver once and avoid race conditions when using + # parallel tests. + def preload + case type + when :chrome + if ::Selenium::WebDriver::Service.respond_to? :driver_path= + ::Selenium::WebDriver::Chrome::Service.driver_path.try(:call) + else + # Selenium <= v3.141.0 + ::Selenium::WebDriver::Chrome.driver_path + end + when :firefox + if ::Selenium::WebDriver::Service.respond_to? :driver_path= + ::Selenium::WebDriver::Firefox::Service.driver_path.try(:call) + else + # Selenium <= v3.141.0 + ::Selenium::WebDriver::Firefox.driver_path + end + end + end + private def headless_chrome_browser_options capabilities.args << "--headless" diff --git a/actionpack/lib/action_dispatch/system_testing/driver.rb b/actionpack/lib/action_dispatch/system_testing/driver.rb index 25a09dd918..15943a55ea 100644 --- a/actionpack/lib/action_dispatch/system_testing/driver.rb +++ b/actionpack/lib/action_dispatch/system_testing/driver.rb @@ -9,6 +9,8 @@ module ActionDispatch @screen_size = options[:screen_size] @options = options[:options] @capabilities = capabilities + + @browser.preload end def use diff --git a/actionpack/lib/action_dispatch/testing/assertion_response.rb b/actionpack/lib/action_dispatch/testing/assertion_response.rb index dc019db6ac..79af372cc1 100644 --- a/actionpack/lib/action_dispatch/testing/assertion_response.rb +++ b/actionpack/lib/action_dispatch/testing/assertion_response.rb @@ -35,7 +35,6 @@ module ActionDispatch end private - def code_from_name(name) GENERIC_RESPONSE_CODES[name] || Rack::Utils::SYMBOL_TO_STATUS_CODE[name] end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 32a0b8efeb..1decfcee95 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -335,7 +335,6 @@ module RoutingTestHelpers end private - def make_request(env) Request.new super, url_helpers, @block, strict end diff --git a/actionpack/test/controller/api/conditional_get_test.rb b/actionpack/test/controller/api/conditional_get_test.rb index e366ce9532..f1cd9e46f9 100644 --- a/actionpack/test/controller/api/conditional_get_test.rb +++ b/actionpack/test/controller/api/conditional_get_test.rb @@ -18,7 +18,6 @@ class ConditionalGetApiController < ActionController::API end private - def handle_last_modified_and_etags fresh_when(last_modified: Time.now.utc.beginning_of_day, etag: [ :foo, 123 ]) end diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb index aeb0d07195..fcf767b706 100644 --- a/actionpack/test/controller/content_type_test.rb +++ b/actionpack/test/controller/content_type_test.rb @@ -132,7 +132,6 @@ class ContentTypeTest < ActionController::TestCase end private - def with_default_charset(charset) old_default_charset = ActionDispatch::Response.default_charset ActionDispatch::Response.default_charset = charset diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index fcee812ee4..40443a9397 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -310,7 +310,6 @@ class FilterTest < ActionController::TestCase after_action :conditional_in_parent_after, only: [:show, :another_action] private - def conditional_in_parent_before @ran_filter ||= [] @ran_filter << "conditional_in_parent_before" @@ -508,7 +507,6 @@ class FilterTest < ActionController::TestCase end private - def filter_one @filters ||= [] @filters << "filter_one" @@ -532,7 +530,6 @@ class FilterTest < ActionController::TestCase before_action :find_except, except: :edit private - def find_only @only = "Only" end diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb index bf95c633e5..1f44c7a68e 100644 --- a/actionpack/test/controller/flash_test.rb +++ b/actionpack/test/controller/flash_test.rb @@ -361,7 +361,6 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest end private - # Overwrite get to send SessionSecret in env hash def get(path, *args) args[0] ||= {} diff --git a/actionpack/test/controller/http_basic_authentication_test.rb b/actionpack/test/controller/http_basic_authentication_test.rb index 1544a627ee..73524d0443 100644 --- a/actionpack/test/controller/http_basic_authentication_test.rb +++ b/actionpack/test/controller/http_basic_authentication_test.rb @@ -32,7 +32,6 @@ class HttpBasicAuthenticationTest < ActionController::TestCase end private - def authenticate authenticate_or_request_with_http_basic do |username, password| username == "lifo" && password == "world" @@ -172,7 +171,6 @@ class HttpBasicAuthenticationTest < ActionController::TestCase end private - def encode_credentials(username, password) "Basic #{::Base64.encode64("#{username}:#{password}")}" end diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index dd4ff85d11..a0f543f607 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -20,7 +20,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase end private - def authenticate authenticate_or_request_with_http_digest("SuperSecret") do |username| # Returns the password @@ -254,7 +253,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase end private - def encode_credentials(options) options.reverse_merge!(nc: "00000001", cnonce: "0a4f113b", password_is_ha1: false) password = options.delete(:password) diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb index 103123f98c..57b78154bc 100644 --- a/actionpack/test/controller/http_token_authentication_test.rb +++ b/actionpack/test/controller/http_token_authentication_test.rb @@ -21,7 +21,6 @@ class HttpTokenAuthenticationTest < ActionController::TestCase end private - def authenticate authenticate_or_request_with_http_token do |token, _| token == "lifo" @@ -190,7 +189,6 @@ class HttpTokenAuthenticationTest < ActionController::TestCase end private - def sample_request(token, options = { nonce: "def" }) authorization = options.inject([%{Token token="#{token}"}]) do |arr, (k, v)| arr << "#{k}=\"#{v}\"" diff --git a/actionpack/test/controller/mime/accept_format_test.rb b/actionpack/test/controller/mime/accept_format_test.rb index eed671d593..fb038ae158 100644 --- a/actionpack/test/controller/mime/accept_format_test.rb +++ b/actionpack/test/controller/mime/accept_format_test.rb @@ -43,7 +43,6 @@ class PostController < AbstractPostController end private - def with_iphone request.format = "iphone" if request.env["HTTP_ACCEPT"] == "text/iphone" yield diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index 14dc958475..270f75eb9e 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -67,7 +67,6 @@ module RenderTemplate end private - def show_detailed_exceptions? request.local? end diff --git a/actionpack/test/controller/new_base/render_test.rb b/actionpack/test/controller/new_base/render_test.rb index eb29203f59..dfeb2e2b15 100644 --- a/actionpack/test/controller/new_base/render_test.rb +++ b/actionpack/test/controller/new_base/render_test.rb @@ -37,7 +37,6 @@ module Render end private - def secretz render plain: "FAIL WHALE!" end diff --git a/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb b/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb index fc9229ca1d..4fffcf6b10 100644 --- a/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb +++ b/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb @@ -52,7 +52,6 @@ class LogOnUnpermittedParamsTest < ActiveSupport::TestCase end private - def assert_logged(message) old_logger = ActionController::Base.logger log = StringIO.new diff --git a/actionpack/test/controller/params_parse_test.rb b/actionpack/test/controller/params_parse_test.rb index 440ab06fd7..091b567473 100644 --- a/actionpack/test/controller/params_parse_test.rb +++ b/actionpack/test/controller/params_parse_test.rb @@ -24,7 +24,6 @@ class ParamsParseTest < ActionController::TestCase end private - def capture_log_output output = StringIO.new request.set_header "action_dispatch.logger", ActiveSupport::Logger.new(output) diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb index c4c74e8f2b..894a3824c0 100644 --- a/actionpack/test/controller/params_wrapper_test.rb +++ b/actionpack/test/controller/params_wrapper_test.rb @@ -411,7 +411,6 @@ class IrregularInflectionParamsWrapperTest < ActionController::TestCase end private - def with_dup original = ActiveSupport::Inflector::Inflections.instance_variable_get(:@__instance__)[:en] ActiveSupport::Inflector::Inflections.instance_variable_set(:@__instance__, en: original.dup) diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 8bb6617eaa..a2a6c69dd3 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -265,7 +265,6 @@ class TestController < ActionController::Base end private - def set_variable_for_layout @variable_for_layout = nil end diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index ea94a3e048..01250880f5 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -112,7 +112,6 @@ class PrependProtectForgeryBaseController < ActionController::Base end private - def add_called_callback(name) @called_callbacks ||= [] @called_callbacks << name diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index 089b0b94d4..538bc15fc9 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -304,7 +304,6 @@ class RescueControllerTest < ActionController::TestCase end private - def capture_log_output output = StringIO.new request.set_header "action_dispatch.logger", ActiveSupport::Logger.new(output) @@ -351,7 +350,6 @@ class RescueTest < ActionDispatch::IntegrationTest end private - def with_test_routing with_routing do |set| set.draw do diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb index 2cd2114db6..8e1068fecf 100644 --- a/actionpack/test/controller/show_exceptions_test.rb +++ b/actionpack/test/controller/show_exceptions_test.rb @@ -51,7 +51,6 @@ module ShowExceptions class ShowExceptionsOverriddenController < ShowExceptionsController private - def show_detailed_exceptions? params["detailed"] == "1" end diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb index 998a495d0d..635a91507d 100644 --- a/actionpack/test/controller/test_case_test.rb +++ b/actionpack/test/controller/test_case_test.rb @@ -165,7 +165,6 @@ XML end private - def generate_url(opts) url_for(opts.merge(action: "test_uri")) end diff --git a/actionpack/test/dispatch/callbacks_test.rb b/actionpack/test/dispatch/callbacks_test.rb index fc80191c02..aa8640c506 100644 --- a/actionpack/test/dispatch/callbacks_test.rb +++ b/actionpack/test/dispatch/callbacks_test.rb @@ -38,7 +38,6 @@ class DispatcherTest < ActiveSupport::TestCase end private - def dispatch(&block) ActionDispatch::Callbacks.new(block || DummyApp.new).call( "rack.input" => StringIO.new("") diff --git a/actionpack/test/dispatch/content_security_policy_test.rb b/actionpack/test/dispatch/content_security_policy_test.rb index c8c885f35c..a4634626bb 100644 --- a/actionpack/test/dispatch/content_security_policy_test.rb +++ b/actionpack/test/dispatch/content_security_policy_test.rb @@ -307,7 +307,6 @@ class DefaultContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationT end private - def assert_policy(expected, report_only: false) if report_only expected_header = "Content-Security-Policy-Report-Only" @@ -470,7 +469,6 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest end private - def assert_policy(expected, report_only: false) assert_response :success @@ -544,3 +542,57 @@ class DisabledContentSecurityPolicyIntegrationTest < ActionDispatch::Integration assert_equal "default-src https://example.com", response.headers["Content-Security-Policy"] end end + +class NonceDirectiveContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest + class PolicyController < ActionController::Base + def index + head :ok + end + end + + ROUTES = ActionDispatch::Routing::RouteSet.new + ROUTES.draw do + scope module: "nonce_directive_content_security_policy_integration_test" do + get "/", to: "policy#index" + end + end + + POLICY = ActionDispatch::ContentSecurityPolicy.new do |p| + p.default_src -> { :self } + p.script_src -> { :https } + p.style_src -> { :https } + end + + class PolicyConfigMiddleware + def initialize(app) + @app = app + end + + def call(env) + env["action_dispatch.content_security_policy"] = POLICY + env["action_dispatch.content_security_policy_nonce_generator"] = proc { "iyhD0Yc0W+c=" } + env["action_dispatch.content_security_policy_report_only"] = false + env["action_dispatch.content_security_policy_nonce_directives"] = %w(script-src) + env["action_dispatch.show_exceptions"] = false + + @app.call(env) + end + end + + APP = build_app(ROUTES) do |middleware| + middleware.use PolicyConfigMiddleware + middleware.use ActionDispatch::ContentSecurityPolicy::Middleware + end + + def app + APP + end + + def test_generate_nonce_only_specified_in_nonce_directives + get "/" + + assert_response :success + assert_match "script-src https: 'nonce-iyhD0Yc0W+c='", response.headers["Content-Security-Policy"] + assert_no_match "style-src https: 'nonce-iyhD0Yc0W+c='", response.headers["Content-Security-Policy"] + end +end diff --git a/actionpack/test/dispatch/request_id_test.rb b/actionpack/test/dispatch/request_id_test.rb index 9df4712dab..036180c297 100644 --- a/actionpack/test/dispatch/request_id_test.rb +++ b/actionpack/test/dispatch/request_id_test.rb @@ -29,7 +29,6 @@ class RequestIdTest < ActiveSupport::TestCase end private - def stub_request(env = {}) ActionDispatch::RequestId.new(lambda { |environment| [ 200, environment, [] ] }).call(env) ActionDispatch::Request.new(env) @@ -58,7 +57,6 @@ class RequestIdResponseTest < ActionDispatch::IntegrationTest end private - def with_test_route_set with_routing do |set| set.draw do diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 33cf86a081..ed64d89902 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -593,4 +593,33 @@ class ResponseIntegrationTest < ActionDispatch::IntegrationTest assert_equal("text/csv", @response.media_type) assert_equal("utf-16", @response.charset) end + + test "`content type` returns header that excludes `charset` when specified `return_only_media_type_on_content_type`" do + original = ActionDispatch::Response.return_only_media_type_on_content_type + ActionDispatch::Response.return_only_media_type_on_content_type = true + + @app = lambda { |env| + if env["PATH_INFO"] == "/with_parameters" + [200, { "Content-Type" => "text/csv; header=present; charset=utf-16" }, [""]] + else + [200, { "Content-Type" => "text/csv; charset=utf-16" }, [""]] + end + } + + get "/" + assert_response :success + + assert_deprecated do + assert_equal("text/csv", @response.content_type) + end + + get "/with_parameters" + assert_response :success + + assert_deprecated do + assert_equal("text/csv; header=present", @response.content_type) + end + ensure + ActionDispatch::Response.return_only_media_type_on_content_type = original + end end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 0070d7af72..b67b1dd347 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -3810,7 +3810,6 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end private - def draw(&block) self.class.stub_controllers do |routes| routes.default_url_options = { host: "www.example.com" } @@ -4953,7 +4952,6 @@ class TestPartialDynamicPathSegments < ActionDispatch::IntegrationTest end private - def assert_params(params) assert_equal(params, request.path_parameters) end @@ -5184,7 +5182,6 @@ class TestRecognizePath < ActionDispatch::IntegrationTest end private - def recognize_path(*args) Routes.recognize_path(*args) end diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index e34426a471..b6f83f4062 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -379,7 +379,6 @@ class CookieStoreTest < ActionDispatch::IntegrationTest end private - # Overwrite get to send SessionSecret in env hash def get(path, *args) args[0] ||= {} diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index d44aa00122..1f93d594a6 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -232,7 +232,6 @@ module StaticTests end private - def assert_gzip(file_name, response) expected = File.read("#{FIXTURE_LOAD_PATH}/#{public_path}" + file_name) actual = ActiveSupport::Gzip.decompress(response.body) diff --git a/actionpack/test/dispatch/system_testing/driver_test.rb b/actionpack/test/dispatch/system_testing/driver_test.rb index 7ef306d04b..d3b16d0328 100644 --- a/actionpack/test/dispatch/system_testing/driver_test.rb +++ b/actionpack/test/dispatch/system_testing/driver_test.rb @@ -120,4 +120,17 @@ class DriverTest < ActiveSupport::TestCase driver.use end end + + test "preloads browser's driver_path" do + called = false + + original_driver_path = ::Selenium::WebDriver::Chrome::Service.driver_path + ::Selenium::WebDriver::Chrome::Service.driver_path = -> { called = true } + + ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :chrome) + + assert called + ensure + ::Selenium::WebDriver::Chrome::Service.driver_path = original_driver_path + end end diff --git a/actionpack/test/journey/route/definition/scanner_test.rb b/actionpack/test/journey/route/definition/scanner_test.rb index 092177d315..e55ed92cc8 100644 --- a/actionpack/test/journey/route/definition/scanner_test.rb +++ b/actionpack/test/journey/route/definition/scanner_test.rb @@ -66,7 +66,6 @@ module ActionDispatch end private - def assert_tokens(expected_tokens, scanner, pattern) actual_tokens = [] while token = scanner.next_token diff --git a/actionpack/test/journey/router_test.rb b/actionpack/test/journey/router_test.rb index f8d89def6a..fe0e3a975b 100644 --- a/actionpack/test/journey/router_test.rb +++ b/actionpack/test/journey/router_test.rb @@ -503,7 +503,6 @@ module ActionDispatch end private - def get(*args) ActiveSupport::Deprecation.silence do mapper.get(*args) diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index a1e94384bd..f2f57e6a36 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,11 @@ +* Add autoload for SyntaxErrorInTemplate so syntax errors are correctly raised by DebugExceptions. + + *Guilherme Mansur*, *Gannon McGibbon* + +* `RenderingHelper` supports rendering objects that `respond_to?` `:render_in` + + *Joel Hawksley*, *Natasha Umer*, *Aaron Patterson*, *Shawn Allen*, *Emily Plummer*, *Diana Mounter*, *John Hawthorn*, *Nathan Herald*, *Zaid Zawaideh*, *Zach Ahn* + * Fix `select_tag` so that it doesn't change `options` when `include_blank` is present. *Younes SERRAJ* diff --git a/actionview/app/assets/javascripts/rails-ujs/features/remote.coffee b/actionview/app/assets/javascripts/rails-ujs/features/remote.coffee index a5b61220bb..d1aeef56c7 100644 --- a/actionview/app/assets/javascripts/rails-ujs/features/remote.coffee +++ b/actionview/app/assets/javascripts/rails-ujs/features/remote.coffee @@ -88,6 +88,6 @@ Rails.preventInsignificantClick = (e) -> data = link.getAttribute('data-params') metaClick = e.metaKey or e.ctrlKey insignificantMetaClick = metaClick and method is 'GET' and not data - primaryMouseKey = e.button is 0 - e.stopImmediatePropagation() if not primaryMouseKey or insignificantMetaClick + nonPrimaryMouseClick = e.button? and e.button isnt 0 + e.stopImmediatePropagation() if nonPrimaryMouseClick or insignificantMetaClick diff --git a/actionview/lib/action_view.rb b/actionview/lib/action_view.rb index 7f85bf2a5e..11b4563548 100644 --- a/actionview/lib/action_view.rb +++ b/actionview/lib/action_view.rb @@ -77,6 +77,7 @@ module ActionView autoload :ActionViewError autoload :EncodingError autoload :TemplateError + autoload :SyntaxErrorInTemplate autoload :WrongEncodingError end end diff --git a/actionview/lib/action_view/cache_expiry.rb b/actionview/lib/action_view/cache_expiry.rb index 7cdc2e9982..27690561b7 100644 --- a/actionview/lib/action_view/cache_expiry.rb +++ b/actionview/lib/action_view/cache_expiry.rb @@ -41,7 +41,6 @@ module ActionView end private - def dirs_to_watch fs_paths = all_view_paths.grep(FileSystemResolver) fs_paths.map(&:path).sort.uniq diff --git a/actionview/lib/action_view/flows.rb b/actionview/lib/action_view/flows.rb index ff44fa6619..1609777182 100644 --- a/actionview/lib/action_view/flows.rb +++ b/actionview/lib/action_view/flows.rb @@ -68,7 +68,6 @@ module ActionView end private - def inside_fiber? Fiber.current.object_id != @root end diff --git a/actionview/lib/action_view/helpers/active_model_helper.rb b/actionview/lib/action_view/helpers/active_model_helper.rb index e41a95d2ce..e8f1d4fee5 100644 --- a/actionview/lib/action_view/helpers/active_model_helper.rb +++ b/actionview/lib/action_view/helpers/active_model_helper.rb @@ -38,7 +38,6 @@ module ActionView end private - def object_has_errors? object.respond_to?(:errors) && object.errors.respond_to?(:[]) && error_message.present? end diff --git a/actionview/lib/action_view/helpers/cache_helper.rb b/actionview/lib/action_view/helpers/cache_helper.rb index 020aebeea3..5a05f8706a 100644 --- a/actionview/lib/action_view/helpers/cache_helper.rb +++ b/actionview/lib/action_view/helpers/cache_helper.rb @@ -227,7 +227,6 @@ module ActionView end private - def fragment_name_with_digest(name, virtual_path, digest_path) virtual_path ||= @virtual_path diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb index 9d5e5eaba3..f1d9fdc678 100644 --- a/actionview/lib/action_view/helpers/date_helper.rb +++ b/actionview/lib/action_view/helpers/date_helper.rb @@ -688,7 +688,6 @@ module ActionView end private - def normalize_distance_of_time_argument_to_time(value) if value.is_a?(Numeric) Time.at(value) diff --git a/actionview/lib/action_view/helpers/number_helper.rb b/actionview/lib/action_view/helpers/number_helper.rb index 03ec7df9c1..827e0bd02c 100644 --- a/actionview/lib/action_view/helpers/number_helper.rb +++ b/actionview/lib/action_view/helpers/number_helper.rb @@ -403,7 +403,6 @@ module ActionView end private - def delegate_number_helper_method(method, number, options) return unless number options = escape_unsafe_options(options.symbolize_keys) diff --git a/actionview/lib/action_view/helpers/rendering_helper.rb b/actionview/lib/action_view/helpers/rendering_helper.rb index 7ead691113..4be23b68f3 100644 --- a/actionview/lib/action_view/helpers/rendering_helper.rb +++ b/actionview/lib/action_view/helpers/rendering_helper.rb @@ -35,7 +35,11 @@ module ActionView end end else - view_renderer.render_partial(self, partial: options, locals: locals, &block) + if options.respond_to?(:render_in) + options.render_in(self, &block) + else + view_renderer.render_partial(self, partial: options, locals: locals, &block) + end end end diff --git a/actionview/lib/action_view/helpers/tags/base.rb b/actionview/lib/action_view/helpers/tags/base.rb index 39c01f3334..4ce1f507f3 100644 --- a/actionview/lib/action_view/helpers/tags/base.rb +++ b/actionview/lib/action_view/helpers/tags/base.rb @@ -34,7 +34,6 @@ module ActionView end private - def value if @allow_method_names_outside_object object.public_send @method_name if object && object.respond_to?(@method_name) diff --git a/actionview/lib/action_view/helpers/tags/check_box.rb b/actionview/lib/action_view/helpers/tags/check_box.rb index 4327e07cae..dbf020e514 100644 --- a/actionview/lib/action_view/helpers/tags/check_box.rb +++ b/actionview/lib/action_view/helpers/tags/check_box.rb @@ -39,7 +39,6 @@ module ActionView end private - def checked?(value) case value when TrueClass, FalseClass diff --git a/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb b/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb index 455442178e..d058eb2c72 100644 --- a/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb +++ b/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb @@ -22,7 +22,6 @@ module ActionView end private - def render_component(builder) builder.check_box + builder.label end diff --git a/actionview/lib/action_view/helpers/tags/collection_helpers.rb b/actionview/lib/action_view/helpers/tags/collection_helpers.rb index e1ad11bff8..62060547de 100644 --- a/actionview/lib/action_view/helpers/tags/collection_helpers.rb +++ b/actionview/lib/action_view/helpers/tags/collection_helpers.rb @@ -37,7 +37,6 @@ module ActionView end private - def instantiate_builder(builder_class, item, value, text, html_options) builder_class.new(@template_object, @object_name, @method_name, item, sanitize_attribute_name(value), text, value, html_options) diff --git a/actionview/lib/action_view/helpers/tags/collection_radio_buttons.rb b/actionview/lib/action_view/helpers/tags/collection_radio_buttons.rb index 16d37134e5..0c3b899f53 100644 --- a/actionview/lib/action_view/helpers/tags/collection_radio_buttons.rb +++ b/actionview/lib/action_view/helpers/tags/collection_radio_buttons.rb @@ -21,7 +21,6 @@ module ActionView end private - def render_component(builder) builder.radio_button + builder.label end diff --git a/actionview/lib/action_view/helpers/tags/color_field.rb b/actionview/lib/action_view/helpers/tags/color_field.rb index 39ab1285c3..69b190809f 100644 --- a/actionview/lib/action_view/helpers/tags/color_field.rb +++ b/actionview/lib/action_view/helpers/tags/color_field.rb @@ -12,7 +12,6 @@ module ActionView end private - def validate_color_string(string) regex = /#[0-9a-fA-F]{6}/ if regex.match?(string) diff --git a/actionview/lib/action_view/helpers/tags/date_field.rb b/actionview/lib/action_view/helpers/tags/date_field.rb index b17a907651..ceaabfa99c 100644 --- a/actionview/lib/action_view/helpers/tags/date_field.rb +++ b/actionview/lib/action_view/helpers/tags/date_field.rb @@ -5,7 +5,6 @@ module ActionView module Tags # :nodoc: class DateField < DatetimeField # :nodoc: private - def format_date(value) value.try(:strftime, "%Y-%m-%d") end diff --git a/actionview/lib/action_view/helpers/tags/date_select.rb b/actionview/lib/action_view/helpers/tags/date_select.rb index fe4e3914d7..f222bf2075 100644 --- a/actionview/lib/action_view/helpers/tags/date_select.rb +++ b/actionview/lib/action_view/helpers/tags/date_select.rb @@ -23,7 +23,6 @@ module ActionView end private - def select_type self.class.select_type end diff --git a/actionview/lib/action_view/helpers/tags/datetime_field.rb b/actionview/lib/action_view/helpers/tags/datetime_field.rb index 5d9b639b1b..e2dbf408c8 100644 --- a/actionview/lib/action_view/helpers/tags/datetime_field.rb +++ b/actionview/lib/action_view/helpers/tags/datetime_field.rb @@ -14,7 +14,6 @@ module ActionView end private - def format_date(value) raise NotImplementedError end diff --git a/actionview/lib/action_view/helpers/tags/datetime_local_field.rb b/actionview/lib/action_view/helpers/tags/datetime_local_field.rb index d8f8fd00d1..8908bf9948 100644 --- a/actionview/lib/action_view/helpers/tags/datetime_local_field.rb +++ b/actionview/lib/action_view/helpers/tags/datetime_local_field.rb @@ -11,7 +11,6 @@ module ActionView end private - def format_date(value) value.try(:strftime, "%Y-%m-%dT%T") end diff --git a/actionview/lib/action_view/helpers/tags/label.rb b/actionview/lib/action_view/helpers/tags/label.rb index 02bd099784..436c4cbda3 100644 --- a/actionview/lib/action_view/helpers/tags/label.rb +++ b/actionview/lib/action_view/helpers/tags/label.rb @@ -71,7 +71,6 @@ module ActionView end private - def render_component(builder) builder.translation end diff --git a/actionview/lib/action_view/helpers/tags/month_field.rb b/actionview/lib/action_view/helpers/tags/month_field.rb index 93b2bf11f0..463866a181 100644 --- a/actionview/lib/action_view/helpers/tags/month_field.rb +++ b/actionview/lib/action_view/helpers/tags/month_field.rb @@ -5,7 +5,6 @@ module ActionView module Tags # :nodoc: class MonthField < DatetimeField # :nodoc: private - def format_date(value) value.try(:strftime, "%Y-%m") end diff --git a/actionview/lib/action_view/helpers/tags/radio_button.rb b/actionview/lib/action_view/helpers/tags/radio_button.rb index 621db2b1b5..4ce6c9f6bc 100644 --- a/actionview/lib/action_view/helpers/tags/radio_button.rb +++ b/actionview/lib/action_view/helpers/tags/radio_button.rb @@ -23,7 +23,6 @@ module ActionView end private - def checked?(value) value.to_s == @tag_value.to_s end diff --git a/actionview/lib/action_view/helpers/tags/select.rb b/actionview/lib/action_view/helpers/tags/select.rb index 790721a0b7..172e3a9226 100644 --- a/actionview/lib/action_view/helpers/tags/select.rb +++ b/actionview/lib/action_view/helpers/tags/select.rb @@ -29,7 +29,6 @@ module ActionView end private - # Grouped choices look like this: # # [nil, []] diff --git a/actionview/lib/action_view/helpers/tags/text_field.rb b/actionview/lib/action_view/helpers/tags/text_field.rb index d92967e212..c579e9e79f 100644 --- a/actionview/lib/action_view/helpers/tags/text_field.rb +++ b/actionview/lib/action_view/helpers/tags/text_field.rb @@ -24,7 +24,6 @@ module ActionView end private - def field_type self.class.field_type end diff --git a/actionview/lib/action_view/helpers/tags/time_field.rb b/actionview/lib/action_view/helpers/tags/time_field.rb index 9384a83a3e..e74c578db9 100644 --- a/actionview/lib/action_view/helpers/tags/time_field.rb +++ b/actionview/lib/action_view/helpers/tags/time_field.rb @@ -5,7 +5,6 @@ module ActionView module Tags # :nodoc: class TimeField < DatetimeField # :nodoc: private - def format_date(value) value.try(:strftime, "%T.%L") end diff --git a/actionview/lib/action_view/helpers/tags/week_field.rb b/actionview/lib/action_view/helpers/tags/week_field.rb index 572535d1d6..5a403ed91d 100644 --- a/actionview/lib/action_view/helpers/tags/week_field.rb +++ b/actionview/lib/action_view/helpers/tags/week_field.rb @@ -5,7 +5,6 @@ module ActionView module Tags # :nodoc: class WeekField < DatetimeField # :nodoc: private - def format_date(value) value.try(:strftime, "%Y-W%V") end diff --git a/actionview/lib/action_view/helpers/text_helper.rb b/actionview/lib/action_view/helpers/text_helper.rb index c282505e13..8203a43239 100644 --- a/actionview/lib/action_view/helpers/text_helper.rb +++ b/actionview/lib/action_view/helpers/text_helper.rb @@ -426,7 +426,6 @@ module ActionView end private - def next_index step_index(1) end diff --git a/actionview/lib/action_view/helpers/translation_helper.rb b/actionview/lib/action_view/helpers/translation_helper.rb index d5b0a9263f..baa337c62f 100644 --- a/actionview/lib/action_view/helpers/translation_helper.rb +++ b/actionview/lib/action_view/helpers/translation_helper.rb @@ -60,7 +60,7 @@ module ActionView def translate(key, options = {}) options = options.dup if options.has_key?(:default) - remaining_defaults = Array(options.delete(:default)).compact + remaining_defaults = Array.wrap(options.delete(:default)).compact options[:default] = remaining_defaults unless remaining_defaults.first.kind_of?(Symbol) end diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb index df83dff681..4b3a258287 100644 --- a/actionview/lib/action_view/helpers/url_helper.rb +++ b/actionview/lib/action_view/helpers/url_helper.rb @@ -253,7 +253,7 @@ module ActionView # # <input value="New" type="submit" /> # # </form>" # - # <%= button_to "New", new_articles_path %> + # <%= button_to "New", new_article_path %> # # => "<form method="post" action="/articles/new" class="button_to"> # # <input value="New" type="submit" /> # # </form>" diff --git a/actionview/lib/action_view/layouts.rb b/actionview/lib/action_view/layouts.rb index 08f66bf435..be21ff0e5d 100644 --- a/actionview/lib/action_view/layouts.rb +++ b/actionview/lib/action_view/layouts.rb @@ -224,7 +224,6 @@ module ActionView # that if no layout conditions are used, this method is not used module LayoutConditions # :nodoc: private - # Determines whether the current action has a layout definition by # checking the action name against the :only and :except conditions # set by the <tt>layout</tt> method. @@ -334,7 +333,6 @@ module ActionView end private - # If no layout is supplied, look for a template named the return # value of this method. # @@ -372,7 +370,6 @@ module ActionView end private - def _conditional_layout? true end diff --git a/actionview/lib/action_view/log_subscriber.rb b/actionview/lib/action_view/log_subscriber.rb index 227f025385..02ac0ce477 100644 --- a/actionview/lib/action_view/log_subscriber.rb +++ b/actionview/lib/action_view/log_subscriber.rb @@ -54,7 +54,6 @@ module ActionView end private - EMPTY = "" def from_rails_root(string) # :doc: string = string.sub(rails_root, EMPTY) diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb index b9a8cc129c..138ffa515b 100644 --- a/actionview/lib/action_view/lookup_context.rb +++ b/actionview/lib/action_view/lookup_context.rb @@ -112,7 +112,6 @@ module ActionView end private - def _set_detail(key, value) # :doc: @details = @details.dup if @digest_cache || @details_key @digest_cache = nil @@ -171,7 +170,6 @@ module ActionView end private - # Whenever setting view paths, makes a copy so that we can manipulate them in # instance objects as we wish. def build_view_paths(paths) diff --git a/actionview/lib/action_view/path_set.rb b/actionview/lib/action_view/path_set.rb index d54749d8e3..a6401323db 100644 --- a/actionview/lib/action_view/path_set.rb +++ b/actionview/lib/action_view/path_set.rb @@ -69,7 +69,6 @@ module ActionView #:nodoc: end private - def _find_all(path, prefixes, args) prefixes = [prefixes] if String === prefixes prefixes.each do |prefix| diff --git a/actionview/lib/action_view/record_identifier.rb b/actionview/lib/action_view/record_identifier.rb index ee39b6050d..7491dbe15a 100644 --- a/actionview/lib/action_view/record_identifier.rb +++ b/actionview/lib/action_view/record_identifier.rb @@ -95,7 +95,6 @@ module ActionView end private - # Returns a string representation of the key attribute(s) that is suitable for use in an HTML DOM id. # This can be overwritten to customize the default generated string representation if desired. # If you need to read back a key from a dom_id in order to query for the underlying database record, diff --git a/actionview/lib/action_view/renderer/abstract_renderer.rb b/actionview/lib/action_view/renderer/abstract_renderer.rb index b397c02cde..a52e5d3aca 100644 --- a/actionview/lib/action_view/renderer/abstract_renderer.rb +++ b/actionview/lib/action_view/renderer/abstract_renderer.rb @@ -74,7 +74,6 @@ module ActionView end private - def extract_details(options) # :doc: @lookup_context.registered_details.each_with_object({}) do |key, details| value = options[key] diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb index 608e417583..46bc4c9d5f 100644 --- a/actionview/lib/action_view/renderer/partial_renderer.rb +++ b/actionview/lib/action_view/renderer/partial_renderer.rb @@ -322,7 +322,6 @@ module ActionView end private - def render_collection(view, template) identifier = (template && template.identifier) || @path instrument(:collection, identifier: identifier, count: @collection.size) do |payload| diff --git a/actionview/lib/action_view/renderer/streaming_template_renderer.rb b/actionview/lib/action_view/renderer/streaming_template_renderer.rb index 19fa399e2c..08a280c7ee 100644 --- a/actionview/lib/action_view/renderer/streaming_template_renderer.rb +++ b/actionview/lib/action_view/renderer/streaming_template_renderer.rb @@ -27,7 +27,6 @@ module ActionView end private - # This is the same logging logic as in ShowExceptions middleware. def log_error(exception) logger = ActionView::Base.logger @@ -55,7 +54,6 @@ module ActionView end private - def delayed_render(buffer, template, layout, view, locals) # Wrap the given buffer in the StreamingBuffer and pass it to the # underlying template handler. Now, every time something is concatenated diff --git a/actionview/lib/action_view/renderer/template_renderer.rb b/actionview/lib/action_view/renderer/template_renderer.rb index 4cd8fc5bb2..b2d7332572 100644 --- a/actionview/lib/action_view/renderer/template_renderer.rb +++ b/actionview/lib/action_view/renderer/template_renderer.rb @@ -14,7 +14,6 @@ module ActionView end private - # Determine the template to be rendered using the given options. def determine_template(options) keys = options.has_key?(:locals) ? options[:locals].keys : [] diff --git a/actionview/lib/action_view/rendering.rb b/actionview/lib/action_view/rendering.rb index 5a06bd9da6..7247598ac2 100644 --- a/actionview/lib/action_view/rendering.rb +++ b/actionview/lib/action_view/rendering.rb @@ -104,7 +104,6 @@ module ActionView end private - # Find and render a template based on the options given. def _render_template(options) variant = options.delete(:variant) diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb index b80bf56c1b..88320dcd0d 100644 --- a/actionview/lib/action_view/template.rb +++ b/actionview/lib/action_view/template.rb @@ -264,7 +264,6 @@ module ActionView end private - # Compile a template. This method ensures a template is compiled # just once and removes the source after it is compiled. def compile!(view) diff --git a/actionview/lib/action_view/template/error.rb b/actionview/lib/action_view/template/error.rb index d0ea03e228..feceef15f9 100644 --- a/actionview/lib/action_view/template/error.rb +++ b/actionview/lib/action_view/template/error.rb @@ -114,7 +114,6 @@ module ActionView end private - def source_location if line_number "on line ##{line_number} of " diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb index b6314a5bc3..69a5a0b1b9 100644 --- a/actionview/lib/action_view/template/handlers/erb.rb +++ b/actionview/lib/action_view/template/handlers/erb.rb @@ -63,7 +63,6 @@ module ActionView end private - def valid_encoding(string, encoding) # If a magic encoding comment was found, tag the # String with this encoding. This is for a case diff --git a/actionview/lib/action_view/template/resolver.rb b/actionview/lib/action_view/template/resolver.rb index ce53eb046d..bfac4c08a0 100644 --- a/actionview/lib/action_view/template/resolver.rb +++ b/actionview/lib/action_view/template/resolver.rb @@ -93,7 +93,6 @@ module ActionView end private - def canonical_no_templates(templates) templates.empty? ? NO_TEMPLATES : templates end @@ -130,7 +129,6 @@ module ActionView end private - def _find_all(name, prefix, partial, details, key, locals) find_templates(name, prefix, partial, details, locals) end @@ -183,7 +181,6 @@ module ActionView end private - def _find_all(name, prefix, partial, details, key, locals) path = Path.build(name, prefix, partial) query(path, details, details[:formats], locals, cache: !!key) @@ -282,12 +279,8 @@ module ActionView format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last format = if format Template::Types[format]&.ref - else - if handler.respond_to?(:default_format) # default_format can return nil - handler.default_format - else - nil - end + elsif handler.respond_to?(:default_format) # default_format can return nil + handler.default_format end # Template::Types[format] and handler.default_format can return nil @@ -323,7 +316,6 @@ module ActionView end private - def find_template_paths_from_details(path, details) # Instead of checking for every possible path, as our other globs would # do, scan the directory for files with the right prefix. diff --git a/actionview/lib/action_view/test_case.rb b/actionview/lib/action_view/test_case.rb index 3a75633743..b08f8b2dfb 100644 --- a/actionview/lib/action_view/test_case.rb +++ b/actionview/lib/action_view/test_case.rb @@ -93,7 +93,6 @@ module ActionView end private - def include_helper_modules! helper(helper_class) if helper_class include _helpers @@ -163,7 +162,6 @@ module ActionView end private - # Need to experiment if this priority is the best one: rendered => output_buffer def document_root_element Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root diff --git a/actionview/lib/action_view/testing/resolvers.rb b/actionview/lib/action_view/testing/resolvers.rb index 1bedf44934..539bedcdf0 100644 --- a/actionview/lib/action_view/testing/resolvers.rb +++ b/actionview/lib/action_view/testing/resolvers.rb @@ -22,7 +22,6 @@ module ActionView #:nodoc: end private - def query(path, exts, _, locals, cache:) query = +"" EXTENSIONS.each do |ext, prefix| diff --git a/actionview/lib/action_view/unbound_template.rb b/actionview/lib/action_view/unbound_template.rb index db69b6d016..d28bab91b6 100644 --- a/actionview/lib/action_view/unbound_template.rb +++ b/actionview/lib/action_view/unbound_template.rb @@ -18,7 +18,6 @@ module ActionView end private - def build_template(locals) options = @options.merge(locals: locals) Template.new( diff --git a/actionview/lib/action_view/view_paths.rb b/actionview/lib/action_view/view_paths.rb index 3ca5aedc14..7e05f15648 100644 --- a/actionview/lib/action_view/view_paths.rb +++ b/actionview/lib/action_view/view_paths.rb @@ -29,7 +29,6 @@ module ActionView end private - # Override this method in your controller if you want to change paths prefixes for finding views. # Prefixes defined here will still be added to parents' <tt>._prefixes</tt>. def local_prefixes diff --git a/actionview/test/actionpack/abstract/abstract_controller_test.rb b/actionview/test/actionpack/abstract/abstract_controller_test.rb index eecc19d413..2de81596b5 100644 --- a/actionview/test/actionpack/abstract/abstract_controller_test.rb +++ b/actionview/test/actionpack/abstract/abstract_controller_test.rb @@ -230,6 +230,7 @@ module AbstractController class ActionMissingRespondToActionController < AbstractController::Base # No actions + private def action_missing(action_name) self.response_body = "success" @@ -242,7 +243,6 @@ module AbstractController def fail() self.response_body = "fail" end private - def method_for_action(action_name) action_name.to_s != "fail" && action_name end diff --git a/actionview/test/actionpack/abstract/layouts_test.rb b/actionview/test/actionpack/abstract/layouts_test.rb index 72d8e54bf8..15643c161d 100644 --- a/actionview/test/actionpack/abstract/layouts_test.rb +++ b/actionview/test/actionpack/abstract/layouts_test.rb @@ -140,6 +140,7 @@ module AbstractControllerTests def index render template: ActionView::Template::Text.new("Hello symbol!") end + private def hello "overwrite" diff --git a/actionview/test/actionpack/controller/render_test.rb b/actionview/test/actionpack/controller/render_test.rb index 9b1a720636..64070a9542 100644 --- a/actionview/test/actionpack/controller/render_test.rb +++ b/actionview/test/actionpack/controller/render_test.rb @@ -607,7 +607,6 @@ class TestController < ActionController::Base end private - def set_variable_for_layout @variable_for_layout = nil end diff --git a/actionview/test/activerecord/form_helper_activerecord_test.rb b/actionview/test/activerecord/form_helper_activerecord_test.rb index 34655bfe23..1b196ade6d 100644 --- a/actionview/test/activerecord/form_helper_activerecord_test.rb +++ b/actionview/test/activerecord/form_helper_activerecord_test.rb @@ -58,7 +58,6 @@ class FormHelperActiveRecordTest < ActionView::TestCase end private - def hidden_fields(method = nil) txt = +%{<input name="utf8" type="hidden" value="✓" />} diff --git a/actionview/test/lib/test_component.rb b/actionview/test/lib/test_component.rb new file mode 100644 index 0000000000..0d45d6e25f --- /dev/null +++ b/actionview/test/lib/test_component.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +class TestComponent < ActionView::Base + include ActiveModel::Validations + + validates :content, :title, presence: true + delegate :render, to: :view_context + + def initialize(title:) + @title = title + end + + # Entrypoint for rendering. Called by ActionView::RenderingHelper#render. + # + # Returns ActionView::OutputBuffer. + def render_in(view_context, &block) + self.class.compile + @view_context = view_context + @content = view_context.capture(&block) if block_given? + validate! + rendered_template + end + + def self.template + <<~'erb' + <span title="<%= title %>"><%= content %> (<%= render(plain: "Inline render") %>)</span> + erb + end + + def self.compile + @compiled ||= nil + return if @compiled + + class_eval( + "def rendered_template; @output_buffer = ActionView::OutputBuffer.new; " + + ActionView::Template::Handlers::ERB.erb_implementation.new(template, trim: true).src + + "; end" + ) + + @compiled = true + end + +private + attr_reader :content, :title, :view_context +end diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb index 91052e5ae2..83b089397c 100644 --- a/actionview/test/template/form_helper_test.rb +++ b/actionview/test/template/form_helper_test.rb @@ -1897,7 +1897,6 @@ class FormHelperTest < ActionView::TestCase def test_form_tags_do_not_call_private_properties_on_form_object obj = Class.new do private - def private_property raise "This method should not be called." end diff --git a/actionview/test/template/form_options_helper_test.rb b/actionview/test/template/form_options_helper_test.rb index c9c36917d6..d7a7b95ab3 100644 --- a/actionview/test/template/form_options_helper_test.rb +++ b/actionview/test/template/form_options_helper_test.rb @@ -1472,7 +1472,6 @@ class FormOptionsHelperTest < ActionView::TestCase end private - def dummy_posts [ Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), Post.new("Babe went home", "Babe", "To a little house", "shh!"), diff --git a/actionview/test/template/form_tag_helper_test.rb b/actionview/test/template/form_tag_helper_test.rb index 70c5ae6771..80afed96e5 100644 --- a/actionview/test/template/form_tag_helper_test.rb +++ b/actionview/test/template/form_tag_helper_test.rb @@ -803,7 +803,6 @@ class FormTagHelperTest < ActionView::TestCase end private - def root_elem(rendered_content) Nokogiri::HTML::DocumentFragment.parse(rendered_content).children.first # extract from nodeset end diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb index 2235a7816f..c82264a170 100644 --- a/actionview/test/template/render_test.rb +++ b/actionview/test/template/render_test.rb @@ -2,6 +2,8 @@ require "abstract_unit" require "controller/fake_models" +require "test_component" +require "active_model/validations" class TestController < ActionController::Base end @@ -670,6 +672,21 @@ module RenderTestCases def test_render_throws_exception_when_no_extensions_passed_to_register_template_handler_function_call assert_raises(ArgumentError) { ActionView::Template.register_template_handler CustomHandler } end + + def test_render_component + assert_equal( + %(<span title="my title">Hello, World! (Inline render)</span>), + @view.render(TestComponent.new(title: "my title")) { "Hello, World!" }.strip + ) + end + + def test_render_component_with_validation_error + error = assert_raises(ActiveModel::ValidationError) do + @view.render(TestComponent.new(title: "my title")).strip + end + + assert_match "Content can't be blank", error.message + end end class CachedViewRenderTest < ActiveSupport::TestCase diff --git a/actionview/test/template/translation_helper_test.rb b/actionview/test/template/translation_helper_test.rb index 9afdc3c68f..3475a1dada 100644 --- a/actionview/test/template/translation_helper_test.rb +++ b/actionview/test/template/translation_helper_test.rb @@ -121,6 +121,11 @@ class TranslationHelperTest < ActiveSupport::TestCase I18n.exception_handler = old_exception_handler end + def test_hash_default + default = { separator: ".", delimiter: "," } + assert_equal default, translate(:'special.number.format', default: default) + end + def test_translation_returning_an_array expected = %w(foo bar) assert_equal expected, translate(:"translations.array") diff --git a/actionview/test/ujs/public/test/data-remote.js b/actionview/test/ujs/public/test/data-remote.js index 9e41067549..16ea114f3b 100644 --- a/actionview/test/ujs/public/test/data-remote.js +++ b/actionview/test/ujs/public/test/data-remote.js @@ -82,6 +82,20 @@ asyncTest('right/mouse-wheel-clicking on a link does not fire ajaxyness', 0, fun setTimeout(function() { start() }, 13) }) +asyncTest('clicking on a link via a non-mouse Event (such as from js) works', 1, function() { + var link = $('a[data-remote]') + + link + .removeAttr('data-params') + .bindNative('ajax:beforeSend', function() { + ok(true, 'ajax should be triggered') + }) + + Rails.fire(link[0], 'click') + + setTimeout(function() { start() }, 13) +}) + asyncTest('ctrl-clicking on a link still fires ajax for non-GET links and for links with "data-params"', 2, function() { var link = $('a[data-remote]') diff --git a/activejob/lib/active_job/arguments.rb b/activejob/lib/active_job/arguments.rb index 92eb58aaaf..e08e30040b 100644 --- a/activejob/lib/active_job/arguments.rb +++ b/activejob/lib/active_job/arguments.rb @@ -45,7 +45,6 @@ module ActiveJob end private - # :nodoc: PERMITTED_TYPES = [ NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass ] # :nodoc: diff --git a/activejob/lib/active_job/serializers/date_serializer.rb b/activejob/lib/active_job/serializers/date_serializer.rb index e995d30faa..3ec587bc54 100644 --- a/activejob/lib/active_job/serializers/date_serializer.rb +++ b/activejob/lib/active_job/serializers/date_serializer.rb @@ -12,7 +12,6 @@ module ActiveJob end private - def klass Date end diff --git a/activejob/lib/active_job/serializers/date_time_serializer.rb b/activejob/lib/active_job/serializers/date_time_serializer.rb index fe780a1978..42df338b73 100644 --- a/activejob/lib/active_job/serializers/date_time_serializer.rb +++ b/activejob/lib/active_job/serializers/date_time_serializer.rb @@ -12,7 +12,6 @@ module ActiveJob end private - def klass DateTime end diff --git a/activejob/lib/active_job/serializers/duration_serializer.rb b/activejob/lib/active_job/serializers/duration_serializer.rb index 715fe27a5c..b35eaf5f60 100644 --- a/activejob/lib/active_job/serializers/duration_serializer.rb +++ b/activejob/lib/active_job/serializers/duration_serializer.rb @@ -15,7 +15,6 @@ module ActiveJob end private - def klass ActiveSupport::Duration end diff --git a/activejob/lib/active_job/serializers/object_serializer.rb b/activejob/lib/active_job/serializers/object_serializer.rb index 6d280969be..be69ddf90c 100644 --- a/activejob/lib/active_job/serializers/object_serializer.rb +++ b/activejob/lib/active_job/serializers/object_serializer.rb @@ -44,7 +44,6 @@ module ActiveJob end private - # The class of the object that will be serialized. def klass # :doc: raise NotImplementedError diff --git a/activejob/lib/active_job/serializers/symbol_serializer.rb b/activejob/lib/active_job/serializers/symbol_serializer.rb index 7e1f9553a2..3f6ee9101f 100644 --- a/activejob/lib/active_job/serializers/symbol_serializer.rb +++ b/activejob/lib/active_job/serializers/symbol_serializer.rb @@ -12,7 +12,6 @@ module ActiveJob end private - def klass Symbol end diff --git a/activejob/lib/active_job/serializers/time_serializer.rb b/activejob/lib/active_job/serializers/time_serializer.rb index fe20772f35..d385cca6bb 100644 --- a/activejob/lib/active_job/serializers/time_serializer.rb +++ b/activejob/lib/active_job/serializers/time_serializer.rb @@ -12,7 +12,6 @@ module ActiveJob end private - def klass Time end diff --git a/activejob/lib/active_job/serializers/time_with_zone_serializer.rb b/activejob/lib/active_job/serializers/time_with_zone_serializer.rb index 43017fc75b..0b29012072 100644 --- a/activejob/lib/active_job/serializers/time_with_zone_serializer.rb +++ b/activejob/lib/active_job/serializers/time_with_zone_serializer.rb @@ -12,7 +12,6 @@ module ActiveJob end private - def klass ActiveSupport::TimeWithZone end diff --git a/activejob/test/cases/serializers_test.rb b/activejob/test/cases/serializers_test.rb index bee0c061bd..2b9ba75ae0 100644 --- a/activejob/test/cases/serializers_test.rb +++ b/activejob/test/cases/serializers_test.rb @@ -26,7 +26,6 @@ class SerializersTest < ActiveSupport::TestCase end private - def klass DummyValueObject end diff --git a/activejob/test/jobs/timezone_dependent_job.rb b/activejob/test/jobs/timezone_dependent_job.rb index 41f473d533..f63ff95b95 100644 --- a/activejob/test/jobs/timezone_dependent_job.rb +++ b/activejob/test/jobs/timezone_dependent_job.rb @@ -15,7 +15,6 @@ class TimezoneDependentJob < ActiveJob::Base end private - def localtime(*args) Time.zone ? Time.zone.local(*args) : Time.utc(*args) end diff --git a/activejob/test/support/integration/test_case_helpers.rb b/activejob/test/support/integration/test_case_helpers.rb index 973ee07764..d8931a74ed 100644 --- a/activejob/test/support/integration/test_case_helpers.rb +++ b/activejob/test/support/integration/test_case_helpers.rb @@ -19,7 +19,6 @@ module TestCaseHelpers end private - def jobs_manager JobsManager.current_manager end diff --git a/activemodel/lib/active_model/attribute_assignment.rb b/activemodel/lib/active_model/attribute_assignment.rb index f0e3458f51..9bdec0dfda 100644 --- a/activemodel/lib/active_model/attribute_assignment.rb +++ b/activemodel/lib/active_model/attribute_assignment.rb @@ -38,7 +38,6 @@ module ActiveModel alias attributes= assign_attributes private - def _assign_attributes(attributes) attributes.each do |k, v| _assign_attribute(k, v) diff --git a/activemodel/lib/active_model/attribute_set.rb b/activemodel/lib/active_model/attribute_set.rb index 4679b33852..2f5437ceda 100644 --- a/activemodel/lib/active_model/attribute_set.rb +++ b/activemodel/lib/active_model/attribute_set.rb @@ -94,11 +94,9 @@ module ActiveModel end protected - attr_reader :attributes private - def initialized_attributes attributes.select { |_, attr| attr.initialized? } end diff --git a/activemodel/lib/active_model/attributes.rb b/activemodel/lib/active_model/attributes.rb index d176ea88d0..c586f52b78 100644 --- a/activemodel/lib/active_model/attributes.rb +++ b/activemodel/lib/active_model/attributes.rb @@ -42,7 +42,6 @@ module ActiveModel end private - def define_method_attribute=(name) ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method( generated_attribute_methods, name, writer: true, @@ -114,7 +113,6 @@ module ActiveModel end private - def write_attribute(attr_name, value) name = attr_name.to_s name = self.class.attribute_aliases[name] || name diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb index ea2ed7dff7..7a544395cb 100644 --- a/activemodel/lib/active_model/callbacks.rb +++ b/activemodel/lib/active_model/callbacks.rb @@ -126,7 +126,6 @@ module ActiveModel end private - def _define_before_model_callback(klass, callback) klass.define_singleton_method("before_#{callback}") do |*args, **options, &block| options.assert_valid_keys(:if, :unless, :prepend) diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index 35a587658c..aaefe00c83 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -136,7 +136,7 @@ module ActiveModel @mutations_from_database = nil end - # Clears dirty data and moves +changes+ to +previously_changed+ and + # Clears dirty data and moves +changes+ to +previous_changes+ and # +mutations_from_database+ to +mutations_before_last_save+ respectively. def changes_applied unless defined?(@attributes) diff --git a/activemodel/lib/active_model/error.rb b/activemodel/lib/active_model/error.rb index 5a1298e27f..f7267fc7bf 100644 --- a/activemodel/lib/active_model/error.rb +++ b/activemodel/lib/active_model/error.rb @@ -73,7 +73,6 @@ module ActiveModel end protected - def attributes_for_hash [@base, @attribute, @raw_type, @options] end diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index d7bcfacce3..f8ea21cf47 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -594,7 +594,6 @@ module ActiveModel end private - def normalize_arguments(attribute, type, **options) # Evaluate proc first if type.respond_to?(:call) @@ -640,7 +639,6 @@ module ActiveModel end private - def prepare_content content = @errors.to_hash content.each do |attribute, value| diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index bf23fa3c05..6a02d5dbf7 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -207,7 +207,6 @@ module ActiveModel end private - def _singularize(string) ActiveSupport::Inflector.underscore(string).tr("/", "_") end diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index c4b7b32291..168dfa0dd2 100644 --- a/activemodel/lib/active_model/serialization.rb +++ b/activemodel/lib/active_model/serialization.rb @@ -150,7 +150,6 @@ module ActiveModel end private - # Hook method defining how an attribute value should be retrieved for # serialization. By default this is assumed to be an instance named after # the attribute. Override this method in subclasses should you need to diff --git a/activemodel/lib/active_model/type/big_integer.rb b/activemodel/lib/active_model/type/big_integer.rb index 89e43bcc5f..b2c3ee50aa 100644 --- a/activemodel/lib/active_model/type/big_integer.rb +++ b/activemodel/lib/active_model/type/big_integer.rb @@ -6,7 +6,6 @@ module ActiveModel module Type class BigInteger < Integer # :nodoc: private - def max_value ::Float::INFINITY end diff --git a/activemodel/lib/active_model/type/boolean.rb b/activemodel/lib/active_model/type/boolean.rb index e64d2c793c..1214e9319b 100644 --- a/activemodel/lib/active_model/type/boolean.rb +++ b/activemodel/lib/active_model/type/boolean.rb @@ -34,7 +34,6 @@ module ActiveModel end private - def cast_value(value) if value == "" nil diff --git a/activemodel/lib/active_model/type/date.rb b/activemodel/lib/active_model/type/date.rb index c5fe926039..0e96d2c8a4 100644 --- a/activemodel/lib/active_model/type/date.rb +++ b/activemodel/lib/active_model/type/date.rb @@ -15,7 +15,6 @@ module ActiveModel end private - def cast_value(value) if value.is_a?(::String) return if value.empty? diff --git a/activemodel/lib/active_model/type/date_time.rb b/activemodel/lib/active_model/type/date_time.rb index 133410e821..ba705be9b2 100644 --- a/activemodel/lib/active_model/type/date_time.rb +++ b/activemodel/lib/active_model/type/date_time.rb @@ -14,7 +14,6 @@ module ActiveModel end private - def cast_value(value) return apply_seconds_precision(value) unless value.is_a?(::String) return if value.empty? diff --git a/activemodel/lib/active_model/type/decimal.rb b/activemodel/lib/active_model/type/decimal.rb index e8ee18c00e..6aa51ff2ac 100644 --- a/activemodel/lib/active_model/type/decimal.rb +++ b/activemodel/lib/active_model/type/decimal.rb @@ -17,7 +17,6 @@ module ActiveModel end private - def cast_value(value) casted_value = \ case value diff --git a/activemodel/lib/active_model/type/float.rb b/activemodel/lib/active_model/type/float.rb index ea1987df7c..36c7a5103c 100644 --- a/activemodel/lib/active_model/type/float.rb +++ b/activemodel/lib/active_model/type/float.rb @@ -19,7 +19,6 @@ module ActiveModel end private - def cast_value(value) case value when ::Float then value diff --git a/activemodel/lib/active_model/type/helpers/numeric.rb b/activemodel/lib/active_model/type/helpers/numeric.rb index 1d8171e25b..074316b559 100644 --- a/activemodel/lib/active_model/type/helpers/numeric.rb +++ b/activemodel/lib/active_model/type/helpers/numeric.rb @@ -24,7 +24,6 @@ module ActiveModel end private - def number_to_non_number?(old_value, new_value_before_type_cast) old_value != nil && non_numeric_string?(new_value_before_type_cast.to_s) end diff --git a/activemodel/lib/active_model/type/helpers/time_value.rb b/activemodel/lib/active_model/type/helpers/time_value.rb index dab196d653..075e906034 100644 --- a/activemodel/lib/active_model/type/helpers/time_value.rb +++ b/activemodel/lib/active_model/type/helpers/time_value.rb @@ -11,10 +11,10 @@ module ActiveModel value = apply_seconds_precision(value) if value.acts_like?(:time) - zone_conversion_method = is_utc? ? :getutc : :getlocal - - if value.respond_to?(zone_conversion_method) - value = value.send(zone_conversion_method) + if is_utc? + value = value.getutc if value.respond_to?(:getutc) && !value.utc? + else + value = value.getlocal if value.respond_to?(:getlocal) end end @@ -44,7 +44,6 @@ module ActiveModel end private - def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil) # Treat 0000-00-00 00:00:00 as nil. return if year.nil? || (year == 0 && mon == 0 && mday == 0) diff --git a/activemodel/lib/active_model/type/immutable_string.rb b/activemodel/lib/active_model/type/immutable_string.rb index 826bd7038f..18e12c54d1 100644 --- a/activemodel/lib/active_model/type/immutable_string.rb +++ b/activemodel/lib/active_model/type/immutable_string.rb @@ -17,7 +17,6 @@ module ActiveModel end private - def cast_value(value) result = \ case value diff --git a/activemodel/lib/active_model/type/string.rb b/activemodel/lib/active_model/type/string.rb index a9c9bfadb6..0d9f4a63b4 100644 --- a/activemodel/lib/active_model/type/string.rb +++ b/activemodel/lib/active_model/type/string.rb @@ -12,7 +12,6 @@ module ActiveModel end private - def cast_value(value) case value when ::String then ::String.new(value) diff --git a/activemodel/lib/active_model/type/time.rb b/activemodel/lib/active_model/type/time.rb index 61847a4ce7..f230bd4257 100644 --- a/activemodel/lib/active_model/type/time.rb +++ b/activemodel/lib/active_model/type/time.rb @@ -29,7 +29,6 @@ module ActiveModel end private - def cast_value(value) return apply_seconds_precision(value) unless value.is_a?(::String) return if value.empty? diff --git a/activemodel/lib/active_model/type/value.rb b/activemodel/lib/active_model/type/value.rb index b6914dd63c..788ded3e96 100644 --- a/activemodel/lib/active_model/type/value.rb +++ b/activemodel/lib/active_model/type/value.rb @@ -110,11 +110,10 @@ module ActiveModel [self.class, precision, scale, limit].hash end - def assert_valid_value(*) + def assert_valid_value(_) end private - # Convenience method for types which do not need separate type casting # behavior for user and database inputs. Called by Value#cast for # values except +nil+. diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index f18f9a601a..4a6b464131 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -402,7 +402,6 @@ module ActiveModel alias :read_attribute_for_validation :send private - def run_validations! _run_validate_callbacks errors.empty? diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index 6fd54270f2..1b96575a10 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -15,7 +15,6 @@ module ActiveModel end private - def setup!(klass) klass.include(LazilyDefineAttributes.new(AttributeDefinition.new(attributes))) end diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb index 887d31ae2a..7178ba99e9 100644 --- a/activemodel/lib/active_model/validations/callbacks.rb +++ b/activemodel/lib/active_model/validations/callbacks.rb @@ -112,7 +112,6 @@ module ActiveModel end private - # Overwrite run validations to include callbacks. def run_validations! _run_validation_callbacks { super } diff --git a/activemodel/lib/active_model/validations/clusivity.rb b/activemodel/lib/active_model/validations/clusivity.rb index bafb8e2106..fb9f48301c 100644 --- a/activemodel/lib/active_model/validations/clusivity.rb +++ b/activemodel/lib/active_model/validations/clusivity.rb @@ -15,7 +15,6 @@ module ActiveModel end private - def include?(record, value) members = if delimiter.respond_to?(:call) delimiter.call(record) diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index 7c3f091473..bea57415b0 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -23,7 +23,6 @@ module ActiveModel end private - def option_call(record, name) option = options[name] option.respond_to?(:call) ? option.call(record) : option diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 51e224d5cd..e7be668e9d 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -79,7 +79,6 @@ module ActiveModel end private - def is_number?(raw_value) !parse_as_number(raw_value).nil? rescue ArgumentError, TypeError diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 21c4ce0dfe..97612d474d 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -150,7 +150,6 @@ module ActiveModel end private - # When creating custom validators, it might be useful to be able to specify # additional default keys. This can be done by overwriting this method. def _validates_default_keys diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index 94d53b8dd1..3ba6acea15 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -175,7 +175,6 @@ module ActiveModel end private - def validate_each(record, attribute, value) @block.call(record, attribute, value) end diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb index 4e228032c3..e3b3b15f25 100644 --- a/activemodel/test/cases/attribute_methods_test.rb +++ b/activemodel/test/cases/attribute_methods_test.rb @@ -40,7 +40,6 @@ private end protected - def protected_method "O_o O_o" end diff --git a/activemodel/test/cases/type/date_time_test.rb b/activemodel/test/cases/type/date_time_test.rb index 74b47d1b4d..4a63eee0cf 100644 --- a/activemodel/test/cases/type/date_time_test.rb +++ b/activemodel/test/cases/type/date_time_test.rb @@ -37,7 +37,6 @@ module ActiveModel end private - def with_timezone_config(default:) old_zone_default = ::Time.zone_default ::Time.zone_default = ::Time.find_zone(default) diff --git a/activemodel/test/cases/validations/acceptance_validation_test.rb b/activemodel/test/cases/validations/acceptance_validation_test.rb index 72baf6e7a7..6bd3d292f8 100644 --- a/activemodel/test/cases/validations/acceptance_validation_test.rb +++ b/activemodel/test/cases/validations/acceptance_validation_test.rb @@ -92,7 +92,6 @@ class AcceptanceValidationTest < ActiveModel::TestCase end private - # Acceptance validator includes anonymous module into class, which cannot # be cleared, so to avoid multiple inclusions we use a named subclass which # we can remove in teardown. diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb index 16c44762cb..191af033df 100644 --- a/activemodel/test/cases/validations/numericality_validation_test.rb +++ b/activemodel/test/cases/validations/numericality_validation_test.rb @@ -310,7 +310,6 @@ class NumericalityValidationTest < ActiveModel::TestCase end private - def invalid!(values, error = nil) with_each_topic_approved_value(values) do |topic, value| assert topic.invalid?, "#{value.inspect} not rejected as a number" diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 09fdc66788..8642227a2b 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,23 @@ +* Loading the schema for a model that has no `table_name` raises a `TableNotSpecified` error. + + *Guilherme Mansur*, *Eugene Kenny* + +* PostgreSQL: Fix GROUP BY with ORDER BY virtual count attribute. + + Fixes #36022. + + *Ryuta Kamizono* + +* Make ActiveRecord `ConnectionPool.connections` method thread-safe. + + Fixes #36465. + + *Jeff Doering* + +* Add support for multiple databases to `rails db:abort_if_pending_migrations`. + + *Mark Lee* + * Fix sqlite3 collation parsing when using decimal columns. *Martin R. Schuster* diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb index 3250e29b82..aa08124158 100644 --- a/activerecord/lib/active_record/aggregations.rb +++ b/activerecord/lib/active_record/aggregations.rb @@ -14,7 +14,6 @@ module ActiveRecord end private - def clear_aggregation_cache @aggregation_cache.clear if persisted? end diff --git a/activerecord/lib/active_record/association_relation.rb b/activerecord/lib/active_record/association_relation.rb index 4c538ef2bd..de9892e48d 100644 --- a/activerecord/lib/active_record/association_relation.rb +++ b/activerecord/lib/active_record/association_relation.rb @@ -29,7 +29,6 @@ module ActiveRecord end private - def exec_queries super do |record| @association.set_inverse_instance_from_queries(record) diff --git a/activerecord/lib/active_record/associations/alias_tracker.rb b/activerecord/lib/active_record/associations/alias_tracker.rb index 272eede824..ac90ba0137 100644 --- a/activerecord/lib/active_record/associations/alias_tracker.rb +++ b/activerecord/lib/active_record/associations/alias_tracker.rb @@ -72,7 +72,6 @@ module ActiveRecord attr_reader :aliases private - def truncate(name) name.slice(0, @connection.table_alias_length - 2) end diff --git a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb index 0140aa15c8..6ad4c75fb5 100644 --- a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb @@ -46,7 +46,6 @@ module ActiveRecord::Associations::Builder # :nodoc: end private - def self.suppress_composite_primary_key(pk) pk unless pk.is_a?(Array) end @@ -73,7 +72,6 @@ module ActiveRecord::Associations::Builder # :nodoc: end private - def middle_options(join_model) middle_options = {} middle_options[:class_name] = "#{lhs_model.name}::#{join_model.name}" diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 797d647900..0db0ad8595 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -1101,7 +1101,6 @@ module ActiveRecord delegate(*delegate_methods, to: :scope) private - def find_nth_with_limit(index, limit) load_target if find_from_target? super diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 5972846940..dd2ed55279 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -37,7 +37,6 @@ module ActiveRecord end private - # Returns the number of records in this collection. # # If the association has a counter cache it gets that value. Otherwise diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb index 6b57e5093a..d4e8b364e1 100644 --- a/activerecord/lib/active_record/associations/preloader.rb +++ b/activerecord/lib/active_record/associations/preloader.rb @@ -95,7 +95,6 @@ module ActiveRecord end private - # Loads all the given data into +records+ for the +association+. def preloaders_on(association, records, scope, polymorphic_parent = false) case association diff --git a/activerecord/lib/active_record/attribute_assignment.rb b/activerecord/lib/active_record/attribute_assignment.rb index 929045f29b..acb8ba7e5a 100644 --- a/activerecord/lib/active_record/attribute_assignment.rb +++ b/activerecord/lib/active_record/attribute_assignment.rb @@ -7,7 +7,6 @@ module ActiveRecord include ActiveModel::AttributeAssignment private - def _assign_attributes(attributes) multi_parameter_attributes = {} nested_parameter_attributes = {} diff --git a/activerecord/lib/active_record/attribute_decorators.rb b/activerecord/lib/active_record/attribute_decorators.rb index 98b7805c0a..0b66043d2a 100644 --- a/activerecord/lib/active_record/attribute_decorators.rb +++ b/activerecord/lib/active_record/attribute_decorators.rb @@ -46,7 +46,6 @@ module ActiveRecord end private - def load_schema! super attribute_types.each do |name, type| @@ -75,7 +74,6 @@ module ActiveRecord end private - def decorators_for(name, type) matching(name, type).map(&:last) end diff --git a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb index 3d917ec9b1..4a7b6c60e5 100644 --- a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb +++ b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb @@ -66,7 +66,6 @@ module ActiveRecord end private - # Dispatch target for <tt>*_before_type_cast</tt> attribute methods. def attribute_before_type_cast(attribute_name) read_attribute_before_type_cast(attribute_name) diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index b4f5e6e75a..768c5f8c05 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -45,7 +45,6 @@ module ActiveRecord end private - def attribute_method?(attr_name) attr_name == "id" || super end @@ -120,7 +119,6 @@ module ActiveRecord end private - def suppress_composite_primary_key(pk) return pk unless pk.is_a?(Array) diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 0562327a9a..0f0e721b24 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -7,7 +7,6 @@ module ActiveRecord module ClassMethods # :nodoc: private - def define_method_attribute(name) ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method( generated_attribute_methods, name diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 6e0e90f39c..7bc03b9eed 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -79,7 +79,6 @@ module ActiveRecord end private - def type_incompatible_with_serialize?(type, class_name) type.is_a?(ActiveRecord::Type::Json) && class_name == ::JSON || type.respond_to?(:type_cast_array, true) && class_name == ::Array diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index 294a3dc32c..fb44232dff 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -25,7 +25,6 @@ module ActiveRecord end private - def convert_time_to_time_zone(value) return if value.nil? @@ -64,7 +63,6 @@ module ActiveRecord module ClassMethods # :nodoc: private - def inherited(subclass) super # We need to apply this decorator here, rather than on module inclusion. The closure diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index 1c63b553d0..66536a8ddf 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -11,7 +11,6 @@ module ActiveRecord module ClassMethods # :nodoc: private - def define_method_attribute=(name) ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method( generated_attribute_methods, name, writer: true, diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb index 7cf421c184..c7846dbe7a 100644 --- a/activerecord/lib/active_record/attributes.rb +++ b/activerecord/lib/active_record/attributes.rb @@ -255,7 +255,6 @@ module ActiveRecord end private - NO_DEFAULT_PROVIDED = Object.new # :nodoc: private_constant :NO_DEFAULT_PROVIDED diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 8d89e7d84a..94d8134b55 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -147,7 +147,6 @@ module ActiveRecord module ClassMethods # :nodoc: private - def define_non_cyclic_method(name, &block) return if instance_methods(false).include?(name) define_method(name) do |*args| @@ -267,7 +266,6 @@ module ActiveRecord end private - # Returns the record for an association collection that should be validated # or saved. If +autosave+ is +false+ only new records will be returned, # unless the parent is/was a new record itself. @@ -411,7 +409,7 @@ module ActiveRecord saved = record.save(validate: false) end - raise ActiveRecord::Rollback unless saved + raise(RecordInvalid.new(association.owner)) unless saved end end end diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index ef5444dfc3..a9ab9ab7a9 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -323,7 +323,6 @@ module ActiveRecord end private - def create_or_update(**) _run_save_callbacks { super } end diff --git a/activerecord/lib/active_record/coders/yaml_column.rb b/activerecord/lib/active_record/coders/yaml_column.rb index 11559141c7..881f0bcdb0 100644 --- a/activerecord/lib/active_record/coders/yaml_column.rb +++ b/activerecord/lib/active_record/coders/yaml_column.rb @@ -39,7 +39,6 @@ module ActiveRecord end private - def check_arity_of_constructor load(nil) rescue ArgumentError diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 7dd5169e43..9b3f5260f7 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -167,7 +167,6 @@ module ActiveRecord end private - def internal_poll(timeout) no_wait_poll || (timeout && wait_poll(timeout)) end @@ -330,7 +329,6 @@ module ActiveRecord end private - def spawn_thread(frequency) Thread.new(frequency) do |t| loop do @@ -359,7 +357,7 @@ module ActiveRecord include ConnectionAdapters::AbstractPool attr_accessor :automatic_reconnect, :checkout_timeout, :schema_cache - attr_reader :spec, :connections, :size, :reaper + attr_reader :spec, :size, :reaper # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification # object which describes database connection information (e.g. adapter, @@ -472,6 +470,21 @@ module ActiveRecord synchronize { @connections.any? } end + # Returns an array containing the connections currently in the pool. + # Access to the array does not require synchronization on the pool because + # the array is newly created and not retained by the pool. + # + # However; this method bypasses the ConnectionPool's thread-safe connection + # access pattern. A returned connection may be owned by another thread, + # unowned, or by happen-stance owned by the calling thread. + # + # Calling methods on a connection without ownership is subject to the + # thread-safety guarantees of the underlying method. Many of the methods + # on connection adapter classes are inherently multi-thread unsafe. + def connections + synchronize { @connections.dup } + end + # Disconnects all connections in the pool, and clears the pool. # # Raises: @@ -986,15 +999,30 @@ module ActiveRecord end end + attr_reader :prevent_writes + def initialize # These caches are keyed by spec.name (ConnectionSpecification#name). @owner_to_pool = ConnectionHandler.create_owner_to_pool + @prevent_writes = false # Backup finalizer: if the forked child never needed a pool, the above # early discard has not occurred ObjectSpace.define_finalizer self, ConnectionHandler.unowned_pool_finalizer(@owner_to_pool) end + # Prevent writing to the database regardless of role. + # + # In some cases you may want to prevent writes to the database + # even if you are on a database that can write. `while_preventing_writes` + # will prevent writes to the database for the duration of the block. + def while_preventing_writes + original, @prevent_writes = @prevent_writes, true + yield + ensure + @prevent_writes = original + end + def connection_pool_list owner_to_pool.values.compact end @@ -1112,7 +1140,6 @@ module ActiveRecord end private - def owner_to_pool @owner_to_pool[Process.pid] end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb index a7753e3e9c..6fec4dbd81 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb @@ -109,7 +109,6 @@ module ActiveRecord end private - def cache_sql(sql, name, binds) @lock.synchronize do result = diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 99e1a11f30..93273f6cf6 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -114,16 +114,16 @@ module ActiveRecord # if the value is a Time responding to usec. def quoted_date(value) if value.acts_like?(:time) - zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal - - if value.respond_to?(zone_conversion_method) - value = value.send(zone_conversion_method) + if ActiveRecord::Base.default_timezone == :utc + value = value.getutc if value.respond_to?(:getutc) && !value.utc? + else + value = value.getlocal if value.respond_to?(:getlocal) end end result = value.to_s(:db) if value.respond_to?(:usec) && value.usec > 0 - "#{result}.#{sprintf("%06d", value.usec)}" + result << "." << sprintf("%06d", value.usec) else result end @@ -155,7 +155,18 @@ module ActiveRecord # # "#{table_name}.#{column_name}" # "#{column_name}" - COLUMN_NAME = /\A(?:\w+\.)?\w+\z/i + COLUMN_NAME = / + \A + ( + (?: + # table_name.column_name | function(one or no argument) + ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\) + ) + (?:(?:\s+AS)?\s+\w+)? + ) + (?:\s*,\s*\g<1>)* + \z + /ix # Regexp for column names with order (with or without a table name prefix, # with or without various order modifiers). Matches the following: @@ -170,10 +181,15 @@ module ActiveRecord # "#{column_name} NULLS LAST" COLUMN_NAME_WITH_ORDER = / \A - (?:\w+\.)? - \w+ - (?:\s+ASC|\s+DESC)? - (?:\s+NULLS\s+(?:FIRST|LAST))? + ( + (?: + # table_name.column_name | function(one or no argument) + ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\) + ) + (?:\s+ASC|\s+DESC)? + (?:\s+NULLS\s+(?:FIRST|LAST))? + ) + (?:\s*,\s*\g<1>)* \z /ix diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb index 7d20825a75..23c993cfc3 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb @@ -19,7 +19,6 @@ module ActiveRecord to: :@conn, private: true private - def visit_AlterTable(o) sql = +"ALTER TABLE #{quote_table_name(o.name)} " sql << o.adds.map { |col| accept col }.join(" ") diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index cf57af5473..79dc98607a 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -310,6 +310,8 @@ module ActiveRecord if force drop_table(table_name, force: force, if_exists: true) + else + schema_cache.clear_data_source_cache!(table_name.to_s) end result = execute schema_creation.accept td @@ -499,6 +501,7 @@ module ActiveRecord # it can be helpful to provide these in a migration's +change+ method so it can be reverted. # In that case, +options+ and the block will be used by #create_table. def drop_table(table_name, options = {}) + schema_cache.clear_data_source_cache!(table_name.to_s) execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}" end @@ -1061,8 +1064,8 @@ module ActiveRecord options end - def dump_schema_information #:nodoc: - versions = ActiveRecord::SchemaMigration.all_versions + def dump_schema_information # :nodoc: + versions = schema_migration.all_versions insert_versions_sql(versions) if versions.any? end @@ -1078,7 +1081,7 @@ module ActiveRecord end version = version.to_i - sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name) + sm_table = quote_table_name(schema_migration.table_name) migrated = migration_context.get_all_versions versions = migration_context.migrations.map(&:version) @@ -1451,7 +1454,7 @@ module ActiveRecord end def insert_versions_sql(versions) - sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name) + sm_table = quote_table_name(schema_migration.table_name) if versions.is_a?(Array) sql = +"INSERT INTO #{sm_table} (version) VALUES\n" diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 7b6321d83b..53ce8df491 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -5,10 +5,11 @@ module ActiveRecord class TransactionState def initialize(state = nil) @state = state - @children = [] + @children = nil end def add_child(state) + @children ||= [] @children << state end @@ -41,12 +42,12 @@ module ActiveRecord end def rollback! - @children.each { |c| c.rollback! } + @children&.each { |c| c.rollback! } @state = :rolledback end def full_rollback! - @children.each { |c| c.rollback! } + @children&.each { |c| c.rollback! } @state = :fully_rolledback end @@ -75,18 +76,19 @@ module ActiveRecord class Transaction #:nodoc: attr_reader :connection, :state, :records, :savepoint_name, :isolation_level - def initialize(connection, options, run_commit_callbacks: false) + def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false) @connection = connection @state = TransactionState.new - @records = [] - @isolation_level = options[:isolation] + @records = nil + @isolation_level = isolation @materialized = false - @joinable = options.fetch(:joinable, true) + @joinable = joinable @run_commit_callbacks = run_commit_callbacks end def add_record(record) - records << record + @records ||= [] + @records << record end def materialize! @@ -98,6 +100,7 @@ module ActiveRecord end def rollback_records + return unless records ite = records.uniq(&:object_id) already_run_callbacks = {} while record = ite.shift @@ -107,16 +110,17 @@ module ActiveRecord record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks) end ensure - ite.each do |i| + ite&.each do |i| i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false) end end def before_commit_records - records.uniq.each(&:before_committed!) if @run_commit_callbacks + records.uniq.each(&:before_committed!) if records && @run_commit_callbacks end def commit_records + return unless records ite = records.uniq(&:object_id) already_run_callbacks = {} while record = ite.shift @@ -131,7 +135,7 @@ module ActiveRecord end end ensure - ite.each { |i| i.committed!(should_run_callbacks: false) } + ite&.each { |i| i.committed!(should_run_callbacks: false) } end def full_rollback?; true; end @@ -141,8 +145,8 @@ module ActiveRecord end class SavepointTransaction < Transaction - def initialize(connection, savepoint_name, parent_transaction, *args) - super(connection, *args) + def initialize(connection, savepoint_name, parent_transaction, **options) + super(connection, options) parent_transaction.state.add_child(@state) @@ -202,18 +206,29 @@ module ActiveRecord @lazy_transactions_enabled = true end - def begin_transaction(options = {}) + def begin_transaction(isolation: nil, joinable: true, _lazy: true) @connection.lock.synchronize do run_commit_callbacks = !current_transaction.joinable? transaction = if @stack.empty? - RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks) + RealTransaction.new( + @connection, + isolation: isolation, + joinable: joinable, + run_commit_callbacks: run_commit_callbacks + ) else - SavepointTransaction.new(@connection, "active_record_#{@stack.size}", @stack.last, options, - run_commit_callbacks: run_commit_callbacks) + SavepointTransaction.new( + @connection, + "active_record_#{@stack.size}", + @stack.last, + isolation: isolation, + joinable: joinable, + run_commit_callbacks: run_commit_callbacks + ) end - if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && options[:_lazy] != false + if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy @has_unmaterialized_transactions = true else transaction.materialize! @@ -274,9 +289,9 @@ module ActiveRecord end end - def within_new_transaction(options = {}) + def within_new_transaction(isolation: nil, joinable: true) @connection.lock.synchronize do - transaction = begin_transaction options + transaction = begin_transaction(isolation: isolation, joinable: joinable) yield rescue Exception => error if transaction @@ -309,7 +324,6 @@ module ActiveRecord end private - NULL_TRANSACTION = NullTransaction.new # Deallocate invalidated prepared statements outside of the transaction diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 57a8e7ad98..c0ead17b3b 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -78,7 +78,7 @@ module ActiveRecord SIMPLE_INT = /\A\d+\z/ attr_accessor :pool - attr_reader :visitor, :owner, :logger, :lock, :prepared_statements, :prevent_writes + attr_reader :visitor, :owner, :logger, :lock, :prepared_statements alias :in_use? :owner set_callback :checkin, :after, :enable_lazy_transactions! @@ -117,7 +117,6 @@ module ActiveRecord @pool = ActiveRecord::ConnectionAdapters::NullPool.new @idle_since = Concurrent.monotonic_time @quoted_column_names, @quoted_table_names = {}, {} - @prevent_writes = false @visitor = arel_visitor @statements = build_statement_pool @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new @@ -143,19 +142,7 @@ module ActiveRecord # Returns true if the connection is a replica, or if +prevent_writes+ # is set to true. def preventing_writes? - replica? || prevent_writes - end - - # Prevent writing to the database regardless of role. - # - # In some cases you may want to prevent writes to the database - # even if you are on a database that can write. `while_preventing_writes` - # will prevent writes to the database for the duration of the block. - def while_preventing_writes - original, @prevent_writes = @prevent_writes, true - yield - ensure - @prevent_writes = original + replica? || ActiveRecord::Base.connection_handler.prevent_writes end def migrations_paths # :nodoc: @@ -163,7 +150,22 @@ module ActiveRecord end def migration_context # :nodoc: - MigrationContext.new(migrations_paths) + MigrationContext.new(migrations_paths, schema_migration) + end + + def schema_migration # :nodoc: + @schema_migration ||= begin + conn = self + spec_name = conn.pool.spec.name + name = "#{spec_name}::SchemaMigration" + + Class.new(ActiveRecord::SchemaMigration) do + define_singleton_method(:name) { name } + define_singleton_method(:to_s) { name } + + self.connection_specification_name = spec_name + end + end end class Version @@ -593,7 +595,6 @@ module ActiveRecord end private - def type_map @type_map ||= Type::TypeMap.new.tap do |mapping| initialize_type_map(mapping) 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 ef33d712ad..e9ae8d159e 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -45,7 +45,6 @@ module ActiveRecord class StatementPool < ConnectionAdapters::StatementPool # :nodoc: private - def dealloc(stmt) stmt.close end @@ -289,6 +288,8 @@ module ActiveRecord # Example: # rename_table('octopuses', 'octopi') def rename_table(table_name, new_name) + schema_cache.clear_data_source_cache!(table_name.to_s) + schema_cache.clear_data_source_cache!(new_name.to_s) execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}" rename_table_indexes(table_name, new_name) end @@ -309,6 +310,7 @@ module ActiveRecord # it can be helpful to provide these in a migration's +change+ method so it can be reverted. # In that case, +options+ and the block will be used by create_table. def drop_table(table_name, options = {}) + schema_cache.clear_data_source_cache!(table_name.to_s) execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}" end @@ -513,7 +515,6 @@ module ActiveRecord end private - def initialize_type_map(m = type_map) super @@ -736,7 +737,7 @@ module ActiveRecord end.compact.join(", ") # ...and send them all in one query - execute "SET #{encoding} #{sql_mode_assignment} #{variable_assignments}" + execute("SET #{encoding} #{sql_mode_assignment} #{variable_assignments}", "SCHEMA") end def column_definitions(table_name) # :nodoc: @@ -795,7 +796,6 @@ module ActiveRecord end private - def cast_value(value) case value when true then "1" diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 279d0b9e84..2708d2756b 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -5,6 +5,8 @@ module ActiveRecord module ConnectionAdapters # An abstract definition of a column in a table. class Column + include Deduplicable + attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true @@ -76,6 +78,7 @@ module ActiveRecord def hash Column.hash ^ name.hash ^ + name.encoding.hash ^ default.hash ^ sql_type_metadata.hash ^ null.hash ^ @@ -83,6 +86,17 @@ module ActiveRecord collation.hash ^ comment.hash end + + private + def deduplicated + @name = -name + @sql_type_metadata = sql_type_metadata.deduplicate if sql_type_metadata + @default = -default if default + @default_function = -default_function if default_function + @collation = -collation if collation + @comment = -comment if comment + super + end end class NullColumn < Column diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb index 9eaf9d9a89..df26f67c6e 100644 --- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb @@ -56,7 +56,6 @@ module ActiveRecord end private - attr_reader :uri def uri_parser diff --git a/activerecord/lib/active_record/connection_adapters/deduplicable.rb b/activerecord/lib/active_record/connection_adapters/deduplicable.rb new file mode 100644 index 0000000000..fb2fd60bbc --- /dev/null +++ b/activerecord/lib/active_record/connection_adapters/deduplicable.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module ActiveRecord + module ConnectionAdapters # :nodoc: + module Deduplicable + extend ActiveSupport::Concern + + module ClassMethods + def registry + @registry ||= {} + end + + def new(*) + super.deduplicate + end + end + + def deduplicate + self.class.registry[self] ||= deduplicated + end + alias :-@ :deduplicate + + private + def deduplicated + freeze + end + end + end +end diff --git a/activerecord/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb b/activerecord/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb index 1df4dea2d8..97d74df529 100644 --- a/activerecord/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +++ b/activerecord/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb @@ -5,7 +5,7 @@ module ActiveRecord module DetermineIfPreparableVisitor attr_accessor :preparable - def accept(*) + def accept(object, collector) @preparable = true super end @@ -20,7 +20,7 @@ module ActiveRecord super end - def visit_Arel_Nodes_SqlLiteral(*) + def visit_Arel_Nodes_SqlLiteral(o, collector) @preparable = false super end diff --git a/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb b/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb index 20c3c83664..edd5ea0542 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb @@ -37,7 +37,6 @@ module ActiveRecord end private - def compute_column_widths(result) [].tap do |widths| result.columns.each_with_index do |column, i| diff --git a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb index 84354c0187..dfed5471f4 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb @@ -40,13 +40,29 @@ module ActiveRecord COLUMN_NAME_WITH_ORDER end - COLUMN_NAME = /\A(?:(`?)\w+\k<1>\.)?(`?)\w+\k<2>\z/i + COLUMN_NAME = / + \A + ( + (?: + # `table_name`.`column_name` | function(one or no argument) + ((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\) + ) + (?:(?:\s+AS)?\s+(?:\w+|`\w+`))? + ) + (?:\s*,\s*\g<1>)* + \z + /ix COLUMN_NAME_WITH_ORDER = / \A - (?:(`?)\w+\k<1>\.)? - (`?)\w+\k<2> - (?:\s+ASC|\s+DESC)? + ( + (?: + # `table_name`.`column_name` | function(one or no argument) + ((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\) + ) + (?:\s+ASC|\s+DESC)? + ) + (?:\s*,\s*\g<1>)* \z /ix diff --git a/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb b/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb index 82ed320617..0f5ab7562a 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb @@ -7,7 +7,6 @@ module ActiveRecord delegate :add_sql_comment!, :mariadb?, to: :@conn, private: true private - def visit_DropForeignKey(name) "DROP FOREIGN KEY #{name}" end diff --git a/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb b/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb index 234fb25fdf..bcd300f3db 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb @@ -41,13 +41,15 @@ module ActiveRecord case column.sql_type when /\Atimestamp\b/ :timestamp + when /\A(?:enum|set)\b/ + column.sql_type else super end end def schema_limit(column) - super unless /\A(?:tiny|medium|long)?(?:text|blob)/.match?(column.sql_type) + super unless /\A(?:enum|set|(?:tiny|medium|long)?(?:text|blob))\b/.match?(column.sql_type) end def schema_precision(column) diff --git a/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb b/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb index 9167593064..a7232fa249 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/type_metadata.rb @@ -6,9 +6,11 @@ module ActiveRecord class TypeMetadata < DelegateClass(SqlTypeMetadata) # :nodoc: undef to_yaml if method_defined?(:to_yaml) + include Deduplicable + attr_reader :extra - def initialize(type_metadata, extra: "") + def initialize(type_metadata, extra: nil) super(type_metadata) @extra = extra end @@ -25,6 +27,13 @@ module ActiveRecord __getobj__.hash ^ extra.hash end + + private + def deduplicated + __setobj__(__getobj__.deduplicate) + @extra = -extra if extra + super + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index f1ee6a2bce..53510c62c2 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -115,7 +115,6 @@ module ActiveRecord end private - def connect @connection = Mysql2::Client.new(@config) configure_connection diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb index ec25bb1e19..f1ecf6df30 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb @@ -23,6 +23,29 @@ module ActiveRecord def sql_type super.sub(/\[\]\z/, "") end + + def init_with(coder) + @serial = coder["serial"] + super + end + + def encode_with(coder) + coder["serial"] = @serial + super + end + + def ==(other) + other.is_a?(Column) && + super && + serial? == other.serial? + end + alias :eql? :== + + def hash + Column.hash ^ + super.hash ^ + serial?.hash + end end end PostgreSQLColumn = PostgreSQL::Column # :nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb index b1dfbde86e..0bbe98145a 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb @@ -77,7 +77,6 @@ module ActiveRecord end private - def type_cast_array(value, method) if value.is_a?(::Array) value.map { |item| type_cast_array(item, method) } diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb index f70f09ad95..bae34472e1 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb @@ -10,7 +10,6 @@ module ActiveRecord end private - def cast_value(value) value.to_s end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb index 7b42677101..8d4dacbd64 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb @@ -46,7 +46,6 @@ module ActiveRecord end private - HstorePair = begin quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/ unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/ diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb index 7f6adc351c..e52d4385ef 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb @@ -34,7 +34,6 @@ module ActiveRecord end private - def number_for_point(number) number.to_s.gsub(/\.0$/, "") end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb index 8c74cecc4d..e81e18ff70 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb @@ -50,7 +50,6 @@ module ActiveRecord end private - def number_for_point(number) number.to_s.gsub(/\.0$/, "") end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb index aa7701e038..d19f1f9cf8 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb @@ -58,7 +58,6 @@ module ActiveRecord end private - def type_cast_single(value) infinity?(value) ? value : @subtype.deserialize(value) end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb index 28abdbd073..74a28eef58 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb @@ -14,7 +14,6 @@ module ActiveRecord end private - def cast_value(value) casted = value.to_s casted if casted.match?(ACCEPTABLE_UUID) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb index 0ebed21717..0c800dca83 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb @@ -86,15 +86,30 @@ module ActiveRecord COLUMN_NAME_WITH_ORDER end - COLUMN_NAME = /\A(?:("?)\w+\k<1>\.)?("?)\w+\k<2>(?:::\w+)?\z/i + COLUMN_NAME = / + \A + ( + (?: + # "table_name"."column_name"::type_name | function(one or no argument)::type_name + ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)? + ) + (?:(?:\s+AS)?\s+(?:\w+|"\w+"))? + ) + (?:\s*,\s*\g<1>)* + \z + /ix COLUMN_NAME_WITH_ORDER = / \A - (?:("?)\w+\k<1>\.)? - ("?)\w+\k<2> - (?:::\w+)? - (?:\s+ASC|\s+DESC)? - (?:\s+NULLS\s+(?:FIRST|LAST))? + ( + (?: + # "table_name"."column_name"::type_name | function(one or no argument)::type_name + ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)? + ) + (?:\s+ASC|\s+DESC)? + (?:\s+NULLS\s+(?:FIRST|LAST))? + ) + (?:\s*,\s*\g<1>)* \z /ix diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb index 84643d20da..d201e40190 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb @@ -5,7 +5,6 @@ module ActiveRecord module PostgreSQL class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc: private - def extensions(stream) extensions = @connection.extensions if extensions.any? diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index 40c5e51d92..0062952667 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -55,6 +55,7 @@ module ActiveRecord end def drop_table(table_name, options = {}) # :nodoc: + schema_cache.clear_data_source_cache!(table_name.to_s) execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}" end @@ -376,6 +377,8 @@ module ActiveRecord # rename_table('octopuses', 'octopi') def rename_table(table_name, new_name) clear_cache! + schema_cache.clear_data_source_cache!(table_name.to_s) + schema_cache.clear_data_source_cache!(new_name.to_s) execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}" pk, seq = pk_and_sequence_for(new_name) if pk diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb b/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb index 8bdec623af..b7f6479357 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb @@ -7,6 +7,8 @@ module ActiveRecord class TypeMetadata < DelegateClass(SqlTypeMetadata) undef to_yaml if method_defined?(:to_yaml) + include Deduplicable + attr_reader :oid, :fmod def initialize(type_metadata, oid: nil, fmod: nil) @@ -29,6 +31,12 @@ module ActiveRecord oid.hash ^ fmod.hash end + + private + def deduplicated + __setobj__(__getobj__.deduplicate) + super + end end end PostgreSQLTypeMetadata = PostgreSQL::TypeMetadata diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb b/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb index f2f4701500..e8caeb8132 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb @@ -37,7 +37,6 @@ module ActiveRecord end protected - def parts @parts ||= [@schema, @identifier].compact end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 738805a160..6b18a12bce 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -453,7 +453,6 @@ module ActiveRecord end private - # See https://www.postgresql.org/docs/current/static/errcodes-appendix.html VALUE_LIMIT_VIOLATION = "22001" NUMERIC_VALUE_OUT_OF_RANGE = "22003" diff --git a/activerecord/lib/active_record/connection_adapters/schema_cache.rb b/activerecord/lib/active_record/connection_adapters/schema_cache.rb index dbfe1e4a34..7d54fcf9a0 100644 --- a/activerecord/lib/active_record/connection_adapters/schema_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/schema_cache.rb @@ -27,7 +27,6 @@ module ActiveRecord def encode_with(coder) coder["columns"] = @columns - coder["columns_hash"] = @columns_hash coder["primary_keys"] = @primary_keys coder["data_sources"] = @data_sources coder["indexes"] = @indexes @@ -37,12 +36,13 @@ module ActiveRecord def init_with(coder) @columns = coder["columns"] - @columns_hash = coder["columns_hash"] @primary_keys = coder["primary_keys"] @data_sources = coder["data_sources"] @indexes = coder["indexes"] || {} @version = coder["version"] @database_version = coder["database_version"] + + derive_columns_hash_and_deduplicate_values end def primary_keys(table_name) @@ -79,9 +79,7 @@ module ActiveRecord # Get the columns for a table as a hash, key is the column name # value is the column object. def columns_hash(table_name) - @columns_hash[table_name] ||= Hash[columns(table_name).map { |col| - [col.name, col] - }] + @columns_hash[table_name] ||= columns(table_name).index_by(&:name) end # Checks whether the columns hash is already cached for a table. @@ -124,15 +122,38 @@ module ActiveRecord def marshal_dump # if we get current version during initialization, it happens stack over flow. @version = connection.migration_context.current_version - [@version, @columns, @columns_hash, @primary_keys, @data_sources, @indexes, database_version] + [@version, @columns, {}, @primary_keys, @data_sources, @indexes, database_version] end def marshal_load(array) - @version, @columns, @columns_hash, @primary_keys, @data_sources, @indexes, @database_version = array - @indexes = @indexes || {} + @version, @columns, _columns_hash, @primary_keys, @data_sources, @indexes, @database_version = array + @indexes ||= {} + + derive_columns_hash_and_deduplicate_values end private + def derive_columns_hash_and_deduplicate_values + @columns = deep_deduplicate(@columns) + @columns_hash = @columns.transform_values { |columns| columns.index_by(&:name) } + @primary_keys = deep_deduplicate(@primary_keys) + @data_sources = deep_deduplicate(@data_sources) + @indexes = deep_deduplicate(@indexes) + end + + def deep_deduplicate(value) + case value + when Hash + value.transform_keys { |k| deep_deduplicate(k) }.transform_values { |v| deep_deduplicate(v) } + when Array + value.map { |i| deep_deduplicate(i) } + when String, Deduplicable + -value + else + value + end + end + def prepare_data_sources connection.data_sources.each { |source| @data_sources[source] = true } end diff --git a/activerecord/lib/active_record/connection_adapters/sql_type_metadata.rb b/activerecord/lib/active_record/connection_adapters/sql_type_metadata.rb index df28df7a7c..969867e70f 100644 --- a/activerecord/lib/active_record/connection_adapters/sql_type_metadata.rb +++ b/activerecord/lib/active_record/connection_adapters/sql_type_metadata.rb @@ -1,9 +1,13 @@ # frozen_string_literal: true +require "active_record/connection_adapters/deduplicable" + module ActiveRecord # :stopdoc: module ConnectionAdapters class SqlTypeMetadata + include Deduplicable + attr_reader :sql_type, :type, :limit, :precision, :scale def initialize(sql_type: nil, type: nil, limit: nil, precision: nil, scale: nil) @@ -32,6 +36,12 @@ module ActiveRecord precision.hash >> 1 ^ scale.hash >> 2 end + + private + def deduplicated + @sql_type = -sql_type + super + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb index 79d477cdb2..58787cf9db 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb @@ -53,20 +53,35 @@ module ActiveRecord COLUMN_NAME_WITH_ORDER end - COLUMN_NAME = /\A(?:("?)\w+\k<1>\.)?("?)\w+\k<2>\z/i + COLUMN_NAME = / + \A + ( + (?: + # "table_name"."column_name" | function(one or no argument) + ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\) + ) + (?:(?:\s+AS)?\s+(?:\w+|"\w+"))? + ) + (?:\s*,\s*\g<1>)* + \z + /ix COLUMN_NAME_WITH_ORDER = / \A - (?:("?)\w+\k<1>\.)? - ("?)\w+\k<2> - (?:\s+ASC|\s+DESC)? + ( + (?: + # "table_name"."column_name" | function(one or no argument) + ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\) + ) + (?:\s+ASC|\s+DESC)? + ) + (?:\s*,\s*\g<1>)* \z /ix private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER private - def _type_cast(value) case value when BigDecimal diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 9fc5ee3ab4..da971fdba7 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -218,6 +218,8 @@ module ActiveRecord # Example: # rename_table('octopuses', 'octopi') def rename_table(table_name, new_name) + schema_cache.clear_data_source_cache!(table_name.to_s) + schema_cache.clear_data_source_cache!(new_name.to_s) exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}" rename_table_indexes(table_name, new_name) end @@ -381,6 +383,7 @@ module ActiveRecord if from_primary_key.is_a?(Array) @definition.primary_keys from_primary_key end + columns(from).each do |column| column_name = options[:rename] ? (options[:rename][column.name] || diff --git a/activerecord/lib/active_record/connection_adapters/statement_pool.rb b/activerecord/lib/active_record/connection_adapters/statement_pool.rb index 46bd831da7..0960feed84 100644 --- a/activerecord/lib/active_record/connection_adapters/statement_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/statement_pool.rb @@ -48,7 +48,6 @@ module ActiveRecord end private - def cache @cache[Process.pid] end diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb index d472eb2e2b..c8cefa9906 100644 --- a/activerecord/lib/active_record/connection_handling.rb +++ b/activerecord/lib/active_record/connection_handling.rb @@ -256,7 +256,6 @@ module ActiveRecord :clear_all_connections!, :flush_idle_connections!, to: :connection_handler private - def swap_connection_handler(handler, &blk) # :nodoc: old_handler, ActiveRecord::Base.connection_handler = ActiveRecord::Base.connection_handler, handler yield diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index dfd33d3dd7..595ef4ee25 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -286,7 +286,6 @@ module ActiveRecord end private - def cached_find_by_statement(key, &block) cache = @find_by_statement_cache[connection.prepared_statements] cache.compute_if_absent(key) { StatementCache.create(connection, &block) } @@ -554,7 +553,6 @@ module ActiveRecord end private - # +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of # the array, and then rescues from the possible +NoMethodError+. If those elements are # +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have, diff --git a/activerecord/lib/active_record/database_configurations.rb b/activerecord/lib/active_record/database_configurations.rb index 44b5cfc738..b917f4e6b7 100644 --- a/activerecord/lib/active_record/database_configurations.rb +++ b/activerecord/lib/active_record/database_configurations.rb @@ -141,7 +141,7 @@ module ActiveRecord config_without_url.delete "url" ActiveRecord::DatabaseConfigurations::UrlConfig.new(env_name, spec_name, url, config_without_url) - elsif config["database"] || (config.size == 1 && config.values.all? { |v| v.is_a? String }) + elsif config["database"] || config["adapter"] || ENV["DATABASE_URL"] ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, spec_name, config) else config.each_pair.map do |sub_spec_name, sub_config| diff --git a/activerecord/lib/active_record/database_configurations/url_config.rb b/activerecord/lib/active_record/database_configurations/url_config.rb index e2d30ae416..e6b4acc647 100644 --- a/activerecord/lib/active_record/database_configurations/url_config.rb +++ b/activerecord/lib/active_record/database_configurations/url_config.rb @@ -56,7 +56,6 @@ module ActiveRecord end private - def build_url_hash(url) if url.nil? || /^jdbc:/.match?(url) { "url" => url } diff --git a/activerecord/lib/active_record/dynamic_matchers.rb b/activerecord/lib/active_record/dynamic_matchers.rb index 398a029068..7d9e221faa 100644 --- a/activerecord/lib/active_record/dynamic_matchers.rb +++ b/activerecord/lib/active_record/dynamic_matchers.rb @@ -69,7 +69,6 @@ module ActiveRecord end private - def body "#{finder}(#{attributes_hash})" end diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb index 60cf9818c1..c8c06375a3 100644 --- a/activerecord/lib/active_record/errors.rb +++ b/activerecord/lib/active_record/errors.rb @@ -38,6 +38,10 @@ module ActiveRecord class AdapterNotSpecified < ActiveRecordError end + # Raised when a model makes a query but it has not specified an associated table. + class TableNotSpecified < ActiveRecordError + end + # Raised when Active Record cannot find database adapter specified in # +config/database.yml+ or programmatically. class AdapterNotFound < ActiveRecordError diff --git a/activerecord/lib/active_record/explain.rb b/activerecord/lib/active_record/explain.rb index 919e96cd7a..5dca75c539 100644 --- a/activerecord/lib/active_record/explain.rb +++ b/activerecord/lib/active_record/explain.rb @@ -36,7 +36,6 @@ module ActiveRecord end private - def render_bind(attr) value = if attr.type.binary? && attr.value "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>" diff --git a/activerecord/lib/active_record/fixture_set/table_row.rb b/activerecord/lib/active_record/fixture_set/table_row.rb index cb4726f1ee..f65329f91d 100644 --- a/activerecord/lib/active_record/fixture_set/table_row.rb +++ b/activerecord/lib/active_record/fixture_set/table_row.rb @@ -48,7 +48,6 @@ module ActiveRecord end private - def model_metadata @table_rows.model_metadata end diff --git a/activerecord/lib/active_record/fixture_set/table_rows.rb b/activerecord/lib/active_record/fixture_set/table_rows.rb index 23814b6cb5..df1cd63963 100644 --- a/activerecord/lib/active_record/fixture_set/table_rows.rb +++ b/activerecord/lib/active_record/fixture_set/table_rows.rb @@ -29,7 +29,6 @@ module ActiveRecord end private - def build_table_rows_from(table_name, fixtures, config) now = config.default_timezone == :utc ? Time.now.utc : Time.now diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 327121a2a2..046ed0e95c 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -464,7 +464,6 @@ module ActiveRecord end private - def insert_class(class_names, name, klass) # We only want to deal with AR objects. if klass && klass < ActiveRecord::Base @@ -570,7 +569,6 @@ module ActiveRecord end private - def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc: fixtures_map = {} fixture_sets = fixture_files.map do |fixture_set_name| @@ -661,7 +659,6 @@ module ActiveRecord end private - def model_class=(class_name) if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any? @model_class = class_name diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index 9570bc6f86..5ca48fa18c 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -176,7 +176,6 @@ module ActiveRecord end protected - # Returns the class type of the record using the current module as a prefix. So descendants of # MyApp::Business::Account would appear as MyApp::Business::AccountSubclass. def compute_type(type_name) @@ -208,7 +207,6 @@ module ActiveRecord end private - # Called by +instantiate+ to decide which class to use for a new # record instance. For single-table inheritance, we check the record # for a +type+ column and return the corresponding class. @@ -272,7 +270,6 @@ module ActiveRecord end private - def initialize_internals_callback super ensure_proper_type diff --git a/activerecord/lib/active_record/internal_metadata.rb b/activerecord/lib/active_record/internal_metadata.rb index e6166581f1..8f3c6d0ee3 100644 --- a/activerecord/lib/active_record/internal_metadata.rb +++ b/activerecord/lib/active_record/internal_metadata.rb @@ -28,10 +28,6 @@ module ActiveRecord where(key: key).pluck(:value).first end - def table_exists? - connection.table_exists?(table_name) - end - # Creates an internal metadata table with columns +key+ and +value+ def create_table unless table_exists? diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index 6711ee9bf4..c2a083bf3b 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -156,7 +156,6 @@ module ActiveRecord end private - # We need to apply this decorator here, rather than on module inclusion. The closure # created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the # sub class being decorated. As such, changes to `lock_optimistically`, or diff --git a/activerecord/lib/active_record/middleware/database_selector.rb b/activerecord/lib/active_record/middleware/database_selector.rb index 93a1a39c3e..7374107048 100644 --- a/activerecord/lib/active_record/middleware/database_selector.rb +++ b/activerecord/lib/active_record/middleware/database_selector.rb @@ -55,7 +55,6 @@ module ActiveRecord end private - def select_database(request, &blk) context = context_klass.call(request) resolver = resolver_klass.call(context, options) diff --git a/activerecord/lib/active_record/middleware/database_selector/resolver.rb b/activerecord/lib/active_record/middleware/database_selector/resolver.rb index 80b8cd7cae..3eb1039c50 100644 --- a/activerecord/lib/active_record/middleware/database_selector/resolver.rb +++ b/activerecord/lib/active_record/middleware/database_selector/resolver.rb @@ -44,10 +44,9 @@ module ActiveRecord end private - def read_from_primary(&blk) - ActiveRecord::Base.connection.while_preventing_writes do - ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do + ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do + ActiveRecord::Base.connection_handler.while_preventing_writes do instrumenter.instrument("database_selector.active_record.read_from_primary") do yield end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index f20edbeb93..7edfec9903 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -494,9 +494,9 @@ module ActiveRecord # This migration will create the horses table for you on the way up, and # automatically figure out how to drop the table on the way down. # - # Some commands like +remove_column+ cannot be reversed. If you care to - # define how to move up and down in these cases, you should define the +up+ - # and +down+ methods as before. + # Some commands cannot be reversed. If you care to define how to move up + # and down in these cases, you should define the +up+ and +down+ methods + # as before. # # If a command cannot be reversed, an # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when @@ -568,7 +568,6 @@ module ActiveRecord end private - def connection ActiveRecord::Base.connection end @@ -885,13 +884,14 @@ module ActiveRecord def copy(destination, sources, options = {}) copied = [] + schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration FileUtils.mkdir_p(destination) unless File.exist?(destination) - destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations + destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations last = destination_migrations.last sources.each do |scope, path| - source_migrations = ActiveRecord::MigrationContext.new(path).migrations + source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations source_migrations.each do |migration| source = File.binread(migration.filename) @@ -992,7 +992,6 @@ module ActiveRecord delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration private - def migration @migration ||= load_migration end @@ -1014,10 +1013,11 @@ module ActiveRecord end class MigrationContext #:nodoc: - attr_reader :migrations_paths + attr_reader :migrations_paths, :schema_migration - def initialize(migrations_paths) + def initialize(migrations_paths, schema_migration) @migrations_paths = migrations_paths + @schema_migration = schema_migration end def migrate(target_version = nil, &block) @@ -1048,7 +1048,7 @@ module ActiveRecord migrations end - Migrator.new(:up, selected_migrations, target_version).migrate + Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate end def down(target_version = nil) @@ -1058,20 +1058,20 @@ module ActiveRecord migrations end - Migrator.new(:down, selected_migrations, target_version).migrate + Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate end def run(direction, target_version) - Migrator.new(direction, migrations, target_version).run + Migrator.new(direction, migrations, schema_migration, target_version).run end def open - Migrator.new(:up, migrations, nil) + Migrator.new(:up, migrations, schema_migration) end def get_all_versions - if SchemaMigration.table_exists? - SchemaMigration.all_versions.map(&:to_i) + if schema_migration.table_exists? + schema_migration.all_versions.map(&:to_i) else [] end @@ -1108,12 +1108,12 @@ module ActiveRecord end def migrations_status - db_list = ActiveRecord::SchemaMigration.normalized_versions + db_list = schema_migration.normalized_versions file_list = migration_files.map do |file| version, name, scope = parse_migration_filename(file) raise IllegalMigrationNameError.new(file) unless version - version = ActiveRecord::SchemaMigration.normalize_migration_number(version) + version = schema_migration.normalize_migration_number(version) status = db_list.delete(version) ? "up" : "down" [status, version, (name + scope).humanize] end.compact @@ -1153,7 +1153,7 @@ module ActiveRecord end def move(direction, steps) - migrator = Migrator.new(direction, migrations) + migrator = Migrator.new(direction, migrations, schema_migration) if current_version != 0 && !migrator.current_migration raise UnknownMigrationVersionError.new(current_version) @@ -1172,27 +1172,28 @@ module ActiveRecord end end - class Migrator #:nodoc: + class Migrator # :nodoc: class << self attr_accessor :migrations_paths # For cases where a table doesn't exist like loading from schema cache def current_version - MigrationContext.new(migrations_paths).current_version + MigrationContext.new(migrations_paths, SchemaMigration).current_version end end self.migrations_paths = ["db/migrate"] - def initialize(direction, migrations, target_version = nil) + def initialize(direction, migrations, schema_migration, target_version = nil) @direction = direction @target_version = target_version @migrated_versions = nil @migrations = migrations + @schema_migration = schema_migration validate(@migrations) - ActiveRecord::SchemaMigration.create_table + @schema_migration.create_table ActiveRecord::InternalMetadata.create_table end @@ -1246,11 +1247,10 @@ module ActiveRecord end def load_migrated - @migrated_versions = Set.new(Base.connection.migration_context.get_all_versions) + @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i)) end private - # Used for running a specific migration. def run_without_lock migration = migrations.detect { |m| m.version == @target_version } @@ -1330,10 +1330,10 @@ module ActiveRecord def record_version_state_after_migrating(version) if down? migrated.delete(version) - ActiveRecord::SchemaMigration.delete_by(version: version.to_s) + @schema_migration.delete_by(version: version.to_s) else migrated << version - ActiveRecord::SchemaMigration.create!(version: version.to_s) + @schema_migration.create!(version: version.to_s) end end diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb index efed4b0e26..67172ef395 100644 --- a/activerecord/lib/active_record/migration/command_recorder.rb +++ b/activerecord/lib/active_record/migration/command_recorder.rb @@ -118,7 +118,6 @@ module ActiveRecord end private - module StraightReversions # :nodoc: private { diff --git a/activerecord/lib/active_record/migration/join_table.rb b/activerecord/lib/active_record/migration/join_table.rb index 9abb289bb0..45169617c1 100644 --- a/activerecord/lib/active_record/migration/join_table.rb +++ b/activerecord/lib/active_record/migration/join_table.rb @@ -4,7 +4,6 @@ module ActiveRecord class Migration module JoinTable #:nodoc: private - def find_join_table_name(table_1, table_2, options = {}) options.delete(:table_name) || join_table_name(table_1, table_2) end diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 55fc58e339..18f19af6be 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -456,13 +456,11 @@ module ActiveRecord end protected - def initialize_load_schema_monitor @load_schema_monitor = Monitor.new end private - def inherited(child_class) super child_class.initialize_load_schema_monitor @@ -484,6 +482,9 @@ module ActiveRecord end def load_schema! + unless table_name + raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name=" + end @columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns) @columns_hash.each do |name, column| define_attribute( diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 8b9098df6c..cab2369b71 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -354,7 +354,6 @@ module ActiveRecord end private - # Generates a writer method for this association. Serves as a point for # accessing the objects in the association. For example, this method # could generate the following: @@ -386,7 +385,6 @@ module ActiveRecord end private - # Attribute hash keys that should not be assigned as normal attributes. # These hash keys are nested attributes implementation details. UNASSIGNABLE_KEYS = %w( id _destroy ) diff --git a/activerecord/lib/active_record/null_relation.rb b/activerecord/lib/active_record/null_relation.rb index cf0de0fdeb..bee5b5f24a 100644 --- a/activerecord/lib/active_record/null_relation.rb +++ b/activerecord/lib/active_record/null_relation.rb @@ -60,7 +60,6 @@ module ActiveRecord end private - def exec_queries @records = [].freeze end diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index b7bc4b3b8e..323b01ab2d 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -865,7 +865,6 @@ module ActiveRecord end private - # A hook to be overridden by association modules. def destroy_associations end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index befcbc8984..648fdd0dc4 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -2,6 +2,8 @@ require "active_record" +databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml + db_namespace = namespace :db do desc "Set the environment value for the database" task "environment:set" => :load_config do @@ -23,7 +25,7 @@ db_namespace = namespace :db do ActiveRecord::Tasks::DatabaseTasks.create_all end - ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| + ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name| desc "Create #{spec_name} database for current environment" task spec_name => :load_config do db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name) @@ -42,7 +44,7 @@ db_namespace = namespace :db do ActiveRecord::Tasks::DatabaseTasks.drop_all end - ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| + ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name| desc "Drop #{spec_name} database for current environment" task spec_name => [:load_config, :check_protected_environments] do db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name) @@ -101,7 +103,7 @@ db_namespace = namespace :db do end namespace :migrate do - ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| + ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name| desc "Migrate #{spec_name} database for current environment" task spec_name => :load_config do db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name) @@ -142,7 +144,7 @@ db_namespace = namespace :db do end namespace :up do - ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| + ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name| task spec_name => :load_config do raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty? @@ -176,7 +178,7 @@ db_namespace = namespace :db do end namespace :down do - ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| + ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name| task spec_name => :load_config do raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty? @@ -203,7 +205,7 @@ db_namespace = namespace :db do end namespace :status do - ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| + ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name| desc "Display status of migrations for #{spec_name} database" task spec_name => :load_config do db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name) @@ -250,7 +252,11 @@ db_namespace = namespace :db do # desc "Raises an error if there are pending migrations" task abort_if_pending_migrations: :load_config do - pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations + pending_migrations = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).flat_map do |db_config| + ActiveRecord::Base.establish_connection(db_config.config) + + ActiveRecord::Base.connection.migration_context.open.pending_migrations + end if pending_migrations.any? puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}" @@ -261,6 +267,26 @@ db_namespace = namespace :db do end end + namespace :abort_if_pending_migrations do + ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name| + # desc "Raises an error if there are pending migrations for #{spec_name} database" + task spec_name => :load_config do + db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name) + ActiveRecord::Base.establish_connection(db_config.config) + + pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations + + if pending_migrations.any? + puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}" + pending_migrations.each do |pending_migration| + puts " %4d %s" % [pending_migration.version, pending_migration.name] + end + abort %{Run `rails db:migrate:#{spec_name}` to update your database then try again.} + end + end + end + end + desc "Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)" task setup: ["db:schema:load_if_ruby", "db:structure:load_if_sql", :seed] diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index eefda2b8f4..cbfa60d4d9 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -590,7 +590,6 @@ module ActiveRecord end private - def calculate_constructable(macro, options) true end @@ -704,7 +703,6 @@ module ActiveRecord end private - def calculate_constructable(macro, options) !options[:through] end diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb index 9c579843b1..30b8edd0bd 100644 --- a/activerecord/lib/active_record/relation/batches.rb +++ b/activerecord/lib/active_record/relation/batches.rb @@ -258,7 +258,6 @@ module ActiveRecord end private - def apply_limits(relation, start, finish) relation = apply_start_limit(relation, start) if start relation = apply_finish_limit(relation, finish) if finish diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index d59331053e..2f61c05eca 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -99,7 +99,6 @@ module ActiveRecord end private - def method_missing(method, *args, &block) if @klass.respond_to?(method) @klass.generate_relation_method(method) @@ -116,7 +115,6 @@ module ActiveRecord end private - def relation_class_for(klass) klass.relation_delegate_class(self) end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 9c7ac80447..6deb9c7da8 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -346,7 +346,6 @@ module ActiveRecord end private - def offset_index offset_value || 0 end diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb index 84fe424ef0..e1735c0522 100644 --- a/activerecord/lib/active_record/relation/merger.rb +++ b/activerecord/lib/active_record/relation/merger.rb @@ -89,7 +89,6 @@ module ActiveRecord end private - def merge_preloads return if other.preload_values.empty? && other.includes_values.empty? diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 588cb130f2..87a53966e4 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1159,8 +1159,9 @@ module ActiveRecord columns.flat_map do |field| case field when Symbol - field = field.to_s - arel_column(field, &connection.method(:quote_table_name)) + arel_column(field.to_s) do |attr_name| + connection.quote_table_name(attr_name) + end when String arel_column(field, &:itself) when Proc @@ -1247,6 +1248,7 @@ module ActiveRecord end def preprocess_order_args(order_args) + order_args.reject!(&:blank?) order_args.map! do |arg| klass.sanitize_sql_for_order(arg) end @@ -1267,20 +1269,14 @@ module ActiveRecord order_args.map! do |arg| case arg when Symbol - arg = arg.to_s - arel_column(arg) { - Arel.sql(connection.quote_table_name(arg)) - }.asc + order_column(arg.to_s).asc when Hash arg.map { |field, dir| case field when Arel::Nodes::SqlLiteral field.send(dir.downcase) else - field = field.to_s - arel_column(field) { - Arel.sql(connection.quote_table_name(field)) - }.send(dir.downcase) + order_column(field.to_s).send(dir.downcase) end } else @@ -1289,6 +1285,16 @@ module ActiveRecord end.flatten! end + def order_column(field) + arel_column(field) do |attr_name| + if attr_name == "count" && !group_values.empty? + arel_attribute(attr_name) + else + Arel.sql(connection.quote_table_name(attr_name)) + end + end + end + # Checks to make sure that the arguments are not blank. Note that if some # blank-like object were initially passed into the query method, then this # method will not raise an error. diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index efc4b447aa..3f6dd50139 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -67,7 +67,6 @@ module ActiveRecord end private - def relation_with(values) result = Relation.create(klass, values: values) result.extend(*extending_values) if extending_values.any? diff --git a/activerecord/lib/active_record/relation/where_clause.rb b/activerecord/lib/active_record/relation/where_clause.rb index b91b135867..8fae380b0a 100644 --- a/activerecord/lib/active_record/relation/where_clause.rb +++ b/activerecord/lib/active_record/relation/where_clause.rb @@ -87,7 +87,6 @@ module ActiveRecord end protected - attr_reader :predicates def referenced_columns diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb index da6d10b6ec..3b615f29a3 100644 --- a/activerecord/lib/active_record/result.rb +++ b/activerecord/lib/active_record/result.rb @@ -132,7 +132,6 @@ module ActiveRecord end private - def column_type(name, type_overrides = {}) type_overrides.fetch(name) do column_types.fetch(name, Type.default_value) diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb index 5296499bad..b16cbb0f84 100644 --- a/activerecord/lib/active_record/sanitization.rb +++ b/activerecord/lib/active_record/sanitization.rb @@ -137,8 +137,7 @@ module ActiveRecord def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc: unexpected = nil args.each do |arg| - next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || - arg.to_s.split(/\s*,\s*/).all? { |part| permit.match?(part) } + next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s) (unexpected ||= []) << arg end diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index 76bf53387d..aba25fb375 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -50,7 +50,7 @@ module ActiveRecord instance_eval(&block) if info[:version].present? - ActiveRecord::SchemaMigration.create_table + connection.schema_migration.create_table connection.assume_migrated_upto_version(info[:version]) end diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index 2f7cc07221..f4b1f536b3 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -146,7 +146,11 @@ HEADER raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type) next if column.name == pk type, colspec = column_spec(column) - tbl.print " t.#{type} #{column.name.inspect}" + if type.is_a?(Symbol) + tbl.print " t.#{type} #{column.name.inspect}" + else + tbl.print " t.column #{column.name.inspect}, #{type.inspect}" + end tbl.print ", #{format_colspec(colspec)}" if colspec.present? tbl.puts end diff --git a/activerecord/lib/active_record/schema_migration.rb b/activerecord/lib/active_record/schema_migration.rb index 74547de862..dec7fee986 100644 --- a/activerecord/lib/active_record/schema_migration.rb +++ b/activerecord/lib/active_record/schema_migration.rb @@ -22,10 +22,6 @@ module ActiveRecord "#{table_name_prefix}#{schema_migrations_table_name}#{table_name_suffix}" end - def table_exists? - connection.table_exists?(table_name) - end - def create_table unless table_exists? version_options = connection.internal_string_options_for_primary_key diff --git a/activerecord/lib/active_record/scoping.rb b/activerecord/lib/active_record/scoping.rb index 35e9dcbffc..62c7988bd8 100644 --- a/activerecord/lib/active_record/scoping.rb +++ b/activerecord/lib/active_record/scoping.rb @@ -95,7 +95,6 @@ module ActiveRecord end private - def raise_invalid_scope_type!(scope_type) if !VALID_SCOPE_TYPES.include?(scope_type) raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES" diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb index 87bcfd5181..151eef362b 100644 --- a/activerecord/lib/active_record/scoping/default.rb +++ b/activerecord/lib/active_record/scoping/default.rb @@ -44,7 +44,6 @@ module ActiveRecord end private - # Use this macro in your model to set a default scope for all operations on # the model. # diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb index cd9801b7a0..7baef99e83 100644 --- a/activerecord/lib/active_record/scoping/named.rb +++ b/activerecord/lib/active_record/scoping/named.rb @@ -204,7 +204,6 @@ module ActiveRecord end private - def valid_scope_name?(name) if respond_to?(name, true) && logger logger.warn "Creating scope :#{name}. " \ diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index cf98a203bd..a78bebf764 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -141,10 +141,19 @@ module ActiveRecord end end - def for_each + def setup_initial_database_yaml return {} unless defined?(Rails) - databases = Rails.application.config.load_database_yaml + begin + Rails.application.config.load_database_yaml + rescue + $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB." + + {} + end + end + + def for_each(databases) database_configs = ActiveRecord::DatabaseConfigurations.new(databases).configs_for(env_name: Rails.env) # if this is a single database application we don't want tasks for each primary database @@ -200,9 +209,10 @@ module ActiveRecord def truncate_tables(configuration) ActiveRecord::Base.connected_to(database: { truncation: configuration }) do - table_names = ActiveRecord::Base.connection.tables + conn = ActiveRecord::Base.connection + table_names = conn.tables table_names -= [ - SchemaMigration.table_name, + conn.schema_migration.table_name, InternalMetadata.table_name ] @@ -233,7 +243,7 @@ module ActiveRecord end def migrate_status - unless ActiveRecord::SchemaMigration.table_exists? + unless ActiveRecord::Base.connection.schema_migration.table_exists? Kernel.abort "Schema migrations table does not exist yet." end @@ -328,6 +338,7 @@ module ActiveRecord def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc: require "active_record/schema_dumper" filename = dump_filename(spec_name, format) + connection = ActiveRecord::Base.connection case format when :ruby @@ -336,9 +347,9 @@ module ActiveRecord end when :sql structure_dump(configuration, filename) - if ActiveRecord::SchemaMigration.table_exists? + if connection.schema_migration.table_exists? File.open(filename, "a") do |f| - f.puts ActiveRecord::Base.connection.dump_schema_information + f.puts connection.dump_schema_information f.print "\n" end end diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb index 1c1b29b5e1..0d9917a4db 100644 --- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb @@ -67,7 +67,6 @@ module ActiveRecord end private - attr_reader :configuration def configuration_without_database diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index 8acb11f75f..626ffdfdf9 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -89,7 +89,6 @@ module ActiveRecord end private - attr_reader :configuration def encoding diff --git a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb index a82cea80ca..f67a3498b6 100644 --- a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb @@ -59,7 +59,6 @@ module ActiveRecord end private - attr_reader :configuration, :root def run_cmd(cmd, args, out) diff --git a/activerecord/lib/active_record/test_fixtures.rb b/activerecord/lib/active_record/test_fixtures.rb index 8c60d71669..1d6fef1eb9 100644 --- a/activerecord/lib/active_record/test_fixtures.rb +++ b/activerecord/lib/active_record/test_fixtures.rb @@ -179,7 +179,6 @@ module ActiveRecord end private - # Shares the writing connection pool with connections on # other handlers. # diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index a5862ae06b..c883d368b5 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -96,7 +96,6 @@ module ActiveRecord end private - def _create_record if record_timestamps current_time = current_time_from_proper_timezone diff --git a/activerecord/lib/active_record/touch_later.rb b/activerecord/lib/active_record/touch_later.rb index bc63c8d987..3981bd46ad 100644 --- a/activerecord/lib/active_record/touch_later.rb +++ b/activerecord/lib/active_record/touch_later.rb @@ -36,7 +36,6 @@ module ActiveRecord end private - def surreptitiously_touch(attrs) attrs.each { |attr| write_attribute attr, @_touch_time } clear_attribute_changes attrs diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index cbb970ac98..5113e08e8e 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -282,7 +282,6 @@ module ActiveRecord end private - def set_options_for_callbacks!(args, enforced_options = {}) options = args.extract_options!.merge!(enforced_options) args << options diff --git a/activerecord/lib/active_record/type.rb b/activerecord/lib/active_record/type.rb index 03d00006b7..4c1ef1a7e4 100644 --- a/activerecord/lib/active_record/type.rb +++ b/activerecord/lib/active_record/type.rb @@ -47,7 +47,6 @@ module ActiveRecord end private - def current_adapter_name ActiveRecord::Base.connection.adapter_name.downcase.to_sym end diff --git a/activerecord/lib/active_record/type/adapter_specific_registry.rb b/activerecord/lib/active_record/type/adapter_specific_registry.rb index b300fdfa05..c8c16635b1 100644 --- a/activerecord/lib/active_record/type/adapter_specific_registry.rb +++ b/activerecord/lib/active_record/type/adapter_specific_registry.rb @@ -11,7 +11,6 @@ module ActiveRecord end private - def registration_klass Registration end @@ -53,7 +52,6 @@ module ActiveRecord end protected - attr_reader :name, :block, :adapter, :override def priority @@ -72,7 +70,6 @@ module ActiveRecord end private - def matches_adapter?(adapter: nil, **) (self.adapter.nil? || adapter == self.adapter) end diff --git a/activerecord/lib/active_record/type/hash_lookup_type_map.rb b/activerecord/lib/active_record/type/hash_lookup_type_map.rb index db9853fbcc..b260464df5 100644 --- a/activerecord/lib/active_record/type/hash_lookup_type_map.rb +++ b/activerecord/lib/active_record/type/hash_lookup_type_map.rb @@ -16,7 +16,6 @@ module ActiveRecord end private - def perform_fetch(type, *args, &block) @mapping.fetch(type, block).call(type, *args) end diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb index 0a2f6cb9fb..a34b2fe702 100644 --- a/activerecord/lib/active_record/type/serialized.rb +++ b/activerecord/lib/active_record/type/serialized.rb @@ -56,7 +56,6 @@ module ActiveRecord end private - def default_value?(value) value == coder.load(nil) end diff --git a/activerecord/lib/active_record/type/type_map.rb b/activerecord/lib/active_record/type/type_map.rb index fc40b460f0..58f25ba075 100644 --- a/activerecord/lib/active_record/type/type_map.rb +++ b/activerecord/lib/active_record/type/type_map.rb @@ -45,7 +45,6 @@ module ActiveRecord end private - def perform_fetch(lookup_key, *args) matching_pair = @mapping.reverse_each.detect do |key, _| key === lookup_key diff --git a/activerecord/lib/active_record/type/unsigned_integer.rb b/activerecord/lib/active_record/type/unsigned_integer.rb index 4619528f81..535369e630 100644 --- a/activerecord/lib/active_record/type/unsigned_integer.rb +++ b/activerecord/lib/active_record/type/unsigned_integer.rb @@ -4,7 +4,6 @@ module ActiveRecord module Type class UnsignedInteger < ActiveModel::Type::Integer # :nodoc: private - def max_value super * 2 end diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index ca27a3f0ab..23e8d53168 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -71,7 +71,6 @@ module ActiveRecord alias_method :validate, :valid? private - def default_validation_context new_record? ? :create : :update end diff --git a/activerecord/lib/active_record/validations/associated.rb b/activerecord/lib/active_record/validations/associated.rb index 3538aeec22..dc89df4be7 100644 --- a/activerecord/lib/active_record/validations/associated.rb +++ b/activerecord/lib/active_record/validations/associated.rb @@ -10,7 +10,6 @@ module ActiveRecord end private - def valid_object?(record) (record.respond_to?(:marked_for_destruction?) && record.marked_for_destruction?) || record.valid? end diff --git a/activerecord/lib/arel.rb b/activerecord/lib/arel.rb index 361cd915cc..0fc07e1ede 100644 --- a/activerecord/lib/arel.rb +++ b/activerecord/lib/arel.rb @@ -12,7 +12,7 @@ require "arel/math" require "arel/alias_predication" require "arel/order_predications" require "arel/table" -require "arel/attributes" +require "arel/attributes/attribute" require "arel/visitors" require "arel/collectors/sql_string" diff --git a/activerecord/lib/arel/attributes.rb b/activerecord/lib/arel/attributes.rb deleted file mode 100644 index 35d586c948..0000000000 --- a/activerecord/lib/arel/attributes.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -require "arel/attributes/attribute" - -module Arel # :nodoc: all - module Attributes - ### - # Factory method to wrap a raw database +column+ to an Arel Attribute. - def self.for(column) - case column.type - when :string, :text, :binary then String - when :integer then Integer - when :float then Float - when :decimal then Decimal - when :date, :datetime, :timestamp, :time then Time - when :boolean then Boolean - else - Undefined - end - end - end -end diff --git a/activerecord/lib/arel/predications.rb b/activerecord/lib/arel/predications.rb index 7dafde4952..dece478615 100644 --- a/activerecord/lib/arel/predications.rb +++ b/activerecord/lib/arel/predications.rb @@ -221,7 +221,6 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead. end private - def grouping_any(method_id, others, *extras) nodes = others.map { |expr| send(method_id, expr, *extras) } Nodes::Grouping.new nodes.inject { |memo, node| diff --git a/activerecord/lib/arel/visitors/depth_first.rb b/activerecord/lib/arel/visitors/depth_first.rb index d696edc507..98c3f92cf1 100644 --- a/activerecord/lib/arel/visitors/depth_first.rb +++ b/activerecord/lib/arel/visitors/depth_first.rb @@ -9,8 +9,7 @@ module Arel # :nodoc: all end private - - def visit(o) + def visit(o, _ = nil) super @block.call o end diff --git a/activerecord/lib/arel/visitors/dot.rb b/activerecord/lib/arel/visitors/dot.rb index ecc386de07..c4ea07bcfe 100644 --- a/activerecord/lib/arel/visitors/dot.rb +++ b/activerecord/lib/arel/visitors/dot.rb @@ -31,7 +31,6 @@ module Arel # :nodoc: all end private - def visit_Arel_Nodes_Ordering(o) visit_edge o, "expr" end diff --git a/activerecord/lib/arel/visitors/mssql.rb b/activerecord/lib/arel/visitors/mssql.rb index 8475139870..92eb94f802 100644 --- a/activerecord/lib/arel/visitors/mssql.rb +++ b/activerecord/lib/arel/visitors/mssql.rb @@ -11,7 +11,6 @@ module Arel # :nodoc: all end private - def visit_Arel_Nodes_IsNotDistinctFrom(o, collector) right = o.right diff --git a/activerecord/lib/arel/visitors/oracle.rb b/activerecord/lib/arel/visitors/oracle.rb index f96bf65ee5..aab66301ef 100644 --- a/activerecord/lib/arel/visitors/oracle.rb +++ b/activerecord/lib/arel/visitors/oracle.rb @@ -4,7 +4,6 @@ module Arel # :nodoc: all module Visitors class Oracle < Arel::Visitors::ToSql private - def visit_Arel_Nodes_SelectStatement(o, collector) o = order_hacks(o) diff --git a/activerecord/lib/arel/visitors/oracle12.rb b/activerecord/lib/arel/visitors/oracle12.rb index 6269bc3907..36783243b5 100644 --- a/activerecord/lib/arel/visitors/oracle12.rb +++ b/activerecord/lib/arel/visitors/oracle12.rb @@ -4,7 +4,6 @@ module Arel # :nodoc: all module Visitors class Oracle12 < Arel::Visitors::ToSql private - def visit_Arel_Nodes_SelectStatement(o, collector) # Oracle does not allow LIMIT clause with select for update if o.limit && o.lock diff --git a/activerecord/lib/arel/visitors/postgresql.rb b/activerecord/lib/arel/visitors/postgresql.rb index 8296f1cdc1..d4f21ff93e 100644 --- a/activerecord/lib/arel/visitors/postgresql.rb +++ b/activerecord/lib/arel/visitors/postgresql.rb @@ -4,7 +4,6 @@ module Arel # :nodoc: all module Visitors class PostgreSQL < Arel::Visitors::ToSql private - def visit_Arel_Nodes_Matches(o, collector) op = o.case_sensitive ? " LIKE " : " ILIKE " collector = infix_value o, collector, op diff --git a/activerecord/lib/arel/visitors/sqlite.rb b/activerecord/lib/arel/visitors/sqlite.rb index af6f7e856a..62ec74ad82 100644 --- a/activerecord/lib/arel/visitors/sqlite.rb +++ b/activerecord/lib/arel/visitors/sqlite.rb @@ -4,7 +4,6 @@ module Arel # :nodoc: all module Visitors class SQLite < Arel::Visitors::ToSql private - # Locks are not supported in SQLite def visit_Arel_Nodes_Lock(o, collector) collector diff --git a/activerecord/lib/arel/visitors/to_sql.rb b/activerecord/lib/arel/visitors/to_sql.rb index 4740e6d94f..eff7a0d036 100644 --- a/activerecord/lib/arel/visitors/to_sql.rb +++ b/activerecord/lib/arel/visitors/to_sql.rb @@ -19,7 +19,6 @@ module Arel # :nodoc: all end private - def visit_Arel_Nodes_DeleteStatement(o, collector) o = prepare_delete_statement(o) @@ -52,10 +51,14 @@ module Arel # :nodoc: all def visit_Arel_Nodes_InsertStatement(o, collector) collector << "INSERT INTO " collector = visit o.relation, collector - if o.columns.any? - collector << " (#{o.columns.map { |x| - quote_column_name x.name - }.join ', '})" + + unless o.columns.empty? + collector << " (" + o.columns.each_with_index do |x, i| + collector << ", " unless i == 0 + collector << quote_column_name(x.name) + end + collector << ")" end if o.values @@ -97,22 +100,20 @@ module Arel # :nodoc: all def visit_Arel_Nodes_ValuesList(o, collector) collector << "VALUES " - len = o.rows.length - 1 - o.rows.each_with_index { |row, i| + o.rows.each_with_index do |row, i| + collector << ", " unless i == 0 collector << "(" - row_len = row.length - 1 row.each_with_index do |value, k| + collector << ", " unless k == 0 case value when Nodes::SqlLiteral, Nodes::BindParam collector = visit(value, collector) else collector << quote(value).to_s end - collector << ", " unless k == row_len end collector << ")" - collector << ", " unless i == len - } + end collector end @@ -128,11 +129,10 @@ module Arel # :nodoc: all unless o.orders.empty? collector << " ORDER BY " - len = o.orders.length - 1 - o.orders.each_with_index { |x, i| + o.orders.each_with_index do |x, i| + collector << ", " unless i == 0 collector = visit(x, collector) - collector << ", " unless len == i - } + end end visit_Arel_Nodes_SelectOptions(o, collector) @@ -506,7 +506,7 @@ module Arel # :nodoc: all def visit_Arel_Table(o, collector) if o.table_alias - collector << "#{quote_table_name o.name} #{quote_table_name o.table_alias}" + collector << quote_table_name(o.name) << " " << quote_table_name(o.table_alias) else collector << quote_table_name(o.name) end @@ -682,20 +682,13 @@ module Arel # :nodoc: all end def visit_Arel_Nodes_UnqualifiedColumn(o, collector) - collector << "#{quote_column_name o.name}" - collector + collector << quote_column_name(o.name) end def visit_Arel_Attributes_Attribute(o, collector) join_name = o.relation.table_alias || o.relation.name - collector << "#{quote_table_name join_name}.#{quote_column_name o.name}" + collector << quote_table_name(join_name) << "." << quote_column_name(o.name) end - alias :visit_Arel_Attributes_Integer :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_Float :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_Decimal :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_String :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute - alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute def literal(o, collector); collector << o.to_s; end @@ -785,14 +778,11 @@ module Arel # :nodoc: all end def inject_join(list, collector, join_str) - len = list.length - 1 - list.each_with_index.inject(collector) { |c, (x, i)| - if i == len - visit x, c - else - visit(x, c) << join_str - end - } + list.each_with_index do |x, i| + collector << join_str unless i == 0 + collector = visit(x, collector) + end + collector end def unboundable?(value) diff --git a/activerecord/lib/arel/visitors/visitor.rb b/activerecord/lib/arel/visitors/visitor.rb index 1c17184e86..d65ac820bc 100644 --- a/activerecord/lib/arel/visitors/visitor.rb +++ b/activerecord/lib/arel/visitors/visitor.rb @@ -7,12 +7,11 @@ module Arel # :nodoc: all @dispatch = get_dispatch_cache end - def accept(object, *args) - visit object, *args + def accept(object, collector = nil) + visit object, collector end private - attr_reader :dispatch def self.dispatch_cache @@ -25,9 +24,13 @@ module Arel # :nodoc: all self.class.dispatch_cache end - def visit(object, *args) + def visit(object, collector = nil) dispatch_method = dispatch[object.class] - send dispatch_method, object, *args + if collector + send dispatch_method, object, collector + else + send dispatch_method, object + end rescue NoMethodError => e raise e if respond_to?(dispatch_method, true) superklass = object.class.ancestors.find { |klass| diff --git a/activerecord/lib/arel/visitors/where_sql.rb b/activerecord/lib/arel/visitors/where_sql.rb index c6caf5e7c9..8fb299d1c8 100644 --- a/activerecord/lib/arel/visitors/where_sql.rb +++ b/activerecord/lib/arel/visitors/where_sql.rb @@ -9,7 +9,6 @@ module Arel # :nodoc: all end private - def visit_Arel_Nodes_SelectCore(o, collector) collector << "WHERE " wheres = o.wheres.map do |where| diff --git a/activerecord/lib/rails/generators/active_record/application_record/application_record_generator.rb b/activerecord/lib/rails/generators/active_record/application_record/application_record_generator.rb index 35d5664400..56b9628a92 100644 --- a/activerecord/lib/rails/generators/active_record/application_record/application_record_generator.rb +++ b/activerecord/lib/rails/generators/active_record/application_record/application_record_generator.rb @@ -13,7 +13,6 @@ module ActiveRecord end private - def application_record_file_name @application_record_file_name ||= if namespaced? diff --git a/activerecord/lib/rails/generators/active_record/migration.rb b/activerecord/lib/rails/generators/active_record/migration.rb index cbb88d571d..af753071a9 100644 --- a/activerecord/lib/rails/generators/active_record/migration.rb +++ b/activerecord/lib/rails/generators/active_record/migration.rb @@ -17,7 +17,6 @@ module ActiveRecord end private - def primary_key_type key_type = options[:primary_key_type] ", id: :#{key_type}" if key_type diff --git a/activerecord/lib/rails/generators/active_record/model/model_generator.rb b/activerecord/lib/rails/generators/active_record/model/model_generator.rb index c71bbdcab8..d4733f948f 100644 --- a/activerecord/lib/rails/generators/active_record/model/model_generator.rb +++ b/activerecord/lib/rails/generators/active_record/model/model_generator.rb @@ -35,7 +35,6 @@ module ActiveRecord hook_for :test_framework private - def attributes_with_index attributes.select { |a| !a.reference? && a.has_index? } end diff --git a/activerecord/test/active_record/connection_adapters/fake_adapter.rb b/activerecord/test/active_record/connection_adapters/fake_adapter.rb index f977b2997b..f1f457aedd 100644 --- a/activerecord/test/active_record/connection_adapters/fake_adapter.rb +++ b/activerecord/test/active_record/connection_adapters/fake_adapter.rb @@ -32,7 +32,8 @@ module ActiveRecord name.to_s, options[:default], fetch_type_metadata(sql_type), - options[:null]) + options[:null], + ) end def columns(table_name) diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index ce2ed06c1d..0bc617edbe 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -12,6 +12,7 @@ module ActiveRecord def setup @connection = ActiveRecord::Base.connection @connection.materialize_transactions + @connection_handler = ActiveRecord::Base.connection_handler end ## @@ -166,7 +167,7 @@ module ActiveRecord def test_preventing_writes_predicate assert_not_predicate @connection, :preventing_writes? - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_predicate @connection, :preventing_writes? end @@ -176,7 +177,7 @@ module ActiveRecord def test_errors_when_an_insert_query_is_called_while_preventing_writes assert_no_queries do assert_raises(ActiveRecord::ReadOnlyError) do - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do @connection.transaction do @connection.insert("INSERT INTO subscribers(nick) VALUES ('138853948594')", nil, false) end @@ -190,7 +191,7 @@ module ActiveRecord assert_no_queries do assert_raises(ActiveRecord::ReadOnlyError) do - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do @connection.transaction do @connection.update("UPDATE subscribers SET nick = '9989' WHERE nick = '138853948594'") end @@ -204,7 +205,7 @@ module ActiveRecord assert_no_queries do assert_raises(ActiveRecord::ReadOnlyError) do - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do @connection.transaction do @connection.delete("DELETE FROM subscribers WHERE nick = '138853948594'") end @@ -216,7 +217,7 @@ module ActiveRecord def test_doesnt_error_when_a_select_query_is_called_while_preventing_writes @connection.insert("INSERT INTO subscribers(nick) VALUES ('138853948594')") - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do result = @connection.select_all("SELECT subscribers.* FROM subscribers WHERE nick = '138853948594'") assert_equal 1, result.length end @@ -559,7 +560,6 @@ module ActiveRecord end private - def reset_fixtures(*fixture_names) ActiveRecord::FixtureSet.reset_cache diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index 9c6566106a..cb7461a8d5 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -197,7 +197,6 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase end private - def test_lock_free(lock_name) @connection.select_value("SELECT IS_FREE_LOCK(#{@connection.quote(lock_name)})") == 1 end diff --git a/activerecord/test/cases/adapters/mysql2/enum_test.rb b/activerecord/test/cases/adapters/mysql2/enum_test.rb index 832f5d61d1..1168b3677e 100644 --- a/activerecord/test/cases/adapters/mysql2/enum_test.rb +++ b/activerecord/test/cases/adapters/mysql2/enum_test.rb @@ -1,11 +1,20 @@ # frozen_string_literal: true require "cases/helper" +require "support/schema_dumping_helper" class Mysql2EnumTest < ActiveRecord::Mysql2TestCase + include SchemaDumpingHelper + class EnumTest < ActiveRecord::Base end + def setup + EnumTest.connection.create_table :enum_tests, id: false, force: true do |t| + t.column :enum_column, "enum('text','blob','tiny','medium','long','unsigned','bigint')" + end + end + def test_enum_limit column = EnumTest.columns_hash["enum_column"] assert_equal 8, column.limit @@ -20,4 +29,9 @@ class Mysql2EnumTest < ActiveRecord::Mysql2TestCase column = EnumTest.columns_hash["enum_column"] assert_not_predicate column, :bigint? end + + def test_schema_dumping + schema = dump_table_schema "enum_tests" + assert_match %r{t\.column "enum_column", "enum\('text','blob','tiny','medium','long','unsigned','bigint'\)"$}, schema + end end diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb index 6ade2eec24..e1f7a0b7c5 100644 --- a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb +++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb @@ -8,6 +8,7 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase def setup @conn = ActiveRecord::Base.connection + @connection_handler = ActiveRecord::Base.connection_handler end def test_exec_query_nothing_raises_with_no_result_queries @@ -148,7 +149,7 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase def test_errors_when_an_insert_query_is_called_while_preventing_writes assert_raises(ActiveRecord::ReadOnlyError) do - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do @conn.insert("INSERT INTO `engines` (`car_id`) VALUES ('138853948594')") end end @@ -158,7 +159,7 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase @conn.insert("INSERT INTO `engines` (`car_id`) VALUES ('138853948594')") assert_raises(ActiveRecord::ReadOnlyError) do - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do @conn.update("UPDATE `engines` SET `engines`.`car_id` = '9989' WHERE `engines`.`car_id` = '138853948594'") end end @@ -168,7 +169,7 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase @conn.execute("INSERT INTO `engines` (`car_id`) VALUES ('138853948594')") assert_raises(ActiveRecord::ReadOnlyError) do - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do @conn.execute("DELETE FROM `engines` where `engines`.`car_id` = '138853948594'") end end @@ -178,7 +179,7 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase @conn.execute("INSERT INTO `engines` (`car_id`) VALUES ('138853948594')") assert_raises(ActiveRecord::ReadOnlyError) do - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do @conn.execute("REPLACE INTO `engines` SET `engines`.`car_id` = '249823948'") end end @@ -187,19 +188,19 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase def test_doesnt_error_when_a_select_query_is_called_while_preventing_writes @conn.execute("INSERT INTO `engines` (`car_id`) VALUES ('138853948594')") - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_equal 1, @conn.execute("SELECT `engines`.* FROM `engines` WHERE `engines`.`car_id` = '138853948594'").entries.count end end def test_doesnt_error_when_a_show_query_is_called_while_preventing_writes - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_equal 2, @conn.execute("SHOW FULL FIELDS FROM `engines`").entries.count end end def test_doesnt_error_when_a_set_query_is_called_while_preventing_writes - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_nil @conn.execute("SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci") end end @@ -207,13 +208,12 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase def test_doesnt_error_when_a_read_query_with_leading_chars_is_called_while_preventing_writes @conn.execute("INSERT INTO `engines` (`car_id`) VALUES ('138853948594')") - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_equal 1, @conn.execute("(\n( SELECT `engines`.* FROM `engines` WHERE `engines`.`car_id` = '138853948594' ) )").entries.count end end private - def with_example_table(definition = "id int auto_increment primary key, number int, data varchar(255)", &block) super(@conn, "ex", definition, &block) end diff --git a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb index d7d9a2d732..182d5a3e58 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb @@ -40,7 +40,6 @@ class SchemaMigrationsTest < ActiveRecord::Mysql2TestCase end private - def with_encoding_utf8mb4 database_name = connection.current_database database_info = connection.select_one("SELECT * FROM information_schema.schemata WHERE schema_name = '#{database_name}'") diff --git a/activerecord/test/cases/adapters/mysql2/set_test.rb b/activerecord/test/cases/adapters/mysql2/set_test.rb new file mode 100644 index 0000000000..89107e142f --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/set_test.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require "cases/helper" +require "support/schema_dumping_helper" + +class Mysql2SetTest < ActiveRecord::Mysql2TestCase + include SchemaDumpingHelper + + class SetTest < ActiveRecord::Base + end + + def setup + SetTest.connection.create_table :set_tests, id: false, force: true do |t| + t.column :set_column, "set('text','blob','tiny','medium','long','unsigned','bigint')" + end + end + + def test_should_not_be_unsigned + column = SetTest.columns_hash["set_column"] + assert_not_predicate column, :unsigned? + end + + def test_should_not_be_bigint + column = SetTest.columns_hash["set_column"] + assert_not_predicate column, :bigint? + end + + def test_schema_dumping + schema = dump_table_schema "set_tests" + assert_match %r{t\.column "set_column", "set\('text','blob','tiny','medium','long','unsigned','bigint'\)"$}, schema + end +end diff --git a/activerecord/test/cases/adapters/mysql2/table_options_test.rb b/activerecord/test/cases/adapters/mysql2/table_options_test.rb index 1c92df940f..13cf1daa08 100644 --- a/activerecord/test/cases/adapters/mysql2/table_options_test.rb +++ b/activerecord/test/cases/adapters/mysql2/table_options_test.rb @@ -73,7 +73,7 @@ class Mysql2DefaultEngineOptionSchemaDumpTest < ActiveRecord::Mysql2TestCase end end.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], ActiveRecord::Base.connection.schema_migration).migrate output = dump_table_schema("mysql_table_options") options = %r{create_table "mysql_table_options", options: "(?<options>.*)"}.match(output)[:options] @@ -112,7 +112,7 @@ class Mysql2DefaultEngineOptionSqlOutputTest < ActiveRecord::Mysql2TestCase end end.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], ActiveRecord::Base.connection.schema_migration).migrate assert_match %r{ENGINE=InnoDB}, @log.string end diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb index 9494863a75..dcee4fd22d 100644 --- a/activerecord/test/cases/adapters/postgresql/connection_test.rb +++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb @@ -239,7 +239,6 @@ module ActiveRecord end private - def with_warning_suppression log_level = @connection.client_min_messages @connection.client_min_messages = "error" diff --git a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb index 0fd7b2c6ed..16baa8933d 100644 --- a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb +++ b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb @@ -27,20 +27,20 @@ class PostgresqlExtensionMigrationTest < ActiveRecord::PostgreSQLTestCase ActiveRecord::Base.table_name_prefix = "p_" ActiveRecord::Base.table_name_suffix = "_s" - ActiveRecord::SchemaMigration.reset_table_name + @connection.schema_migration.reset_table_name ActiveRecord::InternalMetadata.reset_table_name - ActiveRecord::SchemaMigration.delete_all rescue nil + @connection.schema_migration.delete_all rescue nil ActiveRecord::Migration.verbose = false end def teardown - ActiveRecord::SchemaMigration.delete_all rescue nil + @connection.schema_migration.delete_all rescue nil ActiveRecord::Migration.verbose = true ActiveRecord::Base.table_name_prefix = @old_table_name_prefix ActiveRecord::Base.table_name_suffix = @old_table_name_suffix - ActiveRecord::SchemaMigration.reset_table_name + @connection.schema_migration.reset_table_name ActiveRecord::InternalMetadata.reset_table_name super @@ -50,7 +50,7 @@ class PostgresqlExtensionMigrationTest < ActiveRecord::PostgreSQLTestCase @connection.disable_extension("hstore") migrations = [EnableHstore.new(nil, 1)] - ActiveRecord::Migrator.new(:up, migrations).migrate + ActiveRecord::Migrator.new(:up, migrations, ActiveRecord::Base.connection.schema_migration).migrate assert @connection.extension_enabled?("hstore"), "extension hstore should be enabled" end @@ -58,7 +58,7 @@ class PostgresqlExtensionMigrationTest < ActiveRecord::PostgreSQLTestCase @connection.enable_extension("hstore") migrations = [DisableHstore.new(nil, 1)] - ActiveRecord::Migrator.new(:up, migrations).migrate + ActiveRecord::Migrator.new(:up, migrations, ActiveRecord::Base.connection.schema_migration).migrate assert_not @connection.extension_enabled?("hstore"), "extension hstore should not be enabled" end end diff --git a/activerecord/test/cases/adapters/postgresql/geometric_test.rb b/activerecord/test/cases/adapters/postgresql/geometric_test.rb index 14c262f4ce..f312b6e23d 100644 --- a/activerecord/test/cases/adapters/postgresql/geometric_test.rb +++ b/activerecord/test/cases/adapters/postgresql/geometric_test.rb @@ -361,7 +361,6 @@ class PostgreSQLGeometricTypesTest < ActiveRecord::PostgreSQLTestCase end private - def assert_column_exists(column_name) assert connection.column_exists?(table_name, column_name) end diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb index fbd3cbf90f..68bc87eaf8 100644 --- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb +++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb @@ -13,6 +13,7 @@ module ActiveRecord def setup @connection = ActiveRecord::Base.connection + @connection_handler = ActiveRecord::Base.connection_handler end def test_bad_connection @@ -379,7 +380,7 @@ module ActiveRecord def test_errors_when_an_insert_query_is_called_while_preventing_writes with_example_table do assert_raises(ActiveRecord::ReadOnlyError) do - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do @connection.execute("INSERT INTO ex (data) VALUES ('138853948594')") end end @@ -391,7 +392,7 @@ module ActiveRecord @connection.execute("INSERT INTO ex (data) VALUES ('138853948594')") assert_raises(ActiveRecord::ReadOnlyError) do - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do @connection.execute("UPDATE ex SET data = '9989' WHERE data = '138853948594'") end end @@ -403,7 +404,7 @@ module ActiveRecord @connection.execute("INSERT INTO ex (data) VALUES ('138853948594')") assert_raises(ActiveRecord::ReadOnlyError) do - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do @connection.execute("DELETE FROM ex where data = '138853948594'") end end @@ -414,20 +415,20 @@ module ActiveRecord with_example_table do @connection.execute("INSERT INTO ex (data) VALUES ('138853948594')") - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_equal 1, @connection.execute("SELECT * FROM ex WHERE data = '138853948594'").entries.count end end end def test_doesnt_error_when_a_show_query_is_called_while_preventing_writes - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_equal 1, @connection.execute("SHOW TIME ZONE").entries.count end end def test_doesnt_error_when_a_set_query_is_called_while_preventing_writes - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_equal [], @connection.execute("SET standard_conforming_strings = on").entries end end @@ -436,14 +437,13 @@ module ActiveRecord with_example_table do @connection.execute("INSERT INTO ex (data) VALUES ('138853948594')") - @connection.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_equal 1, @connection.execute("(\n( SELECT * FROM ex WHERE data = '138853948594' ) )").entries.count end end end private - def with_example_table(definition = "id serial primary key, number integer, data character varying(255)", &block) super(@connection, "ex", definition, &block) end diff --git a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb index 96cfabf58f..a4f722c063 100644 --- a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb +++ b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb @@ -106,7 +106,6 @@ class PostgreSQLReferentialIntegrityTest < ActiveRecord::PostgreSQLTestCase end private - def assert_transaction_is_not_broken assert_equal 1, @connection.select_value("SELECT 1") end diff --git a/activerecord/test/cases/adapters/postgresql/rename_table_test.rb b/activerecord/test/cases/adapters/postgresql/rename_table_test.rb index 7eccaf4aa2..fae20de086 100644 --- a/activerecord/test/cases/adapters/postgresql/rename_table_test.rb +++ b/activerecord/test/cases/adapters/postgresql/rename_table_test.rb @@ -25,7 +25,6 @@ class PostgresqlRenameTableTest < ActiveRecord::PostgreSQLTestCase end private - def num_indices_named(name) @connection.execute(<<~SQL).values.length SELECT 1 FROM "pg_index" diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb index 336cec30ca..fe6a3deff4 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -104,7 +104,11 @@ class SchemaTest < ActiveRecord::PostgreSQLTestCase end def test_schema_names - assert_equal ["public", "test_schema", "test_schema2"], @connection.schema_names + schema_names = @connection.schema_names + assert_includes schema_names, "public" + assert_includes schema_names, "test_schema" + assert_includes schema_names, "test_schema2" + assert_includes schema_names, "hint_plan" if @connection.supports_optimizer_hints? end def test_create_schema diff --git a/activerecord/test/cases/adapters/postgresql/transaction_test.rb b/activerecord/test/cases/adapters/postgresql/transaction_test.rb index 919ff3d158..311863a418 100644 --- a/activerecord/test/cases/adapters/postgresql/transaction_test.rb +++ b/activerecord/test/cases/adapters/postgresql/transaction_test.rb @@ -177,7 +177,6 @@ module ActiveRecord end private - def with_warning_suppression log_level = ActiveRecord::Base.connection.client_min_messages ActiveRecord::Base.connection.client_min_messages = "error" diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index d2d8ea8042..a1c985fc71 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -293,14 +293,16 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase create_table("pg_uuids_4", id: :uuid) end end.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], ActiveRecord::Base.connection.schema_migration).migrate schema = dump_table_schema "pg_uuids_4" assert_match(/\bcreate_table "pg_uuids_4", id: :uuid, default: -> { "uuid_generate_v4\(\)" }/, schema) ensure drop_table "pg_uuids_4" ActiveRecord::Migration.verbose = @verbose_was + ActiveRecord::Base.connection.schema_migration.delete_all end + uses_transaction :test_schema_dumper_for_uuid_primary_key_default_in_legacy_migration end class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase @@ -341,14 +343,16 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase create_table("pg_uuids_4", id: :uuid, default: nil) end end.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], ActiveRecord::Base.connection.schema_migration).migrate schema = dump_table_schema "pg_uuids_4" assert_match(/\bcreate_table "pg_uuids_4", id: :uuid, default: nil/, schema) ensure drop_table "pg_uuids_4" ActiveRecord::Migration.verbose = @verbose_was + ActiveRecord::Base.connection.schema_migration.delete_all end + uses_transaction :test_schema_dumper_for_uuid_primary_key_with_default_nil_in_legacy_migration end class PostgresqlUUIDTestInverseOf < ActiveRecord::PostgreSQLTestCase diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index 806cfbfc00..508f7d8945 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -19,6 +19,8 @@ module ActiveRecord @conn = Base.sqlite3_connection database: ":memory:", adapter: "sqlite3", timeout: 100 + + @connection_handler = ActiveRecord::Base.connection_handler end def test_bad_connection @@ -572,7 +574,7 @@ module ActiveRecord def test_errors_when_an_insert_query_is_called_while_preventing_writes with_example_table "id int, data string" do assert_raises(ActiveRecord::ReadOnlyError) do - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do @conn.execute("INSERT INTO ex (data) VALUES ('138853948594')") end end @@ -584,7 +586,7 @@ module ActiveRecord @conn.execute("INSERT INTO ex (data) VALUES ('138853948594')") assert_raises(ActiveRecord::ReadOnlyError) do - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do @conn.execute("UPDATE ex SET data = '9989' WHERE data = '138853948594'") end end @@ -596,7 +598,7 @@ module ActiveRecord @conn.execute("INSERT INTO ex (data) VALUES ('138853948594')") assert_raises(ActiveRecord::ReadOnlyError) do - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do @conn.execute("DELETE FROM ex where data = '138853948594'") end end @@ -608,7 +610,7 @@ module ActiveRecord @conn.execute("INSERT INTO ex (data) VALUES ('138853948594')") assert_raises(ActiveRecord::ReadOnlyError) do - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do @conn.execute("REPLACE INTO ex (data) VALUES ('249823948')") end end @@ -619,7 +621,7 @@ module ActiveRecord with_example_table "id int, data string" do @conn.execute("INSERT INTO ex (data) VALUES ('138853948594')") - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_equal 1, @conn.execute("SELECT data from ex WHERE data = '138853948594'").count end end @@ -629,14 +631,13 @@ module ActiveRecord with_example_table "id int, data string" do @conn.execute("INSERT INTO ex (data) VALUES ('138853948594')") - @conn.while_preventing_writes do + @connection_handler.while_preventing_writes do assert_equal 1, @conn.execute(" SELECT data from ex WHERE data = '138853948594'").count end end end private - def assert_logged(logs) subscriber = SQLSubscriber.new subscription = ActiveSupport::Notifications.subscribe("sql.active_record", subscriber) diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb index 7aa6d089c5..2d5a06a4ac 100644 --- a/activerecord/test/cases/ar_schema_test.rb +++ b/activerecord/test/cases/ar_schema_test.rb @@ -9,7 +9,8 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase @original_verbose = ActiveRecord::Migration.verbose ActiveRecord::Migration.verbose = false @connection = ActiveRecord::Base.connection - ActiveRecord::SchemaMigration.drop_table + @schema_migration = @connection.schema_migration + @schema_migration.drop_table end teardown do @@ -18,21 +19,21 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase @connection.drop_table :nep_schema_migrations rescue nil @connection.drop_table :has_timestamps rescue nil @connection.drop_table :multiple_indexes rescue nil - ActiveRecord::SchemaMigration.delete_all rescue nil + @schema_migration.delete_all rescue nil ActiveRecord::Migration.verbose = @original_verbose end def test_has_primary_key old_primary_key_prefix_type = ActiveRecord::Base.primary_key_prefix_type ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore - assert_equal "version", ActiveRecord::SchemaMigration.primary_key + assert_equal "version", @schema_migration.primary_key - ActiveRecord::SchemaMigration.create_table - assert_difference "ActiveRecord::SchemaMigration.count", 1 do - ActiveRecord::SchemaMigration.create version: 12 + @schema_migration.create_table + assert_difference "@schema_migration.count", 1 do + @schema_migration.create version: 12 end ensure - ActiveRecord::SchemaMigration.drop_table + @schema_migration.drop_table ActiveRecord::Base.primary_key_prefix_type = old_primary_key_prefix_type end @@ -54,7 +55,7 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase def test_schema_define_with_table_name_prefix old_table_name_prefix = ActiveRecord::Base.table_name_prefix ActiveRecord::Base.table_name_prefix = "nep_" - ActiveRecord::SchemaMigration.reset_table_name + @schema_migration.reset_table_name ActiveRecord::InternalMetadata.reset_table_name ActiveRecord::Schema.define(version: 7) do create_table :fruits do |t| @@ -67,7 +68,7 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase assert_equal 7, @connection.migration_context.current_version ensure ActiveRecord::Base.table_name_prefix = old_table_name_prefix - ActiveRecord::SchemaMigration.reset_table_name + @schema_migration.reset_table_name ActiveRecord::InternalMetadata.reset_table_name end @@ -89,10 +90,10 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase end def test_normalize_version - assert_equal "118", ActiveRecord::SchemaMigration.normalize_migration_number("0000118") - assert_equal "002", ActiveRecord::SchemaMigration.normalize_migration_number("2") - assert_equal "017", ActiveRecord::SchemaMigration.normalize_migration_number("0017") - assert_equal "20131219224947", ActiveRecord::SchemaMigration.normalize_migration_number("20131219224947") + assert_equal "118", @schema_migration.normalize_migration_number("0000118") + assert_equal "002", @schema_migration.normalize_migration_number("2") + assert_equal "017", @schema_migration.normalize_migration_number("0017") + assert_equal "20131219224947", @schema_migration.normalize_migration_number("20131219224947") end def test_schema_load_with_multiple_indexes_for_column_of_different_names diff --git a/activerecord/test/cases/arel/attributes_test.rb b/activerecord/test/cases/arel/attributes_test.rb index b00af4bd29..1712633ae9 100644 --- a/activerecord/test/cases/arel/attributes_test.rb +++ b/activerecord/test/cases/arel/attributes_test.rb @@ -23,46 +23,5 @@ module Arel assert_equal 2, array.uniq.size end end - - describe "for" do - it "deals with unknown column types" do - column = Struct.new(:type).new :crazy - Attributes.for(column).must_equal Attributes::Undefined - end - - it "returns the correct constant for strings" do - [:string, :text, :binary].each do |type| - column = Struct.new(:type).new type - Attributes.for(column).must_equal Attributes::String - end - end - - it "returns the correct constant for ints" do - column = Struct.new(:type).new :integer - Attributes.for(column).must_equal Attributes::Integer - end - - it "returns the correct constant for floats" do - column = Struct.new(:type).new :float - Attributes.for(column).must_equal Attributes::Float - end - - it "returns the correct constant for decimals" do - column = Struct.new(:type).new :decimal - Attributes.for(column).must_equal Attributes::Decimal - end - - it "returns the correct constant for boolean" do - column = Struct.new(:type).new :boolean - Attributes.for(column).must_equal Attributes::Boolean - end - - it "returns the correct constant for time" do - [:date, :datetime, :timestamp, :time].each do |type| - column = Struct.new(:type).new type - Attributes.for(column).must_equal Attributes::Time - end - end - end end end diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb index 849939de75..9be21b23db 100644 --- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb +++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb @@ -14,6 +14,7 @@ module Remembered included do after_create :remember + private def remember; self.class.remembered << self; end end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 38723b6c19..cb46f9e053 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -968,14 +968,14 @@ class EagerAssociationTest < ActiveRecord::TestCase posts(:thinking, :sti_comments), Post.all.merge!( includes: [:author, :comments], where: { "authors.name" => "David" }, - order: Arel.sql("UPPER(posts.title)"), limit: 2, offset: 1 + order: "UPPER(posts.title)", limit: 2, offset: 1 ).to_a ) assert_equal( posts(:sti_post_and_comments, :sti_comments), Post.all.merge!( includes: [:author, :comments], where: { "authors.name" => "David" }, - order: Arel.sql("UPPER(posts.title) DESC"), limit: 2, offset: 1 + order: "UPPER(posts.title) DESC", limit: 2, offset: 1 ).to_a ) end @@ -985,14 +985,14 @@ class EagerAssociationTest < ActiveRecord::TestCase posts(:thinking, :sti_comments), Post.all.merge!( includes: [:author, :comments], where: { "authors.name" => "David" }, - order: [Arel.sql("UPPER(posts.title)"), "posts.id"], limit: 2, offset: 1 + order: ["UPPER(posts.title)", "posts.id"], limit: 2, offset: 1 ).to_a ) assert_equal( posts(:sti_post_and_comments, :sti_comments), Post.all.merge!( includes: [:author, :comments], where: { "authors.name" => "David" }, - order: [Arel.sql("UPPER(posts.title) DESC"), "posts.id"], limit: 2, offset: 1 + order: ["UPPER(posts.title) DESC", "posts.id"], limit: 2, offset: 1 ).to_a ) end diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb index 5e6e3e8ec4..604a52655c 100644 --- a/activerecord/test/cases/associations/extension_test.rb +++ b/activerecord/test/cases/associations/extension_test.rb @@ -87,7 +87,6 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase end private - def extend!(model) ActiveRecord::Associations::Builder::HasMany.send(:define_extensions, model, :association_name) { } end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index fe7e5dc559..6c54c2f1cd 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -2938,7 +2938,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end private - def force_signal37_to_load_all_clients_of_firm companies(:first_firm).clients_of_firm.load_target end diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index 35da74102d..8d74ae3961 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -626,7 +626,6 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase end private - def assert_includes_and_joins_equal(query, expected, association) actual = assert_queries(1) { query.joins(association).to_a.uniq } assert_equal expected, actual diff --git a/activerecord/test/cases/associations/required_test.rb b/activerecord/test/cases/associations/required_test.rb index c7a78e6bc4..db7f945a36 100644 --- a/activerecord/test/cases/associations/required_test.rb +++ b/activerecord/test/cases/associations/required_test.rb @@ -117,7 +117,6 @@ class RequiredAssociationsTest < ActiveRecord::TestCase end private - def subclass_of(klass, &block) subclass = Class.new(klass, &block) def subclass.name diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 5cbe5d796d..71b5407dcc 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -1087,7 +1087,6 @@ class AttributeMethodsTest < ActiveRecord::TestCase end private - def new_topic_like_ar_class(&block) klass = Class.new(ActiveRecord::Base) do self.table_name = "topics" diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb index a6fb9f0af7..d6ac5a1057 100644 --- a/activerecord/test/cases/attributes_test.rb +++ b/activerecord/test/cases/attributes_test.rb @@ -241,7 +241,7 @@ module ActiveRecord test "attributes not backed by database columns are always initialized" do OverloadedType.create! - model = OverloadedType.first + model = OverloadedType.last assert_nil model.non_existent_decimal model.non_existent_decimal = "123" @@ -253,7 +253,7 @@ module ActiveRecord attribute :non_existent_decimal, :decimal, default: 123 end child.create! - model = child.first + model = child.last assert_equal 123, model.non_existent_decimal end @@ -264,7 +264,7 @@ module ActiveRecord attribute :foo, :string, default: "lol" end child.create! - model = child.first + model = child.last assert_equal "lol", model.foo diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 2fb5ca4152..2d223a3035 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -2,6 +2,7 @@ require "cases/helper" require "models/author" +require "models/book" require "models/bird" require "models/post" require "models/comment" @@ -39,7 +40,6 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase def self.name; "Person"; end private - def should_be_cool unless first_name == "cool" errors.add :first_name, "not cool" @@ -82,7 +82,6 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase end private - def assert_no_difference_when_adding_callbacks_twice_for(model, association_name) reflection = model.reflect_on_association(association_name) assert_no_difference "callbacks_for_model(#{model.name}).length" do @@ -1673,6 +1672,10 @@ class TestAutosaveAssociationValidationsOnAHasManyAssociation < ActiveRecord::Te super @pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?") @pirate.birds.create(name: "cookoo") + + @author = Author.new(name: "DHH") + @author.published_books.build(name: "Rework", isbn: "1234") + @author.published_books.build(name: "Remote", isbn: "1234") end test "should automatically validate associations" do @@ -1681,6 +1684,42 @@ class TestAutosaveAssociationValidationsOnAHasManyAssociation < ActiveRecord::Te assert_not_predicate @pirate, :valid? end + + test "rollbacks whole transaction and raises ActiveRecord::RecordInvalid when associations fail to #save! due to uniqueness validation failure" do + author_count_before_save = Author.count + book_count_before_save = Book.count + + assert_no_difference "Author.count" do + assert_no_difference "Book.count" do + exception = assert_raises(ActiveRecord::RecordInvalid) do + @author.save! + end + + assert_equal("Validation failed: Published books is invalid", exception.message) + end + end + + assert_equal(author_count_before_save, Author.count) + assert_equal(book_count_before_save, Book.count) + end + + test "rollbacks whole transaction when associations fail to #save due to uniqueness validation failure" do + author_count_before_save = Author.count + book_count_before_save = Book.count + + assert_no_difference "Author.count" do + assert_no_difference "Book.count" do + assert_nothing_raised do + result = @author.save + + assert_not(result) + end + end + end + + assert_equal(author_count_before_save, Author.count) + assert_equal(book_count_before_save, Book.count) + end end class TestAutosaveAssociationValidationsOnAHasOneAssociation < ActiveRecord::TestCase diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index ddafa468ed..1324bdf9b8 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -1141,11 +1141,14 @@ class BasicsTest < ActiveRecord::TestCase def test_clear_cache! # preheat cache c1 = Post.connection.schema_cache.columns("posts") + assert_not_equal 0, Post.connection.schema_cache.size + ActiveRecord::Base.clear_cache! + assert_equal 0, Post.connection.schema_cache.size + c2 = Post.connection.schema_cache.columns("posts") - c1.each_with_index do |v, i| - assert_not_same v, c2[i] - end + assert_not_equal 0, Post.connection.schema_cache.size + assert_equal c1, c2 end @@ -1412,6 +1415,14 @@ class BasicsTest < ActiveRecord::TestCase assert_not_includes SymbolIgnoredDeveloper.columns_hash.keys, "first_name" end + test ".columns_hash raises an error if the record has an empty table name" do + expected_message = "FirstAbstractClass has no table configured. Set one with FirstAbstractClass.table_name=" + exception = assert_raises(ActiveRecord::TableNotSpecified) do + FirstAbstractClass.columns_hash + end + assert_equal expected_message, exception.message + end + test "ignored columns have no attribute methods" do assert_not_respond_to Developer.new, :first_name assert_not_respond_to Developer.new, :first_name= @@ -1496,7 +1507,7 @@ class BasicsTest < ActiveRecord::TestCase test "creating a record raises if preventing writes" do error = assert_raises ActiveRecord::ReadOnlyError do - ActiveRecord::Base.connection.while_preventing_writes do + ActiveRecord::Base.connection_handler.while_preventing_writes do Bird.create! name: "Bluejay" end end @@ -1508,7 +1519,7 @@ class BasicsTest < ActiveRecord::TestCase bird = Bird.create! name: "Bluejay" error = assert_raises ActiveRecord::ReadOnlyError do - ActiveRecord::Base.connection.while_preventing_writes do + ActiveRecord::Base.connection_handler.while_preventing_writes do bird.update! name: "Robin" end end @@ -1520,7 +1531,7 @@ class BasicsTest < ActiveRecord::TestCase bird = Bird.create! name: "Bluejay" error = assert_raises ActiveRecord::ReadOnlyError do - ActiveRecord::Base.connection.while_preventing_writes do + ActiveRecord::Base.connection_handler.while_preventing_writes do bird.destroy! end end @@ -1531,7 +1542,7 @@ class BasicsTest < ActiveRecord::TestCase test "selecting a record does not raise if preventing writes" do bird = Bird.create! name: "Bluejay" - ActiveRecord::Base.connection.while_preventing_writes do + ActiveRecord::Base.connection_handler.while_preventing_writes do assert_equal bird, Bird.where(name: "Bluejay").first end end @@ -1539,13 +1550,13 @@ class BasicsTest < ActiveRecord::TestCase test "an explain query does not raise if preventing writes" do Bird.create!(name: "Bluejay") - ActiveRecord::Base.connection.while_preventing_writes do + ActiveRecord::Base.connection_handler.while_preventing_writes do assert_queries(2) { Bird.where(name: "Bluejay").explain } end end test "an empty transaction does not raise if preventing writes" do - ActiveRecord::Base.connection.while_preventing_writes do + ActiveRecord::Base.connection_handler.while_preventing_writes do assert_queries(2, ignore_none: true) do Bird.transaction do ActiveRecord::Base.connection.materialize_transactions @@ -1553,4 +1564,59 @@ class BasicsTest < ActiveRecord::TestCase end end end + + test "preventing writes applies to all connections on a handler" do + conn1_error = assert_raises ActiveRecord::ReadOnlyError do + ActiveRecord::Base.connection_handler.while_preventing_writes do + assert_equal ActiveRecord::Base.connection, Bird.connection + assert_not_equal ARUnit2Model.connection, Bird.connection + Bird.create!(name: "Bluejay") + end + end + + assert_match %r/\AWrite query attempted while in readonly mode: INSERT /, conn1_error.message + + conn2_error = assert_raises ActiveRecord::ReadOnlyError do + ActiveRecord::Base.connection_handler.while_preventing_writes do + assert_not_equal ActiveRecord::Base.connection, Professor.connection + assert_equal ARUnit2Model.connection, Professor.connection + Professor.create!(name: "Professor Bluejay") + end + end + + assert_match %r/\AWrite query attempted while in readonly mode: INSERT /, conn2_error.message + end + + unless in_memory_db? + test "preventing writes with multiple handlers" do + ActiveRecord::Base.connects_to(database: { writing: :arunit, reading: :arunit }) + + conn1_error = assert_raises ActiveRecord::ReadOnlyError do + ActiveRecord::Base.connected_to(role: :writing) do + assert_equal :writing, ActiveRecord::Base.current_role + + ActiveRecord::Base.connection_handler.while_preventing_writes do + Bird.create!(name: "Bluejay") + end + end + end + + assert_match %r/\AWrite query attempted while in readonly mode: INSERT /, conn1_error.message + + conn2_error = assert_raises ActiveRecord::ReadOnlyError do + ActiveRecord::Base.connected_to(role: :reading) do + assert_equal :reading, ActiveRecord::Base.current_role + + ActiveRecord::Base.connection_handler.while_preventing_writes do + Bird.create!(name: "Bluejay") + end + end + end + + assert_match %r/\AWrite query attempted while in readonly mode: INSERT /, conn2_error.message + ensure + ActiveRecord::Base.connection_handlers = { writing: ActiveRecord::Base.default_connection_handler } + ActiveRecord::Base.establish_connection(:arunit) + end + end end diff --git a/activerecord/test/cases/bind_parameter_test.rb b/activerecord/test/cases/bind_parameter_test.rb index 85685d1d00..720446b39d 100644 --- a/activerecord/test/cases/bind_parameter_test.rb +++ b/activerecord/test/cases/bind_parameter_test.rb @@ -93,7 +93,7 @@ if ActiveRecord::Base.connection.prepared_statements def test_statement_cache_with_in_clause @connection.clear_cache! - topics = Topic.where(id: [1, 3]) + topics = Topic.where(id: [1, 3]).order(:id) assert_equal [1, 3], topics.map(&:id) assert_not_includes statement_cache, to_sql_key(topics.arel) end diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index e42af3686e..525085bb28 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -589,11 +589,7 @@ class CalculationsTest < ActiveRecord::TestCase end def test_should_sum_expression - if current_adapter?(:SQLite3Adapter, :Mysql2Adapter, :PostgreSQLAdapter, :OracleAdapter) - assert_equal 636, Account.sum("2 * credit_limit") - else - assert_equal 636, Account.sum("2 * credit_limit").to_i - end + assert_equal 636, Account.sum("2 * credit_limit") end def test_sum_expression_returns_zero_when_no_records_to_sum @@ -771,6 +767,12 @@ class CalculationsTest < ActiveRecord::TestCase assert_equal [[2, 2], [4, 4]], Reply.includes(:topic).pluck(:id, :"topics.id") end + def test_group_by_with_order_by_virtual_count_attribute + expected = { "SpecialPost" => 1, "StiPost" => 2 } + actual = Post.group(:type).order(:count).limit(2).maximum(:comments_count) + assert_equal expected, actual + end if current_adapter?(:PostgreSQLAdapter) + def test_group_by_with_limit expected = { "Post" => 8, "SpecialPost" => 1 } actual = Post.includes(:comments).group(:type).order(:type).limit(2).count("comments.id") diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb index 27589966af..843242a897 100644 --- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb +++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb @@ -29,7 +29,7 @@ module ActiveRecord def test_establish_connection_uses_spec_name old_config = ActiveRecord::Base.configurations - config = { "readonly" => { "adapter" => "sqlite3" } } + config = { "readonly" => { "adapter" => "sqlite3", "pool" => "5" } } ActiveRecord::Base.configurations = config resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new(ActiveRecord::Base.configurations) spec = resolver.spec(:readonly) diff --git a/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb index 515bf5df06..c0a9f8f9ca 100644 --- a/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +++ b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb @@ -273,6 +273,37 @@ module ActiveRecord } assert_equal expected, actual end + + def test_merge_no_conflicts_with_database_url_and_adapter + ENV["DATABASE_URL"] = "postgres://localhost/foo" + + config = { "default_env" => { "adapter" => "postgresql", "pool" => "5" } } + actual = resolve_config(config) + expected = { "default_env" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost", + "pool" => "5" + } + } + assert_equal expected, actual + end + + def test_merge_no_conflicts_with_database_url_and_numeric_pool + ENV["DATABASE_URL"] = "postgres://localhost/foo" + + config = { "default_env" => { "pool" => 5 } } + actual = resolve_config(config) + expected = { "default_env" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost", + "pool" => 5 + } + } + + assert_equal expected, actual + end end end end diff --git a/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb b/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb index 38331aa641..774380d7e0 100644 --- a/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb +++ b/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb @@ -40,7 +40,7 @@ if current_adapter?(:Mysql2Adapter) end def test_enum_type_with_value_matching_other_type - assert_lookup_type :string, "ENUM('unicode', '8bit', 'none')" + assert_lookup_type :string, "ENUM('unicode', '8bit', 'none', 'time')" end def test_binary_types @@ -58,7 +58,6 @@ if current_adapter?(:Mysql2Adapter) end private - def assert_lookup_type(type, lookup) cast_type = @connection.send(:type_map).lookup(lookup) assert_equal type, cast_type.type diff --git a/activerecord/test/cases/connection_adapters/type_lookup_test.rb b/activerecord/test/cases/connection_adapters/type_lookup_test.rb index 1c79d776f0..e92bb40632 100644 --- a/activerecord/test/cases/connection_adapters/type_lookup_test.rb +++ b/activerecord/test/cases/connection_adapters/type_lookup_test.rb @@ -109,7 +109,6 @@ unless current_adapter?(:PostgreSQLAdapter) # PostgreSQL does not use type strin end private - def assert_lookup_type(type, lookup) cast_type = @connection.send(:type_map).lookup(lookup) assert_equal type, cast_type.type diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb index 82f5f45a4c..ccbb6e16cd 100644 --- a/activerecord/test/cases/connection_pool_test.rb +++ b/activerecord/test/cases/connection_pool_test.rb @@ -694,6 +694,28 @@ module ActiveRecord end end + def test_public_connections_access_threadsafe + _conn1 = @pool.checkout + conn2 = @pool.checkout + + connections = @pool.connections + found_conn = nil + + # Without assuming too much about implementation + # details make sure that a concurrent change to + # the pool is thread-safe. + connections.each_index do |idx| + if connections[idx] == conn2 + Thread.new do + @pool.remove(conn2) + end.join + end + found_conn = connections[idx] + end + + assert_not_nil found_conn + end + private def with_single_connection_pool one_conn_spec = ActiveRecord::Base.connection_pool.spec.dup diff --git a/activerecord/test/cases/database_statements_test.rb b/activerecord/test/cases/database_statements_test.rb index 1c934602ec..119d48b85e 100644 --- a/activerecord/test/cases/database_statements_test.rb +++ b/activerecord/test/cases/database_statements_test.rb @@ -23,7 +23,6 @@ class DatabaseStatementsTest < ActiveRecord::TestCase end private - def return_the_inserted_id(method:) # Oracle adapter uses prefetched primary key values from sequence and passes them to connection adapter insert method if current_adapter?(:OracleAdapter) diff --git a/activerecord/test/cases/explain_test.rb b/activerecord/test/cases/explain_test.rb index a0e75f4e89..edd2c768d3 100644 --- a/activerecord/test/cases/explain_test.rb +++ b/activerecord/test/cases/explain_test.rb @@ -72,7 +72,6 @@ if ActiveRecord::Base.connection.supports_explain? end private - def stub_explain_for_query_plans(query_plans = ["query plan foo", "query plan bar"]) explain_called = 0 diff --git a/activerecord/test/cases/finder_respond_to_test.rb b/activerecord/test/cases/finder_respond_to_test.rb index 66413a98e4..d9e88b3feb 100644 --- a/activerecord/test/cases/finder_respond_to_test.rb +++ b/activerecord/test/cases/finder_respond_to_test.rb @@ -54,7 +54,6 @@ class FinderRespondToTest < ActiveRecord::TestCase end private - def ensure_topic_method_is_not_cached(method_id) Topic.singleton_class.remove_method method_id if Topic.public_methods.include? method_id end diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index ca114d468e..3aa610f86b 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -517,6 +517,7 @@ class FinderTest < ActiveRecord::TestCase expected.touch # PostgreSQL changes the default order if no order clause is used assert_equal expected, Topic.first assert_equal expected, Topic.limit(5).first + assert_equal expected, Topic.order(nil).first end def test_model_class_responds_to_first_bang @@ -540,6 +541,7 @@ class FinderTest < ActiveRecord::TestCase expected.touch # PostgreSQL changes the default order if no order clause is used assert_equal expected, Topic.second assert_equal expected, Topic.limit(5).second + assert_equal expected, Topic.order(nil).second end def test_model_class_responds_to_second_bang @@ -563,6 +565,7 @@ class FinderTest < ActiveRecord::TestCase expected.touch # PostgreSQL changes the default order if no order clause is used assert_equal expected, Topic.third assert_equal expected, Topic.limit(5).third + assert_equal expected, Topic.order(nil).third end def test_model_class_responds_to_third_bang @@ -586,6 +589,7 @@ class FinderTest < ActiveRecord::TestCase expected.touch # PostgreSQL changes the default order if no order clause is used assert_equal expected, Topic.fourth assert_equal expected, Topic.limit(5).fourth + assert_equal expected, Topic.order(nil).fourth end def test_model_class_responds_to_fourth_bang @@ -609,6 +613,7 @@ class FinderTest < ActiveRecord::TestCase expected.touch # PostgreSQL changes the default order if no order clause is used assert_equal expected, Topic.fifth assert_equal expected, Topic.limit(5).fifth + assert_equal expected, Topic.order(nil).fifth end def test_model_class_responds_to_fifth_bang @@ -777,6 +782,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal expected, clients.first(2) assert_equal expected, clients.limit(5).first(2) + assert_equal expected, clients.order(nil).first(2) end def test_implicit_order_column_is_configurable diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 0cb868da6e..a7f01e898e 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -948,7 +948,6 @@ class TransactionalFixturesOnConnectionNotification < ActiveRecord::TestCase end private - def fire_connection_notification(connection) assert_called_with(ActiveRecord::Base.connection_handler, :retrieve_connection, ["book"], returns: connection) do message_bus = ActiveSupport::Notifications.instrumenter @@ -1367,7 +1366,6 @@ class MultipleDatabaseFixturesTest < ActiveRecord::TestCase end private - def with_temporary_connection_pool old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name) new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new ActiveRecord::Base.connection_pool.spec diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 543a0aeb39..56c780c4a6 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -189,7 +189,6 @@ end module InTimeZone private - def in_time_zone(zone) old_zone = Time.zone old_tz = ActiveRecord::Base.time_zone_aware_attributes diff --git a/activerecord/test/cases/hot_compatibility_test.rb b/activerecord/test/cases/hot_compatibility_test.rb index 7b388ebc5e..f41aea6125 100644 --- a/activerecord/test/cases/hot_compatibility_test.rb +++ b/activerecord/test/cases/hot_compatibility_test.rb @@ -115,7 +115,6 @@ class HotCompatibilityTest < ActiveRecord::TestCase end private - def get_prepared_statement_cache(connection) connection.instance_variable_get(:@statements) .instance_variable_get(:@cache)[Process.pid] diff --git a/activerecord/test/cases/insert_all_test.rb b/activerecord/test/cases/insert_all_test.rb index f24c63031c..d086d77081 100644 --- a/activerecord/test/cases/insert_all_test.rb +++ b/activerecord/test/cases/insert_all_test.rb @@ -262,7 +262,6 @@ class InsertAllTest < ActiveRecord::TestCase end private - def capture_log_output output = StringIO.new old_logger, ActiveRecord::Base.logger = ActiveRecord::Base.logger, ActiveSupport::Logger.new(output) diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb index 82cf281cff..d68e208617 100644 --- a/activerecord/test/cases/json_serialization_test.rb +++ b/activerecord/test/cases/json_serialization_test.rb @@ -10,7 +10,6 @@ require "models/comment" module JsonSerializationHelpers private - def set_include_root_in_json(value) original_root_in_json = ActiveRecord::Base.include_root_in_json ActiveRecord::Base.include_root_in_json = value @@ -24,7 +23,7 @@ class JsonSerializationTest < ActiveRecord::TestCase include JsonSerializationHelpers class NamespacedContact < Contact - column :name, :string + column :name, "string" end def setup diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index 04f9b26960..b468da7c76 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -593,7 +593,6 @@ class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase end private - def add_counter_column_to(model, col = "test_count") model.connection.add_column model.table_name, col, :integer, null: false, default: 0 model.reset_column_information diff --git a/activerecord/test/cases/migration/compatibility_test.rb b/activerecord/test/cases/migration/compatibility_test.rb index 726ccf925e..ff2a694e66 100644 --- a/activerecord/test/cases/migration/compatibility_test.rb +++ b/activerecord/test/cases/migration/compatibility_test.rb @@ -12,6 +12,7 @@ module ActiveRecord def setup super @connection = ActiveRecord::Base.connection + @schema_migration = @connection.schema_migration @verbose_was = ActiveRecord::Migration.verbose ActiveRecord::Migration.verbose = false @@ -38,7 +39,7 @@ module ActiveRecord }.new assert connection.index_exists?(:testings, :foo, name: "custom_index_name") - assert_raise(StandardError) { ActiveRecord::Migrator.new(:up, [migration]).migrate } + assert_raise(StandardError) { ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate } assert connection.index_exists?(:testings, :foo, name: "custom_index_name") end @@ -53,7 +54,7 @@ module ActiveRecord }.new assert connection.index_exists?(:testings, :bar) - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert_not connection.index_exists?(:testings, :bar) end @@ -67,7 +68,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert_not connection.index_exists?(:more_testings, :foo_id) assert_not connection.index_exists?(:more_testings, :bar_id) @@ -84,7 +85,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:more_testings, :created_at, null: true) assert connection.column_exists?(:more_testings, :updated_at, null: true) @@ -101,7 +102,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: true) assert connection.column_exists?(:testings, :updated_at, null: true) @@ -117,7 +118,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: true) assert connection.column_exists?(:testings, :updated_at, null: true) @@ -131,7 +132,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: true) assert connection.column_exists?(:testings, :updated_at, null: true) @@ -146,7 +147,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:more_testings, :created_at, null: false, **precision_implicit_default) assert connection.column_exists?(:more_testings, :updated_at, null: false, **precision_implicit_default) @@ -163,7 +164,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: false, **precision_implicit_default) assert connection.column_exists?(:testings, :updated_at, null: false, **precision_implicit_default) @@ -179,7 +180,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: false, **precision_implicit_default) assert connection.column_exists?(:testings, :updated_at, null: false, **precision_implicit_default) @@ -193,7 +194,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: false, **precision_implicit_default) assert connection.column_exists?(:testings, :updated_at, null: false, **precision_implicit_default) @@ -230,7 +231,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :foo, comment: "comment") end @@ -243,7 +244,7 @@ module ActiveRecord end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert_equal "comment", connection.table_comment("testings") end @@ -261,7 +262,7 @@ module ActiveRecord }.new Testing.create! - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert_equal ["foobar"], Testing.all.map(&:foo) ensure ActiveRecord::Base.clear_cache! diff --git a/activerecord/test/cases/migration/create_join_table_test.rb b/activerecord/test/cases/migration/create_join_table_test.rb index e0cbb29dcf..0257545330 100644 --- a/activerecord/test/cases/migration/create_join_table_test.rb +++ b/activerecord/test/cases/migration/create_join_table_test.rb @@ -151,7 +151,6 @@ module ActiveRecord end private - def with_table_cleanup tables_before = connection.data_sources diff --git a/activerecord/test/cases/migration/helper.rb b/activerecord/test/cases/migration/helper.rb index c056199140..da8bdc472a 100644 --- a/activerecord/test/cases/migration/helper.rb +++ b/activerecord/test/cases/migration/helper.rb @@ -34,7 +34,6 @@ module ActiveRecord end private - delegate(*CONNECTION_METHODS, to: :connection) end end diff --git a/activerecord/test/cases/migration/logger_test.rb b/activerecord/test/cases/migration/logger_test.rb index 28f4cc124b..431047f957 100644 --- a/activerecord/test/cases/migration/logger_test.rb +++ b/activerecord/test/cases/migration/logger_test.rb @@ -17,19 +17,20 @@ module ActiveRecord def setup super - ActiveRecord::SchemaMigration.create_table - ActiveRecord::SchemaMigration.delete_all + @schema_migration = ActiveRecord::Base.connection.schema_migration + @schema_migration.create_table + @schema_migration.delete_all end teardown do - ActiveRecord::SchemaMigration.drop_table + @schema_migration.drop_table end def test_migration_should_be_run_without_logger previous_logger = ActiveRecord::Base.logger ActiveRecord::Base.logger = nil migrations = [Migration.new("a", 1), Migration.new("b", 2), Migration.new("c", 3)] - ActiveRecord::Migrator.new(:up, migrations).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration).migrate ensure ActiveRecord::Base.logger = previous_logger end diff --git a/activerecord/test/cases/migration/references_statements_test.rb b/activerecord/test/cases/migration/references_statements_test.rb index 769241ba12..451894fc54 100644 --- a/activerecord/test/cases/migration/references_statements_test.rb +++ b/activerecord/test/cases/migration/references_statements_test.rb @@ -126,7 +126,6 @@ module ActiveRecord end private - def with_polymorphic_column add_column table_name, :supplier_type, :string add_index table_name, [:supplier_id, :supplier_type] diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 255885b599..20f577b2c5 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -38,6 +38,7 @@ class MigrationTest < ActiveRecord::TestCase end Reminder.reset_column_information @verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, false + @schema_migration = ActiveRecord::Base.connection.schema_migration ActiveRecord::Base.connection.schema_cache.clear! end @@ -84,7 +85,7 @@ class MigrationTest < ActiveRecord::TestCase def test_migrator_versions migrations_path = MIGRATIONS_ROOT + "/valid" - migrator = ActiveRecord::MigrationContext.new(migrations_path) + migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration) migrator.up assert_equal 3, migrator.current_version @@ -102,23 +103,23 @@ class MigrationTest < ActiveRecord::TestCase ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true migrations_path = MIGRATIONS_ROOT + "/valid" - migrator = ActiveRecord::MigrationContext.new(migrations_path) + migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration) assert_equal true, migrator.needs_migration? end def test_any_migrations - migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid") + migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", @schema_migration) assert_predicate migrator, :any_migrations? - migrator_empty = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/empty") + migrator_empty = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/empty", @schema_migration) assert_not_predicate migrator_empty, :any_migrations? end def test_migration_version - migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/version_check") + migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/version_check", @schema_migration) assert_equal 0, migrator.current_version migrator.up(20131219224947) assert_equal 20131219224947, migrator.current_version @@ -190,6 +191,7 @@ class MigrationTest < ActiveRecord::TestCase assert_not_predicate BigNumber, :table_exists? GiveMeBigNumbers.up + assert_predicate BigNumber, :table_exists? BigNumber.reset_column_information assert BigNumber.create( @@ -248,7 +250,7 @@ class MigrationTest < ActiveRecord::TestCase assert_not_predicate Reminder, :table_exists? name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" } - migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid") + migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", @schema_migration) migrator.up(&name_filter) assert_column Person, :last_name @@ -310,7 +312,7 @@ class MigrationTest < ActiveRecord::TestCase end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) e = assert_raise(StandardError) { migrator.migrate } @@ -331,7 +333,7 @@ class MigrationTest < ActiveRecord::TestCase end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) e = assert_raise(StandardError) { migrator.run } @@ -354,7 +356,7 @@ class MigrationTest < ActiveRecord::TestCase end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 101) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 101) e = assert_raise(StandardError) { migrator.migrate } assert_equal "An error has occurred, all later migrations canceled:\n\nSomething broke", e.message @@ -413,7 +415,7 @@ class MigrationTest < ActiveRecord::TestCase def test_internal_metadata_stores_environment current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call migrations_path = MIGRATIONS_ROOT + "/valid" - migrator = ActiveRecord::MigrationContext.new(migrations_path) + migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration) migrator.up assert_equal current_env, ActiveRecord::InternalMetadata[:environment] @@ -441,7 +443,7 @@ class MigrationTest < ActiveRecord::TestCase current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call migrations_path = MIGRATIONS_ROOT + "/valid" - migrator = ActiveRecord::MigrationContext.new(migrations_path) + migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration) migrator.up assert_equal current_env, ActiveRecord::InternalMetadata[:environment] assert_equal "bar", ActiveRecord::InternalMetadata[:foo] @@ -482,6 +484,7 @@ class MigrationTest < ActiveRecord::TestCase Thing.reset_table_name Thing.reset_sequence_name WeNeedThings.up + assert_predicate Thing, :table_exists? Thing.reset_column_information assert Thing.create("content" => "hello world") @@ -502,8 +505,9 @@ class MigrationTest < ActiveRecord::TestCase ActiveRecord::Base.table_name_suffix = "_suffix" Reminder.reset_table_name Reminder.reset_sequence_name - Reminder.reset_column_information WeNeedReminders.up + assert_predicate Reminder, :table_exists? + Reminder.reset_column_information assert Reminder.create("content" => "hello world", "remind_at" => Time.now) assert_equal "hello world", Reminder.first.content @@ -636,7 +640,7 @@ class MigrationTest < ActiveRecord::TestCase if ActiveRecord::Base.connection.supports_advisory_locks? def test_migrator_generates_valid_lock_id migration = Class.new(ActiveRecord::Migration::Current).new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) @@ -650,7 +654,7 @@ class MigrationTest < ActiveRecord::TestCase # It is important we are consistent with how we generate this so that # exclusive locking works across migrator versions migration = Class.new(ActiveRecord::Migration::Current).new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) @@ -672,7 +676,7 @@ class MigrationTest < ActiveRecord::TestCase end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) with_another_process_holding_lock(lock_id) do @@ -693,7 +697,7 @@ class MigrationTest < ActiveRecord::TestCase end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) with_another_process_holding_lock(lock_id) do @@ -706,7 +710,7 @@ class MigrationTest < ActiveRecord::TestCase def test_with_advisory_lock_raises_the_right_error_when_it_fails_to_release_lock migration = Class.new(ActiveRecord::Migration::Current).new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) e = assert_raises(ActiveRecord::ConcurrentMigrationError) do @@ -935,7 +939,6 @@ if ActiveRecord::Base.connection.supports_bulk_alter? end private - def with_bulk_change_table # Reset columns/indexes cache as we're changing the table @columns = @indexes = nil diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb index 30e199f1c5..aeba8e1d14 100644 --- a/activerecord/test/cases/migrator_test.rb +++ b/activerecord/test/cases/migrator_test.rb @@ -23,8 +23,9 @@ class MigratorTest < ActiveRecord::TestCase def setup super - ActiveRecord::SchemaMigration.create_table - ActiveRecord::SchemaMigration.delete_all rescue nil + @schema_migration = ActiveRecord::Base.connection.schema_migration + @schema_migration.create_table + @schema_migration.delete_all rescue nil @verbose_was = ActiveRecord::Migration.verbose ActiveRecord::Migration.message_count = 0 ActiveRecord::Migration.class_eval do @@ -36,7 +37,7 @@ class MigratorTest < ActiveRecord::TestCase end teardown do - ActiveRecord::SchemaMigration.delete_all rescue nil + @schema_migration.delete_all rescue nil ActiveRecord::Migration.verbose = @verbose_was ActiveRecord::Migration.class_eval do undef :puts @@ -49,7 +50,7 @@ class MigratorTest < ActiveRecord::TestCase def test_migrator_with_duplicate_names e = assert_raises(ActiveRecord::DuplicateMigrationNameError) do list = [ActiveRecord::Migration.new("Chunky"), ActiveRecord::Migration.new("Chunky")] - ActiveRecord::Migrator.new(:up, list) + ActiveRecord::Migrator.new(:up, list, @schema_migration) end assert_match(/Multiple migrations have the name Chunky/, e.message) end @@ -57,39 +58,40 @@ class MigratorTest < ActiveRecord::TestCase def test_migrator_with_duplicate_versions assert_raises(ActiveRecord::DuplicateMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 1)] - ActiveRecord::Migrator.new(:up, list) + ActiveRecord::Migrator.new(:up, list, @schema_migration) end end def test_migrator_with_missing_version_numbers assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, 3).run + ActiveRecord::Migrator.new(:up, list, @schema_migration, 3).run end assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, -1).run + ActiveRecord::Migrator.new(:up, list, @schema_migration, -1).run end assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, 0).run + ActiveRecord::Migrator.new(:up, list, @schema_migration, 0).run end assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, 3).migrate + ActiveRecord::Migrator.new(:up, list, @schema_migration, 3).migrate end assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, -1).migrate + ActiveRecord::Migrator.new(:up, list, @schema_migration, -1).migrate end end def test_finds_migrations - migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid").migrations + schema_migration = ActiveRecord::Base.connection.schema_migration + migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", schema_migration).migrations [[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]].each_with_index do |pair, i| assert_equal migrations[i].version, pair.first @@ -98,7 +100,8 @@ class MigratorTest < ActiveRecord::TestCase end def test_finds_migrations_in_subdirectories - migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations + schema_migration = ActiveRecord::Base.connection.schema_migration + migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid_with_subdirectories", schema_migration).migrations [[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]].each_with_index do |pair, i| assert_equal migrations[i].version, pair.first @@ -107,8 +110,9 @@ class MigratorTest < ActiveRecord::TestCase end def test_finds_migrations_from_two_directories + schema_migration = ActiveRecord::Base.connection.schema_migration directories = [MIGRATIONS_ROOT + "/valid_with_timestamps", MIGRATIONS_ROOT + "/to_copy_with_timestamps"] - migrations = ActiveRecord::MigrationContext.new(directories).migrations + migrations = ActiveRecord::MigrationContext.new(directories, schema_migration).migrations [[20090101010101, "PeopleHaveHobbies"], [20090101010202, "PeopleHaveDescriptions"], @@ -121,14 +125,16 @@ class MigratorTest < ActiveRecord::TestCase end def test_finds_migrations_in_numbered_directory - migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/10_urban").migrations + schema_migration = ActiveRecord::Base.connection.schema_migration + migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/10_urban", schema_migration).migrations assert_equal 9, migrations[0].version assert_equal "AddExpressions", migrations[0].name end def test_relative_migrations + schema_migration = ActiveRecord::Base.connection.schema_migration list = Dir.chdir(MIGRATIONS_ROOT) do - ActiveRecord::MigrationContext.new("valid").migrations + ActiveRecord::MigrationContext.new("valid", schema_migration).migrations end migration_proxy = list.find { |item| @@ -138,9 +144,9 @@ class MigratorTest < ActiveRecord::TestCase end def test_finds_pending_migrations - ActiveRecord::SchemaMigration.create!(version: "1") + @schema_migration.create!(version: "1") migration_list = [ActiveRecord::Migration.new("foo", 1), ActiveRecord::Migration.new("bar", 3)] - migrations = ActiveRecord::Migrator.new(:up, migration_list).pending_migrations + migrations = ActiveRecord::Migrator.new(:up, migration_list, @schema_migration).pending_migrations assert_equal 1, migrations.size assert_equal migration_list.last, migrations.first @@ -148,35 +154,38 @@ class MigratorTest < ActiveRecord::TestCase def test_migrations_status path = MIGRATIONS_ROOT + "/valid" + schema_migration = ActiveRecord::Base.connection.schema_migration - ActiveRecord::SchemaMigration.create(version: 2) - ActiveRecord::SchemaMigration.create(version: 10) + @schema_migration.create(version: 2) + @schema_migration.create(version: 10) assert_equal [ ["down", "001", "Valid people have last names"], ["up", "002", "We need reminders"], ["down", "003", "Innocent jointable"], ["up", "010", "********** NO FILE **********"], - ], ActiveRecord::MigrationContext.new(path).migrations_status + ], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status end def test_migrations_status_in_subdirectories path = MIGRATIONS_ROOT + "/valid_with_subdirectories" + schema_migration = ActiveRecord::Base.connection.schema_migration - ActiveRecord::SchemaMigration.create(version: 2) - ActiveRecord::SchemaMigration.create(version: 10) + @schema_migration.create(version: 2) + @schema_migration.create(version: 10) assert_equal [ ["down", "001", "Valid people have last names"], ["up", "002", "We need reminders"], ["down", "003", "Innocent jointable"], ["up", "010", "********** NO FILE **********"], - ], ActiveRecord::MigrationContext.new(path).migrations_status + ], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status end def test_migrations_status_with_schema_define_in_subdirectories path = MIGRATIONS_ROOT + "/valid_with_subdirectories" prev_paths = ActiveRecord::Migrator.migrations_paths + schema_migration = ActiveRecord::Base.connection.schema_migration ActiveRecord::Migrator.migrations_paths = path ActiveRecord::Schema.define(version: 3) do @@ -186,16 +195,17 @@ class MigratorTest < ActiveRecord::TestCase ["up", "001", "Valid people have last names"], ["up", "002", "We need reminders"], ["up", "003", "Innocent jointable"], - ], ActiveRecord::MigrationContext.new(path).migrations_status + ], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status ensure ActiveRecord::Migrator.migrations_paths = prev_paths end def test_migrations_status_from_two_directories paths = [MIGRATIONS_ROOT + "/valid_with_timestamps", MIGRATIONS_ROOT + "/to_copy_with_timestamps"] + schema_migration = ActiveRecord::Base.connection.schema_migration - ActiveRecord::SchemaMigration.create(version: "20100101010101") - ActiveRecord::SchemaMigration.create(version: "20160528010101") + @schema_migration.create(version: "20100101010101") + @schema_migration.create(version: "20160528010101") assert_equal [ ["down", "20090101010101", "People have hobbies"], @@ -204,18 +214,18 @@ class MigratorTest < ActiveRecord::TestCase ["down", "20100201010101", "Valid with timestamps we need reminders"], ["down", "20100301010101", "Valid with timestamps innocent jointable"], ["up", "20160528010101", "********** NO FILE **********"], - ], ActiveRecord::MigrationContext.new(paths).migrations_status + ], ActiveRecord::MigrationContext.new(paths, schema_migration).migrations_status end def test_migrator_interleaved_migrations pass_one = [Sensor.new("One", 1)] - ActiveRecord::Migrator.new(:up, pass_one).migrate + ActiveRecord::Migrator.new(:up, pass_one, @schema_migration).migrate assert pass_one.first.went_up assert_not pass_one.first.went_down pass_two = [Sensor.new("One", 1), Sensor.new("Three", 3)] - ActiveRecord::Migrator.new(:up, pass_two).migrate + ActiveRecord::Migrator.new(:up, pass_two, @schema_migration).migrate assert_not pass_two[0].went_up assert pass_two[1].went_up assert pass_two.all? { |x| !x.went_down } @@ -224,7 +234,7 @@ class MigratorTest < ActiveRecord::TestCase Sensor.new("Two", 2), Sensor.new("Three", 3)] - ActiveRecord::Migrator.new(:down, pass_three).migrate + ActiveRecord::Migrator.new(:down, pass_three, @schema_migration).migrate assert pass_three[0].went_down assert_not pass_three[1].went_down assert pass_three[2].went_down @@ -232,7 +242,7 @@ class MigratorTest < ActiveRecord::TestCase def test_up_calls_up migrations = [Sensor.new(nil, 0), Sensor.new(nil, 1), Sensor.new(nil, 2)] - migrator = ActiveRecord::Migrator.new(:up, migrations) + migrator = ActiveRecord::Migrator.new(:up, migrations, @schema_migration) migrator.migrate assert migrations.all?(&:went_up) assert migrations.all? { |m| !m.went_down } @@ -243,7 +253,7 @@ class MigratorTest < ActiveRecord::TestCase test_up_calls_up migrations = [Sensor.new(nil, 0), Sensor.new(nil, 1), Sensor.new(nil, 2)] - migrator = ActiveRecord::Migrator.new(:down, migrations) + migrator = ActiveRecord::Migrator.new(:down, migrations, @schema_migration) migrator.migrate assert migrations.all? { |m| !m.went_up } assert migrations.all?(&:went_down) @@ -251,30 +261,31 @@ class MigratorTest < ActiveRecord::TestCase end def test_current_version - ActiveRecord::SchemaMigration.create!(version: "1000") - migrator = ActiveRecord::MigrationContext.new("db/migrate") + @schema_migration.create!(version: "1000") + schema_migration = ActiveRecord::Base.connection.schema_migration + migrator = ActiveRecord::MigrationContext.new("db/migrate", schema_migration) assert_equal 1000, migrator.current_version end def test_migrator_one_up calls, migrations = sensors(3) - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_equal [[:up, 1]], calls calls.clear - ActiveRecord::Migrator.new(:up, migrations, 2).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 2).migrate assert_equal [[:up, 2]], calls end def test_migrator_one_down calls, migrations = sensors(3) - ActiveRecord::Migrator.new(:up, migrations).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration).migrate assert_equal [[:up, 1], [:up, 2], [:up, 3]], calls calls.clear - ActiveRecord::Migrator.new(:down, migrations, 1).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 1).migrate assert_equal [[:down, 3], [:down, 2]], calls end @@ -282,17 +293,17 @@ class MigratorTest < ActiveRecord::TestCase def test_migrator_one_up_one_down calls, migrations = sensors(3) - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_equal [[:up, 1]], calls calls.clear - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_equal [[:down, 1]], calls end def test_migrator_double_up calls, migrations = sensors(3) - migrator = ActiveRecord::Migrator.new(:up, migrations, 1) + migrator = ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1) assert_equal(0, migrator.current_version) migrator.migrate @@ -305,7 +316,7 @@ class MigratorTest < ActiveRecord::TestCase def test_migrator_double_down calls, migrations = sensors(3) - migrator = ActiveRecord::Migrator.new(:up, migrations, 1) + migrator = ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1) assert_equal 0, migrator.current_version @@ -313,7 +324,7 @@ class MigratorTest < ActiveRecord::TestCase assert_equal [[:up, 1]], calls calls.clear - migrator = ActiveRecord::Migrator.new(:down, migrations, 1) + migrator = ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 1) migrator.run assert_equal [[:down, 1]], calls calls.clear @@ -328,12 +339,12 @@ class MigratorTest < ActiveRecord::TestCase _, migrations = sensors(3) ActiveRecord::Migration.verbose = true - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_not_equal 0, ActiveRecord::Migration.message_count ActiveRecord::Migration.message_count = 0 - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_not_equal 0, ActiveRecord::Migration.message_count end @@ -341,9 +352,9 @@ class MigratorTest < ActiveRecord::TestCase _, migrations = sensors(3) ActiveRecord::Migration.verbose = false - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_equal 0, ActiveRecord::Migration.message_count - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_equal 0, ActiveRecord::Migration.message_count end @@ -351,23 +362,24 @@ class MigratorTest < ActiveRecord::TestCase calls, migrations = sensors(3) # migrate up to 1 - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_equal [[:up, 1]], calls calls.clear # migrate down to 0 - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_equal [[:down, 1]], calls calls.clear # migrate down to 0 again - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_equal [], calls end def test_migrator_going_down_due_to_version_target + schema_migration = ActiveRecord::Base.connection.schema_migration calls, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) migrator.up(1) assert_equal [[:up, 1]], calls @@ -382,8 +394,9 @@ class MigratorTest < ActiveRecord::TestCase end def test_migrator_output_when_running_multiple_migrations + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) result = migrator.migrate assert_equal(3, result.count) @@ -397,8 +410,9 @@ class MigratorTest < ActiveRecord::TestCase end def test_migrator_output_when_running_single_migration + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(1) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) result = migrator.run(:up, 1) @@ -406,8 +420,9 @@ class MigratorTest < ActiveRecord::TestCase end def test_migrator_rollback + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) migrator.migrate assert_equal(3, migrator.current_version) @@ -426,18 +441,20 @@ class MigratorTest < ActiveRecord::TestCase end def test_migrator_db_has_no_schema_migrations_table + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) - ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true - assert_not ActiveRecord::Base.connection.table_exists?("schema_migrations") + ActiveRecord::SchemaMigration.drop_table + assert_not_predicate ActiveRecord::SchemaMigration, :table_exists? migrator.migrate(1) - assert ActiveRecord::Base.connection.table_exists?("schema_migrations") + assert_predicate ActiveRecord::SchemaMigration, :table_exists? end def test_migrator_forward + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("/valid") + migrator = migrator.new("/valid", schema_migration) migrator.migrate(1) assert_equal(1, migrator.current_version) @@ -450,18 +467,20 @@ class MigratorTest < ActiveRecord::TestCase def test_only_loads_pending_migrations # migrate up to 1 - ActiveRecord::SchemaMigration.create!(version: "1") + @schema_migration.create!(version: "1") + schema_migration = ActiveRecord::Base.connection.schema_migration calls, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) migrator.migrate assert_equal [[:up, 2], [:up, 3]], calls end def test_get_all_versions + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) migrator.migrate assert_equal([1, 2, 3], migrator.get_all_versions) diff --git a/activerecord/test/cases/multi_db_migrator_test.rb b/activerecord/test/cases/multi_db_migrator_test.rb new file mode 100644 index 0000000000..650b3af6f0 --- /dev/null +++ b/activerecord/test/cases/multi_db_migrator_test.rb @@ -0,0 +1,218 @@ +# frozen_string_literal: true + +require "cases/helper" +require "cases/migration/helper" + +class MultiDbMigratorTest < ActiveRecord::TestCase + self.use_transactional_tests = false + + # Use this class to sense if migrations have gone + # up or down. + class Sensor < ActiveRecord::Migration::Current + attr_reader :went_up, :went_down + + def initialize(name = self.class.name, version = nil) + super + @went_up = false + @went_down = false + end + + def up; @went_up = true; end + def down; @went_down = true; end + end + + def setup + super + @connection_a = ActiveRecord::Base.connection + @connection_b = ARUnit2Model.connection + + @connection_a.schema_migration.create_table + @connection_b.schema_migration.create_table + + @connection_a.schema_migration.delete_all rescue nil + @connection_b.schema_migration.delete_all rescue nil + + @path_a = MIGRATIONS_ROOT + "/valid" + @path_b = MIGRATIONS_ROOT + "/to_copy" + + @schema_migration_a = @connection_a.schema_migration + @migrations_a = ActiveRecord::MigrationContext.new(@path_a, @schema_migration_a).migrations + @schema_migration_b = @connection_b.schema_migration + @migrations_b = ActiveRecord::MigrationContext.new(@path_b, @schema_migration_b).migrations + + @migrations_a_list = [[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]] + @migrations_b_list = [[1, "PeopleHaveHobbies"], [2, "PeopleHaveDescriptions"]] + + @verbose_was = ActiveRecord::Migration.verbose + + ActiveRecord::Migration.message_count = 0 + ActiveRecord::Migration.class_eval do + undef :puts + def puts(*) + ActiveRecord::Migration.message_count += 1 + end + end + end + + teardown do + @connection_a.schema_migration.delete_all rescue nil + @connection_b.schema_migration.delete_all rescue nil + + ActiveRecord::Migration.verbose = @verbose_was + ActiveRecord::Migration.class_eval do + undef :puts + def puts(*) + super + end + end + end + + def test_finds_migrations + @migrations_a_list.each_with_index do |pair, i| + assert_equal @migrations_a[i].version, pair.first + assert_equal @migrations_a[i].name, pair.last + end + + @migrations_b_list.each_with_index do |pair, i| + assert_equal @migrations_b[i].version, pair.first + assert_equal @migrations_b[i].name, pair.last + end + end + + def test_migrations_status + @schema_migration_a.create(version: 2) + @schema_migration_a.create(version: 10) + + assert_equal [ + ["down", "001", "Valid people have last names"], + ["up", "002", "We need reminders"], + ["down", "003", "Innocent jointable"], + ["up", "010", "********** NO FILE **********"], + ], ActiveRecord::MigrationContext.new(@path_a, @schema_migration_a).migrations_status + + @schema_migration_b.create(version: 4) + + assert_equal [ + ["down", "001", "People have hobbies"], + ["down", "002", "People have descriptions"], + ["up", "004", "********** NO FILE **********"] + ], ActiveRecord::MigrationContext.new(@path_b, @schema_migration_b).migrations_status + end + + def test_get_all_versions + _, migrator_a = migrator_class(3) + migrator_a = migrator_a.new(@path_a, @schema_migration_a) + + migrator_a.migrate + assert_equal([1, 2, 3], migrator_a.get_all_versions) + + migrator_a.rollback + assert_equal([1, 2], migrator_a.get_all_versions) + + migrator_a.rollback + assert_equal([1], migrator_a.get_all_versions) + + migrator_a.rollback + assert_equal([], migrator_a.get_all_versions) + + _, migrator_b = migrator_class(2) + migrator_b = migrator_b.new(@path_b, @schema_migration_b) + + migrator_b.migrate + assert_equal([1, 2], migrator_b.get_all_versions) + + migrator_b.rollback + assert_equal([1], migrator_b.get_all_versions) + + migrator_b.rollback + assert_equal([], migrator_b.get_all_versions) + end + + def test_finds_pending_migrations + @schema_migration_a.create!(version: "1") + migration_list_a = [ActiveRecord::Migration.new("foo", 1), ActiveRecord::Migration.new("bar", 3)] + migrations_a = ActiveRecord::Migrator.new(:up, migration_list_a, @schema_migration_a).pending_migrations + + assert_equal 1, migrations_a.size + assert_equal migration_list_a.last, migrations_a.first + + @schema_migration_b.create!(version: "1") + migration_list_b = [ActiveRecord::Migration.new("foo", 1), ActiveRecord::Migration.new("bar", 3)] + migrations_b = ActiveRecord::Migrator.new(:up, migration_list_b, @schema_migration_b).pending_migrations + + assert_equal 1, migrations_b.size + assert_equal migration_list_b.last, migrations_b.first + end + + def test_migrator_db_has_no_schema_migrations_table + _, migrator = migrator_class(3) + migrator = migrator.new(@path_a, @schema_migration_a) + + @schema_migration_a.drop_table + assert_not @connection_a.table_exists?("schema_migrations") + migrator.migrate(1) + assert @connection_a.table_exists?("schema_migrations") + + _, migrator = migrator_class(3) + migrator = migrator.new(@path_b, @schema_migration_b) + + @schema_migration_b.drop_table + assert_not @connection_b.table_exists?("schema_migrations") + migrator.migrate(1) + assert @connection_b.table_exists?("schema_migrations") + end + + def test_migrator_forward + _, migrator = migrator_class(3) + migrator = migrator.new(@path_a, @schema_migration_a) + migrator.migrate(1) + assert_equal(1, migrator.current_version) + + migrator.forward(2) + assert_equal(3, migrator.current_version) + + migrator.forward + assert_equal(3, migrator.current_version) + + _, migrator_b = migrator_class(3) + migrator_b = migrator_b.new(@path_b, @schema_migration_b) + migrator_b.migrate(1) + assert_equal(1, migrator_b.current_version) + + migrator_b.forward(2) + assert_equal(3, migrator_b.current_version) + + migrator_b.forward + assert_equal(3, migrator_b.current_version) + end + + private + def m(name, version) + x = Sensor.new name, version + x.extend(Module.new { + define_method(:up) { yield(:up, x); super() } + define_method(:down) { yield(:down, x); super() } + }) if block_given? + end + + def sensors(count) + calls = [] + migrations = count.times.map { |i| + m(nil, i + 1) { |c, migration| + calls << [c, migration.version] + } + } + [calls, migrations] + end + + def migrator_class(count) + calls, migrations = sensors(count) + + migrator = Class.new(ActiveRecord::MigrationContext) { + define_method(:migrations) { |*| + migrations + } + } + [calls, migrator] + end +end diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index bb1c1ea17d..b49e62bee6 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -851,7 +851,6 @@ module NestedAttributesOnACollectionAssociationTests end private - def association_setter @association_setter ||= "#{@association_name}_attributes=".to_sym end diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb index 080aeb0989..d783b2945d 100644 --- a/activerecord/test/cases/pooled_connections_test.rb +++ b/activerecord/test/cases/pooled_connections_test.rb @@ -72,7 +72,6 @@ class PooledConnectionsTest < ActiveRecord::TestCase end private - def add_record(name) ActiveRecord::Base.connection_pool.with_connection { Project.create! name: name } end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index eb32b690aa..53a4963909 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -335,11 +335,7 @@ class QueryCacheTest < ActiveRecord::TestCase def test_cache_does_not_wrap_results_in_arrays Task.cache do - if current_adapter?(:SQLite3Adapter, :Mysql2Adapter, :PostgreSQLAdapter, :OracleAdapter) - assert_equal 2, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") - else - assert_instance_of String, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") - end + assert_equal 2, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") end end @@ -541,7 +537,6 @@ class QueryCacheTest < ActiveRecord::TestCase end private - def with_temporary_connection_pool old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name) new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new ActiveRecord::Base.connection_pool.spec diff --git a/activerecord/test/cases/relation/where_clause_test.rb b/activerecord/test/cases/relation/where_clause_test.rb index b26a1a1d80..35db3d1175 100644 --- a/activerecord/test/cases/relation/where_clause_test.rb +++ b/activerecord/test/cases/relation/where_clause_test.rb @@ -233,7 +233,6 @@ class ActiveRecord::Relation end private - def table Arel::Table.new("table") end diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 3f370e5ede..e0743de94b 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -405,7 +405,6 @@ module ActiveRecord end private - def skip_if_sqlite3_version_includes_quoting_bug if sqlite3_version_includes_quoting_bug? skip <<-ERROR.squish diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 732bca4bf5..1a20fe5dc2 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -298,7 +298,7 @@ class RelationTest < ActiveRecord::TestCase end def test_reverse_order_with_function - topics = Topic.order(Arel.sql("length(title)")).reverse_order + topics = Topic.order("length(title)").reverse_order assert_equal topics(:second).title, topics.first.title end @@ -308,9 +308,9 @@ class RelationTest < ActiveRecord::TestCase end def test_reverse_order_with_function_other_predicates - topics = Topic.order(Arel.sql("author_name, length(title), id")).reverse_order + topics = Topic.order("author_name, length(title), id").reverse_order assert_equal topics(:second).title, topics.first.title - topics = Topic.order(Arel.sql("length(author_name), id, length(title)")).reverse_order + topics = Topic.order("length(author_name), id, length(title)").reverse_order assert_equal topics(:fifth).title, topics.first.title end @@ -1696,7 +1696,7 @@ class RelationTest < ActiveRecord::TestCase scope = Post.order("comments.body asc") assert_equal ["comments"], scope.references_values - scope = Post.order(Arel.sql("foo(comments.body)")) + scope = Post.order("foo(comments.body)") assert_equal [], scope.references_values end @@ -1721,7 +1721,7 @@ class RelationTest < ActiveRecord::TestCase scope = Post.reorder("comments.body asc") assert_equal %w(comments), scope.references_values - scope = Post.reorder(Arel.sql("foo(comments.body)")) + scope = Post.reorder("foo(comments.body)") assert_equal [], scope.references_values end @@ -1955,8 +1955,8 @@ class RelationTest < ActiveRecord::TestCase test "joins with order by custom attribute" do companies = Company.create!([{ name: "test1" }, { name: "test2" }]) companies.each { |company| company.contracts.create! } - assert_equal companies, Company.joins(:contracts).order(:metadata) - assert_equal companies.reverse, Company.joins(:contracts).order(metadata: :desc) + assert_equal companies, Company.joins(:contracts).order(:metadata, :count) + assert_equal companies.reverse, Company.joins(:contracts).order(metadata: :desc, count: :desc) end test "delegations do not leak to other classes" do diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 49e9be9565..bb7184c5fc 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -33,6 +33,7 @@ class SchemaDumperTest < ActiveRecord::TestCase schema_info = ActiveRecord::Base.connection.dump_schema_information assert_match(/20100201010101.*20100301010101/m, schema_info) + assert_includes schema_info, "20100101010101" ensure ActiveRecord::SchemaMigration.delete_all end diff --git a/activerecord/test/cases/schema_loading_test.rb b/activerecord/test/cases/schema_loading_test.rb index f539156466..5da2d9e08f 100644 --- a/activerecord/test/cases/schema_loading_test.rb +++ b/activerecord/test/cases/schema_loading_test.rb @@ -43,7 +43,6 @@ class SchemaLoadingTest < ActiveRecord::TestCase end private - def define_model Class.new(ActiveRecord::Base) do include SchemaLoadCounter diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb index ffe94eee0f..6b6861465b 100644 --- a/activerecord/test/cases/tasks/database_tasks_test.rb +++ b/activerecord/test/cases/tasks/database_tasks_test.rb @@ -835,7 +835,6 @@ module ActiveRecord end private - def capture_migration_status capture(:stdout) do ActiveRecord::Tasks::DatabaseTasks.migrate_status diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb index 552e623fd4..258132835f 100644 --- a/activerecord/test/cases/tasks/mysql_rake_test.rb +++ b/activerecord/test/cases/tasks/mysql_rake_test.rb @@ -100,7 +100,6 @@ if current_adapter?(:Mysql2Adapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:establish_connection, nil) do ActiveRecord::Base.stub(:connection, @connection) do @@ -180,7 +179,6 @@ if current_adapter?(:Mysql2Adapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:establish_connection, nil) do ActiveRecord::Base.stub(:connection, @connection) do @@ -233,7 +231,6 @@ if current_adapter?(:Mysql2Adapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:establish_connection, nil) do ActiveRecord::Base.stub(:connection, @connection) do diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb index 065ba7734c..f9df650687 100644 --- a/activerecord/test/cases/tasks/postgresql_rake_test.rb +++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb @@ -139,7 +139,6 @@ if current_adapter?(:PostgreSQLAdapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:connection, @connection) do ActiveRecord::Base.stub(:establish_connection, nil) do @@ -201,7 +200,6 @@ if current_adapter?(:PostgreSQLAdapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:connection, @connection) do ActiveRecord::Base.stub(:establish_connection, nil) do @@ -301,7 +299,6 @@ if current_adapter?(:PostgreSQLAdapter) end private - def with_stubbed_connection ActiveRecord::Base.stub(:connection, @connection) do yield diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index 100bd6a925..19b89ab08c 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -460,7 +460,6 @@ class TransactionCallbacksTest < ActiveRecord::TestCase end private - def add_transaction_execution_blocks(record) record.after_commit_block(:create) { |r| r.history << :commit_on_create } record.after_commit_block(:update) { |r| r.history << :commit_on_update } diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 6795996cca..b5c1cac3d9 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -1077,7 +1077,6 @@ class TransactionTest < ActiveRecord::TestCase end private - %w(validation save destroy).each do |filter| define_method("add_cancelling_before_#{filter}_with_db_side_effect_to_topic") do |topic| meta = class << topic; self; end diff --git a/activerecord/test/cases/unsafe_raw_sql_test.rb b/activerecord/test/cases/unsafe_raw_sql_test.rb index fc92bf73c9..87edb163f2 100644 --- a/activerecord/test/cases/unsafe_raw_sql_test.rb +++ b/activerecord/test/cases/unsafe_raw_sql_test.rb @@ -141,7 +141,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: disallows invalid column name" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.order("len(title) asc").pluck(:id) + Post.order("REPLACE(title, 'misc', 'zzzz') asc").pluck(:id) end end end @@ -157,7 +157,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: disallows invalid column with direction" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.order("len(title)" => :asc).pluck(:id) + Post.order("REPLACE(title, 'misc', 'zzzz')" => :asc).pluck(:id) end end end @@ -190,7 +190,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: disallows invalid Array arguments" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.order(["author_id", "length(title)"]).pluck(:id) + Post.order(["author_id", "REPLACE(title, 'misc', 'zzzz')"]).pluck(:id) end end end @@ -198,8 +198,8 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: allows valid Array arguments" do ids_expected = Post.order(Arel.sql("author_id, length(title)")).pluck(:id) - ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id", Arel.sql("length(title)")]).pluck(:id) } - ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id", Arel.sql("length(title)")]).pluck(:id) } + ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id", "length(title)"]).pluck(:id) } + ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id", "length(title)"]).pluck(:id) } assert_equal ids_expected, ids_depr assert_equal ids_expected, ids_disabled @@ -208,7 +208,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: logs deprecation warning for unrecognized column" do with_unsafe_raw_sql_deprecated do assert_deprecated(/Dangerous query method/) do - Post.order("length(title)") + Post.order("REPLACE(title, 'misc', 'zzzz')") end end end @@ -223,6 +223,16 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase assert_equal titles_expected, titles_disabled end + test "pluck: allows string column name with function and alias" do + titles_expected = Post.pluck(Arel.sql("UPPER(title)")) + + titles_depr = with_unsafe_raw_sql_deprecated { Post.pluck("UPPER(title) AS title") } + titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("UPPER(title) AS title") } + + assert_equal titles_expected, titles_depr + assert_equal titles_expected, titles_disabled + end + test "pluck: allows symbol column name" do titles_expected = Post.pluck(Arel.sql("title")) @@ -287,7 +297,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "pluck: disallows invalid column name" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.pluck("length(title)") + Post.pluck("REPLACE(title, 'misc', 'zzzz')") end end end @@ -295,7 +305,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "pluck: disallows invalid column name amongst valid names" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.pluck(:title, "length(title)") + Post.pluck(:title, "REPLACE(title, 'misc', 'zzzz')") end end end @@ -303,7 +313,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "pluck: disallows invalid column names with includes" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.includes(:comments).pluck(:title, "length(title)") + Post.includes(:comments).pluck(:title, "REPLACE(title, 'misc', 'zzzz')") end end end @@ -318,24 +328,25 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "pluck: logs deprecation warning" do with_unsafe_raw_sql_deprecated do assert_deprecated(/Dangerous query method/) do - Post.includes(:comments).pluck(:title, "length(title)") + Post.includes(:comments).pluck(:title, "REPLACE(title, 'misc', 'zzzz')") end end end - def with_unsafe_raw_sql_disabled(&blk) - with_config(:disabled, &blk) - end + private + def with_unsafe_raw_sql_disabled(&block) + with_config(:disabled, &block) + end - def with_unsafe_raw_sql_deprecated(&blk) - with_config(:deprecated, &blk) - end + def with_unsafe_raw_sql_deprecated(&block) + with_config(:deprecated, &block) + end - def with_config(new_value, &blk) - old_value = ActiveRecord::Base.allow_unsafe_raw_sql - ActiveRecord::Base.allow_unsafe_raw_sql = new_value - blk.call - ensure - ActiveRecord::Base.allow_unsafe_raw_sql = old_value - end + def with_config(new_value, &block) + old_value = ActiveRecord::Base.allow_unsafe_raw_sql + ActiveRecord::Base.allow_unsafe_raw_sql = new_value + yield + ensure + ActiveRecord::Base.allow_unsafe_raw_sql = old_value + end end diff --git a/activerecord/test/cases/yaml_serialization_test.rb b/activerecord/test/cases/yaml_serialization_test.rb index 60ebdce178..7003afa33a 100644 --- a/activerecord/test/cases/yaml_serialization_test.rb +++ b/activerecord/test/cases/yaml_serialization_test.rb @@ -130,7 +130,6 @@ class YamlSerializationTest < ActiveRecord::TestCase end private - def yaml_fixture(file_name) path = File.expand_path( "../support/yaml_compatibility_fixtures/#{file_name}.yml", diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb index b52b643ad7..da7e4139b1 100644 --- a/activerecord/test/models/author.rb +++ b/activerecord/test/models/author.rb @@ -116,6 +116,7 @@ class Author < ActiveRecord::Base has_many :tags_with_primary_key, through: :posts has_many :books + has_many :published_books, class_name: "PublishedBook" has_many :unpublished_books, -> { where(status: [:proposed, :written]) }, class_name: "Book" has_many :subscriptions, through: :books has_many :subscribers, -> { order("subscribers.nick") }, through: :subscriptions diff --git a/activerecord/test/models/book.rb b/activerecord/test/models/book.rb index afdda1a81e..43b82e6047 100644 --- a/activerecord/test/models/book.rb +++ b/activerecord/test/models/book.rb @@ -24,3 +24,9 @@ class Book < ActiveRecord::Base "do publish work..." end end + +class PublishedBook < ActiveRecord::Base + self.table_name = "books" + + validates_uniqueness_of :isbn +end diff --git a/activerecord/test/models/club.rb b/activerecord/test/models/club.rb index bb49fb300c..890e427616 100644 --- a/activerecord/test/models/club.rb +++ b/activerecord/test/models/club.rb @@ -15,7 +15,6 @@ class Club < ActiveRecord::Base accepts_nested_attributes_for :membership private - def private_method "I'm sorry sir, this is a *private* club, not a *pirate* club" end diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index a0f48d23f1..339b5c8ca8 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -25,7 +25,6 @@ class Company < AbstractCompany end private - def private_method "I am Jack's innermost fears and aspirations" end diff --git a/activerecord/test/models/company_in_module.rb b/activerecord/test/models/company_in_module.rb index 52b7e06a63..320b26b950 100644 --- a/activerecord/test/models/company_in_module.rb +++ b/activerecord/test/models/company_in_module.rb @@ -91,7 +91,6 @@ module MyApplication validate :check_empty_credit_limit private - def check_empty_credit_limit errors.add("credit_card", :blank) if credit_card.blank? end diff --git a/activerecord/test/models/contact.rb b/activerecord/test/models/contact.rb index 6e02ff199b..d5f6f00691 100644 --- a/activerecord/test/models/contact.rb +++ b/activerecord/test/models/contact.rb @@ -10,14 +10,14 @@ module ContactFakeColumns table_name => "id" } - column :id, :integer - column :name, :string - column :age, :integer - column :avatar, :binary - column :created_at, :datetime - column :awesome, :boolean - column :preferences, :string - column :alternative_id, :integer + column :id, "integer" + column :name, "string" + column :age, "integer" + column :avatar, "binary" + column :created_at, "datetime" + column :awesome, "boolean" + column :preferences, "string" + column :alternative_id, "integer" serialize :preferences @@ -37,7 +37,7 @@ end class ContactSti < ActiveRecord::Base extend ContactFakeColumns - column :type, :string + column :type, "string" def type; "ContactSti" end end diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb index c3d15a571a..0dfd29e45e 100644 --- a/activerecord/test/models/person.rb +++ b/activerecord/test/models/person.rb @@ -101,7 +101,6 @@ class RichPerson < ActiveRecord::Base before_validation :run_before_validation private - def run_before_create self.first_name = first_name.to_s + "run_before_create" end diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 77101090f2..7a864c728c 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -93,7 +93,6 @@ class Topic < ActiveRecord::Base end private - def default_written_on self.written_on = Time.now unless attribute_present?("written_on") end diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb index b143035213..911ac808c6 100644 --- a/activerecord/test/schema/mysql2_specific_schema.rb +++ b/activerecord/test/schema/mysql2_specific_schema.rb @@ -62,10 +62,6 @@ ActiveRecord::Schema.define do t.binary :binary_column, limit: 1 end - create_table :enum_tests, id: false, force: true do |t| - t.column :enum_column, "ENUM('text','blob','tiny','medium','long','unsigned','bigint')" - end - execute "DROP PROCEDURE IF EXISTS ten" execute <<~SQL diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 41920b3719..b6c0ae0de2 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -115,7 +115,7 @@ ActiveRecord::Schema.define do t.column :font_size, :integer, **default_zero t.column :difficulty, :integer, **default_zero t.column :cover, :string, default: "hard" - t.string :isbn + t.string :isbn, **case_sensitive_options t.datetime :published_on t.index [:author_id, :name], unique: true t.index :isbn, where: "published_on IS NOT NULL", unique: true @@ -261,6 +261,7 @@ ActiveRecord::Schema.define do t.references :developer, index: false t.references :company, index: false t.string :metadata + t.integer :count end create_table :customers, force: true do |t| diff --git a/activerecord/test/support/config.rb b/activerecord/test/support/config.rb index de0d90a18f..66ae57b382 100644 --- a/activerecord/test/support/config.rb +++ b/activerecord/test/support/config.rb @@ -12,7 +12,6 @@ module ARTest end private - def config_file Pathname.new(ENV["ARCONFIG"] || TEST_ROOT + "/config.yml") end diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 7ecbafc911..da295a0d35 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -34,5 +34,5 @@ Gem::Specification.new do |s| s.add_dependency "tzinfo", "~> 1.1" s.add_dependency "minitest", "~> 5.1" s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" - s.add_dependency "zeitwerk", "~> 2.1", ">= 2.1.4" + s.add_dependency "zeitwerk", "~> 2.1", ">= 2.1.8" end diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb index 02cbfbaee6..f55e821e10 100644 --- a/activesupport/lib/active_support/backtrace_cleaner.rb +++ b/activesupport/lib/active_support/backtrace_cleaner.rb @@ -85,7 +85,6 @@ module ActiveSupport end private - FORMATTED_GEMS_PATTERN = /\A[^\/]+ \([\w.]+\) / def add_gem_filter diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index f43894a1ea..925440a23f 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -72,7 +72,6 @@ module ActiveSupport end private - def read_entry(key, options) if File.exist?(key) File.open(key) { |f| Marshal.load(f) } diff --git a/activesupport/lib/active_support/cache/memory_store.rb b/activesupport/lib/active_support/cache/memory_store.rb index 629eb2dd70..fa24da91b4 100644 --- a/activesupport/lib/active_support/cache/memory_store.rb +++ b/activesupport/lib/active_support/cache/memory_store.rb @@ -114,7 +114,6 @@ module ActiveSupport end private - PER_ENTRY_OVERHEAD = 240 def cached_size(key, entry) diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index d0644a0f7e..11746e0537 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -142,7 +142,6 @@ module ActiveSupport end private - # A hook invoked every time a before callback is halted. # This can be overridden in ActiveSupport::Callbacks implementors in order # to provide better debugging/logging. @@ -582,7 +581,6 @@ module ActiveSupport attr_reader :chain private - def append_one(callback) @callbacks = nil remove_duplicates(callback) @@ -843,7 +841,6 @@ module ActiveSupport end protected - def get_callbacks(name) # :nodoc: __callbacks[name.to_sym] end diff --git a/activesupport/lib/active_support/concurrency/share_lock.rb b/activesupport/lib/active_support/concurrency/share_lock.rb index f18ccf1c88..eae7d4469f 100644 --- a/activesupport/lib/active_support/concurrency/share_lock.rb +++ b/activesupport/lib/active_support/concurrency/share_lock.rb @@ -200,7 +200,6 @@ module ActiveSupport end private - # Must be called within synchronize def busy_for_exclusive?(purpose) busy_for_sharing?(purpose) || diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb index e2e11545e2..c7a2378e41 100644 --- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb @@ -20,21 +20,11 @@ module DateAndTime advance(days: -1) end - # Returns a new date/time the specified number of days ago. - def prev_day(days = 1) - advance(days: -days) - end - # Returns a new date/time representing tomorrow. def tomorrow advance(days: 1) end - # Returns a new date/time the specified number of days in the future. - def next_day(days = 1) - advance(days: days) - end - # Returns true if the date/time is today. def today? to_date == ::Date.current @@ -198,21 +188,11 @@ module DateAndTime end end - # Returns a new date/time the specified number of months in the future. - def next_month(months = 1) - advance(months: months) - end - # Short-hand for months_since(3) def next_quarter months_since(3) end - # Returns a new date/time the specified number of years in the future. - def next_year(years = 1) - advance(years: years) - end - # Returns a new date/time representing the given day in the previous week. # Week is assumed to start on +start_day+, default is # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. @@ -233,11 +213,6 @@ module DateAndTime end alias_method :last_weekday, :prev_weekday - # Returns a new date/time the specified number of months ago. - def prev_month(months = 1) - advance(months: -months) - end - # Short-hand for months_ago(1). def last_month months_ago(1) @@ -249,11 +224,6 @@ module DateAndTime end alias_method :last_quarter, :prev_quarter - # Returns a new date/time the specified number of years ago. - def prev_year(years = 1) - advance(years: -years) - end - # Short-hand for years_ago(1). def last_year years_ago(1) diff --git a/activesupport/lib/active_support/core_ext/date_and_time/zones.rb b/activesupport/lib/active_support/core_ext/date_and_time/zones.rb index 894fd9b76d..fb6a27cb27 100644 --- a/activesupport/lib/active_support/core_ext/date_and_time/zones.rb +++ b/activesupport/lib/active_support/core_ext/date_and_time/zones.rb @@ -29,7 +29,6 @@ module DateAndTime end private - def time_with_zone(time, zone) if time ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, zone) diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb index 29725c89f7..231bf870a2 100644 --- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb @@ -96,7 +96,6 @@ class DateTime end private - def offset_in_seconds (offset * 86400).to_i end diff --git a/activesupport/lib/active_support/core_ext/digest.rb b/activesupport/lib/active_support/core_ext/digest.rb new file mode 100644 index 0000000000..ce1427e13a --- /dev/null +++ b/activesupport/lib/active_support/core_ext/digest.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require "active_support/core_ext/digest/uuid" diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index b8996ecb10..54271a3970 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -205,18 +205,18 @@ class Module if allow_nil method_def = [ "def #{method_prefix}#{method}(#{definition})", - "_ = #{to}", - "if !_.nil? || nil.respond_to?(:#{method})", - " _.#{method}(#{definition})", - "end", - "end" + " _ = #{to}", + " if !_.nil? || nil.respond_to?(:#{method})", + " _.#{method}(#{definition})", + " end", + "end" ].join ";" else exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") method_def = [ "def #{method_prefix}#{method}(#{definition})", - " _ = #{to}", + " _ = #{to}", " _.#{method}(#{definition})", "rescue NoMethodError => e", " if _.nil? && e.name == :#{method}", diff --git a/activesupport/lib/active_support/core_ext/range/each.rb b/activesupport/lib/active_support/core_ext/range/each.rb index 2f22cd0e92..2d86997edf 100644 --- a/activesupport/lib/active_support/core_ext/range/each.rb +++ b/activesupport/lib/active_support/core_ext/range/each.rb @@ -15,7 +15,6 @@ module ActiveSupport end private - def ensure_iteration_allowed raise TypeError, "can't iterate from #{first.class}" if first.is_a?(TimeWithZone) end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 645b1fea17..f48ea56326 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -291,7 +291,6 @@ module ActiveSupport #:nodoc: end private - def html_escape_interpolated_argument(arg) (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s) end diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index f09a6271ad..eed34965e3 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -311,4 +311,34 @@ class Time end alias_method :eql_without_coercion, :eql? alias_method :eql?, :eql_with_coercion + + # Returns a new time the specified number of days ago. + def prev_day(days = 1) + advance(days: -days) + end + + # Returns a new time the specified number of days in the future. + def next_day(days = 1) + advance(days: days) + end + + # Returns a new time the specified number of months ago. + def prev_month(months = 1) + advance(months: -months) + end + + # Returns a new time the specified number of months in the future. + def next_month(months = 1) + advance(months: months) + end + + # Returns a new time the specified number of years ago. + def prev_year(years = 1) + advance(years: -years) + end + + # Returns a new time the specified number of years in the future. + def next_year(years = 1) + advance(years: years) + end end diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 82f07c085e..5dc47b20c6 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -290,7 +290,6 @@ module ActiveSupport #:nodoc: end private - def load(file, wrap = false) result = false load_dependency(file) { result = super } diff --git a/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb b/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb index fd39ad6e55..821e3f971e 100644 --- a/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb +++ b/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb @@ -56,7 +56,6 @@ module ActiveSupport end private - def setup_autoloaders(enable_reloading) Dependencies.autoload_paths.each do |autoload_path| # Zeitwerk only accepts existing directories in `push_dir` to diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb index 56f1e23136..fab6c1cd73 100644 --- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb @@ -122,7 +122,7 @@ module ActiveSupport # ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"] class DeprecatedConstantProxy < DeprecationProxy def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.") - require "active_support/inflector/methods" + Kernel.require "active_support/inflector/methods" @old_const = old_const @new_const = new_const diff --git a/activesupport/lib/active_support/descendants_tracker.rb b/activesupport/lib/active_support/descendants_tracker.rb index 21565138a7..1dad4f923e 100644 --- a/activesupport/lib/active_support/descendants_tracker.rb +++ b/activesupport/lib/active_support/descendants_tracker.rb @@ -41,7 +41,6 @@ module ActiveSupport end private - def accumulate_descendants(klass, acc) if direct_descendants = @@direct_descendants[klass] direct_descendants.each do |direct_descendant| diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb index a30bd11a87..2b4f1288f1 100644 --- a/activesupport/lib/active_support/duration.rb +++ b/activesupport/lib/active_support/duration.rb @@ -198,7 +198,6 @@ module ActiveSupport end private - def calculate_total_seconds(parts) parts.inject(0) do |total, (part, value)| total + value * PARTS_IN_SECONDS[part] @@ -399,7 +398,6 @@ module ActiveSupport end private - def sum(sign, time = ::Time.current) parts.inject(time) do |t, (type, number)| if t.acts_like?(:time) || t.acts_like?(:date) diff --git a/activesupport/lib/active_support/duration/iso8601_parser.rb b/activesupport/lib/active_support/duration/iso8601_parser.rb index d3233e6111..83f3b28602 100644 --- a/activesupport/lib/active_support/duration/iso8601_parser.rb +++ b/activesupport/lib/active_support/duration/iso8601_parser.rb @@ -80,7 +80,6 @@ module ActiveSupport end private - def finished? scanner.eos? end diff --git a/activesupport/lib/active_support/duration/iso8601_serializer.rb b/activesupport/lib/active_support/duration/iso8601_serializer.rb index 1125454919..8314df12b0 100644 --- a/activesupport/lib/active_support/duration/iso8601_serializer.rb +++ b/activesupport/lib/active_support/duration/iso8601_serializer.rb @@ -32,7 +32,6 @@ module ActiveSupport end private - # Return pair of duration's parts and whole duration sign. # Parts are summarized (as they can become repetitive due to addition, etc). # Zero parts are removed as not significant. diff --git a/activesupport/lib/active_support/evented_file_update_checker.rb b/activesupport/lib/active_support/evented_file_update_checker.rb index 5a79822c49..6075e0a3d3 100644 --- a/activesupport/lib/active_support/evented_file_update_checker.rb +++ b/activesupport/lib/active_support/evented_file_update_checker.rb @@ -217,7 +217,6 @@ module ActiveSupport end private - def ascendant_of?(base, other) base != other && other.ascend do |ascendant| break true if base == ascendant diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb index 1a0bb10815..9b665e7f19 100644 --- a/activesupport/lib/active_support/file_update_checker.rb +++ b/activesupport/lib/active_support/file_update_checker.rb @@ -98,7 +98,6 @@ module ActiveSupport end private - def watched @watched || begin all = @files.select { |f| File.exist?(f) } diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb index 88cdd99dbd..5b29a13894 100644 --- a/activesupport/lib/active_support/inflector/inflections.rb +++ b/activesupport/lib/active_support/inflector/inflections.rb @@ -230,7 +230,6 @@ module ActiveSupport end private - def define_acronym_regex_patterns @acronym_regex = @acronyms.empty? ? /(?=a)b/ : /#{@acronyms.values.join("|")}/ @acronyms_camelize_regex = /^(?:#{@acronym_regex}(?=\b|[A-Z_])|\w)/ diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index ee193add6f..18f3f53879 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -359,7 +359,6 @@ module ActiveSupport end private - # Mounts a regular expression, returned as a string to ease interpolation, # that will match part by part the given constant. # diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb index 402a3fbe60..b4bf882bc3 100644 --- a/activesupport/lib/active_support/json/decoding.rb +++ b/activesupport/lib/active_support/json/decoding.rb @@ -44,7 +44,6 @@ module ActiveSupport end private - def convert_dates_from(data) case data when nil diff --git a/activesupport/lib/active_support/lazy_load_hooks.rb b/activesupport/lib/active_support/lazy_load_hooks.rb index a6b096a973..c6f7ccf0a2 100644 --- a/activesupport/lib/active_support/lazy_load_hooks.rb +++ b/activesupport/lib/active_support/lazy_load_hooks.rb @@ -54,7 +54,6 @@ module ActiveSupport end private - def with_execution_control(name, block, once) unless @run_once[name].include?(block) @run_once[name] << block if once diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb index 938cfdb914..db991c7a32 100644 --- a/activesupport/lib/active_support/log_subscriber.rb +++ b/activesupport/lib/active_support/log_subscriber.rb @@ -112,7 +112,6 @@ module ActiveSupport end private - %w(info debug warn error fatal unknown).each do |level| class_eval <<-METHOD, __FILE__, __LINE__ + 1 def #{level}(progname = nil, &block) diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index a1e23aeaca..2ba3936cae 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -207,7 +207,6 @@ module ActiveSupport #:nodoc: end private - def chars(string) self.class.new(string) end diff --git a/activesupport/lib/active_support/multibyte/unicode.rb b/activesupport/lib/active_support/multibyte/unicode.rb index ce8ecece69..3956137049 100644 --- a/activesupport/lib/active_support/multibyte/unicode.rb +++ b/activesupport/lib/active_support/multibyte/unicode.rb @@ -148,7 +148,6 @@ module ActiveSupport end private - def recode_windows1252_chars(string) string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace) end diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb index 12546511a8..7ab39c9bfb 100644 --- a/activesupport/lib/active_support/notifications/instrumenter.rb +++ b/activesupport/lib/active_support/notifications/instrumenter.rb @@ -46,7 +46,6 @@ module ActiveSupport end private - def unique_id SecureRandom.hex(10) end diff --git a/activesupport/lib/active_support/number_helper/number_converter.rb b/activesupport/lib/active_support/number_helper/number_converter.rb index 06ba797a13..76dd12f27d 100644 --- a/activesupport/lib/active_support/number_helper/number_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_converter.rb @@ -136,7 +136,6 @@ module ActiveSupport end private - def options @options ||= format_options.merge(opts) end diff --git a/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb b/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb index 0e8ae82dd5..4ad89dc62e 100644 --- a/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb @@ -21,7 +21,6 @@ module ActiveSupport end private - def absolute_value(number) number.respond_to?(:abs) ? number.abs : number.sub(/\A-/, "") end diff --git a/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb b/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb index 467a580a2e..351444289c 100644 --- a/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb @@ -14,7 +14,6 @@ module ActiveSupport end private - def parts left, right = number.to_s.split(".") left.gsub!(delimiter_pattern) do |digit_to_delimit| diff --git a/activesupport/lib/active_support/number_helper/number_to_human_converter.rb b/activesupport/lib/active_support/number_helper/number_to_human_converter.rb index 494408fc01..f089d7ae65 100644 --- a/activesupport/lib/active_support/number_helper/number_to_human_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_human_converter.rb @@ -31,7 +31,6 @@ module ActiveSupport end private - def format options[:format] || translate_in_locale("human.decimal_units.format") end diff --git a/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb b/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb index 91262fa656..ed8acbda6e 100644 --- a/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb @@ -28,7 +28,6 @@ module ActiveSupport end private - def conversion_format translate_number_value_with_default("human.storage_units.format", locale: options[:locale], raise: true) end diff --git a/activesupport/lib/active_support/number_helper/number_to_phone_converter.rb b/activesupport/lib/active_support/number_helper/number_to_phone_converter.rb index d5e72981b4..21eadfdcc7 100644 --- a/activesupport/lib/active_support/number_helper/number_to_phone_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_phone_converter.rb @@ -12,7 +12,6 @@ module ActiveSupport end private - def convert_to_phone_number(number) if opts[:area_code] convert_with_area_code(number) diff --git a/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb b/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb index 6ceb9a572e..767cfe22ad 100644 --- a/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb @@ -38,7 +38,6 @@ module ActiveSupport end private - def strip_insignificant_zeros options[:strip_insignificant_zeros] end diff --git a/activesupport/lib/active_support/parameter_filter.rb b/activesupport/lib/active_support/parameter_filter.rb index 1389d82523..8e5595babf 100644 --- a/activesupport/lib/active_support/parameter_filter.rb +++ b/activesupport/lib/active_support/parameter_filter.rb @@ -51,7 +51,6 @@ module ActiveSupport end private - def compiled_filter @compiled_filter ||= CompiledFilter.compile(@filters, mask: @mask) end diff --git a/activesupport/lib/active_support/string_inquirer.rb b/activesupport/lib/active_support/string_inquirer.rb index a3af36720e..e5091e127a 100644 --- a/activesupport/lib/active_support/string_inquirer.rb +++ b/activesupport/lib/active_support/string_inquirer.rb @@ -18,7 +18,6 @@ module ActiveSupport # vehicle.bike? # => false class StringInquirer < String private - def respond_to_missing?(method_name, include_private = false) (method_name[-1] == "?") || super end diff --git a/activesupport/lib/active_support/testing/stream.rb b/activesupport/lib/active_support/testing/stream.rb index 127cfe1e12..f895a74644 100644 --- a/activesupport/lib/active_support/testing/stream.rb +++ b/activesupport/lib/active_support/testing/stream.rb @@ -4,7 +4,6 @@ module ActiveSupport module Testing module Stream #:nodoc: private - def silence_stream(stream) old_stream = stream.dup stream.reopen(IO::NULL) diff --git a/activesupport/lib/active_support/testing/time_helpers.rb b/activesupport/lib/active_support/testing/time_helpers.rb index 5a3fa9346c..84bd920d86 100644 --- a/activesupport/lib/active_support/testing/time_helpers.rb +++ b/activesupport/lib/active_support/testing/time_helpers.rb @@ -40,7 +40,6 @@ module ActiveSupport end private - def unstub_object(stub) singleton_class = stub.object.singleton_class singleton_class.silence_redefinition_of_method stub.method_name @@ -191,7 +190,6 @@ module ActiveSupport end private - def simple_stubs @simple_stubs ||= SimpleStubs.new end diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index 075cd4ed8b..f6ae08bb5d 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -155,7 +155,6 @@ module ActiveSupport end private - def _dasherize(key) # $2 must be a non-greedy regex for this to work left, middle, right = /\A(_*)(.*?)(_*)\Z/.match(key.strip)[1, 3] diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb index 32fe6ade28..12ca19a76f 100644 --- a/activesupport/lib/active_support/xml_mini/jdom.rb +++ b/activesupport/lib/active_support/xml_mini/jdom.rb @@ -53,7 +53,6 @@ module ActiveSupport end private - # Convert an XML element and merge into the hash # # hash:: diff --git a/activesupport/test/cache/behaviors/cache_store_behavior.rb b/activesupport/test/cache/behaviors/cache_store_behavior.rb index a696760bb2..e6f014e08d 100644 --- a/activesupport/test/cache/behaviors/cache_store_behavior.rb +++ b/activesupport/test/cache/behaviors/cache_store_behavior.rb @@ -507,7 +507,6 @@ module CacheStoreBehavior end private - def assert_compressed(value, **options) assert_compression(true, value, **options) end diff --git a/activesupport/test/cache/cache_key_test.rb b/activesupport/test/cache/cache_key_test.rb index c2240d03c2..f0cd991553 100644 --- a/activesupport/test/cache/cache_key_test.rb +++ b/activesupport/test/cache/cache_key_test.rb @@ -79,7 +79,6 @@ class CacheKeyTest < ActiveSupport::TestCase end private - def with_env(kv) old_values = {} kv.each { |key, value| old_values[key], ENV[key] = ENV[key], value } diff --git a/activesupport/test/cache/stores/mem_cache_store_test.rb b/activesupport/test/cache/stores/mem_cache_store_test.rb index 0e472f5a1a..3917d14d1c 100644 --- a/activesupport/test/cache/stores/mem_cache_store_test.rb +++ b/activesupport/test/cache/stores/mem_cache_store_test.rb @@ -113,7 +113,6 @@ class MemCacheStoreTest < ActiveSupport::TestCase end private - def store [:mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211"] end diff --git a/activesupport/test/cache/stores/redis_cache_store_test.rb b/activesupport/test/cache/stores/redis_cache_store_test.rb index 790534cd3c..a2177e0476 100644 --- a/activesupport/test/cache/stores/redis_cache_store_test.rb +++ b/activesupport/test/cache/stores/redis_cache_store_test.rb @@ -191,7 +191,6 @@ module ActiveSupport::Cache::RedisCacheStoreTests include ConnectionPoolBehavior private - def store [:redis_cache_store] end @@ -238,7 +237,6 @@ module ActiveSupport::Cache::RedisCacheStoreTests include FailureSafetyBehavior private - def emulating_unavailability old_client = Redis.send(:remove_const, :Client) Redis.const_set(:Client, UnavailableRedisClient) diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index 79098b2a7d..cc37c4fa99 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -397,7 +397,6 @@ module CallbacksTest end private - def record1 @recorder << 1 end @@ -989,6 +988,7 @@ module CallbacksTest define_callbacks :foo, scope: [:name] set_callback :foo, :before, :foo, if: callback def run; run_callbacks :foo; end + private def foo; end } diff --git a/activesupport/test/core_ext/date_and_time_behavior.rb b/activesupport/test/core_ext/date_and_time_behavior.rb index b77ea22701..6d31734f27 100644 --- a/activesupport/test/core_ext/date_and_time_behavior.rb +++ b/activesupport/test/core_ext/date_and_time_behavior.rb @@ -8,31 +8,11 @@ module DateAndTimeBehavior assert_equal date_time_init(2005, 2, 28, 10, 10, 10), date_time_init(2005, 3, 2, 10, 10, 10).yesterday.yesterday end - def test_prev_day - assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-2) - assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-1) - assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(0) - assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(1) - assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(2) - assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day - assert_equal date_time_init(2005, 2, 28, 10, 10, 10), date_time_init(2005, 3, 2, 10, 10, 10).prev_day.prev_day - end - def test_tomorrow assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).tomorrow assert_equal date_time_init(2005, 3, 2, 10, 10, 10), date_time_init(2005, 2, 28, 10, 10, 10).tomorrow.tomorrow end - def test_next_day - assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-2) - assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-1) - assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(0) - assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(1) - assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(2) - assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day - assert_equal date_time_init(2005, 3, 2, 10, 10, 10), date_time_init(2005, 2, 28, 10, 10, 10).next_day.next_day - end - def test_days_ago assert_equal date_time_init(2005, 6, 4, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).days_ago(1) assert_equal date_time_init(2005, 5, 31, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).days_ago(5) @@ -161,16 +141,6 @@ module DateAndTimeBehavior assert_equal date_time_init(2015, 1, 5, 15, 15, 10), date_time_init(2015, 1, 3, 15, 15, 10).next_weekday end - def test_next_month - assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-2) - assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-1) - assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(0) - assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(1) - assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(2) - assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month - assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month.next_month - end - def test_next_month_on_31st assert_equal date_time_init(2005, 9, 30, 15, 15, 10), date_time_init(2005, 8, 31, 15, 15, 10).next_month end @@ -179,16 +149,6 @@ module DateAndTimeBehavior assert_equal date_time_init(2005, 11, 30, 15, 15, 10), date_time_init(2005, 8, 31, 15, 15, 10).next_quarter end - def test_next_year - assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-2) - assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-1) - assert_equal date_time_init(2005, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(0) - assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(1) - assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(2) - assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year - assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year.next_year - end - def test_prev_week assert_equal date_time_init(2005, 2, 21, 0, 0, 0), date_time_init(2005, 3, 1, 15, 15, 10).prev_week assert_equal date_time_init(2005, 2, 22, 0, 0, 0), date_time_init(2005, 3, 1, 15, 15, 10).prev_week(:tuesday) @@ -229,16 +189,6 @@ module DateAndTimeBehavior assert_equal date_time_init(2015, 1, 2, 15, 15, 10), date_time_init(2015, 1, 4, 15, 15, 10).prev_weekday end - def test_prev_month - assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-2) - assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-1) - assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(0) - assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(1) - assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(2) - assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month - assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month.prev_month - end - def test_prev_month_on_31st assert_equal date_time_init(2004, 2, 29, 10, 10, 10), date_time_init(2004, 3, 31, 10, 10, 10).prev_month end @@ -247,16 +197,6 @@ module DateAndTimeBehavior assert_equal date_time_init(2004, 2, 29, 10, 10, 10), date_time_init(2004, 5, 31, 10, 10, 10).prev_quarter end - def test_prev_year - assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(-2) - assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(-1) - assert_equal date_time_init(2005, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(0) - assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(1) - assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(2) - assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year - assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year.prev_year - end - def test_last_month_on_31st assert_equal date_time_init(2004, 2, 29, 0, 0, 0), date_time_init(2004, 3, 31, 0, 0, 0).last_month end diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index b8652884ce..7060dd3c56 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -112,14 +112,6 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(2005, 4, 30), Date.new(2005, 4, 20).end_of_month end - def test_prev_year_in_leap_years - assert_equal Date.new(1999, 2, 28), Date.new(2000, 2, 29).prev_year - end - - def test_prev_year_in_calendar_reform - assert_equal Date.new(1582, 10, 4), Date.new(1583, 10, 14).prev_year - end - def test_last_year_in_leap_years assert_equal Date.new(1999, 2, 28), Date.new(2000, 2, 29).last_year end @@ -128,14 +120,6 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(1582, 10, 4), Date.new(1583, 10, 14).last_year end - def test_next_year_in_leap_years - assert_equal Date.new(2001, 2, 28), Date.new(2000, 2, 29).next_year - end - - def test_next_year_in_calendar_reform - assert_equal Date.new(1582, 10, 4), Date.new(1581, 10, 10).next_year - end - def test_advance assert_equal Date.new(2006, 2, 28), Date.new(2005, 2, 28).advance(years: 1) assert_equal Date.new(2005, 6, 28), Date.new(2005, 2, 28).advance(months: 4) diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index 6e341480d1..ec9ecd06ee 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -25,7 +25,6 @@ Someone = Struct.new(:name, :place) do delegate :bar, to: :place, allow_nil: true private - def private_name "Private" end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 590b81b770..41ab98e721 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -949,6 +949,66 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal "invalid date", exception.message end + + def test_prev_day + assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-2) + assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(0) + assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(1) + assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(2) + assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day + assert_equal date_time_init(2005, 2, 28, 10, 10, 10), date_time_init(2005, 3, 2, 10, 10, 10).prev_day.prev_day + end + + def test_next_day + assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-2) + assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(0) + assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(1) + assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(2) + assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day + assert_equal date_time_init(2005, 3, 2, 10, 10, 10), date_time_init(2005, 2, 28, 10, 10, 10).next_day.next_day + end + + def test_prev_month + assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-2) + assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(0) + assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(1) + assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(2) + assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month + assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month.prev_month + end + + def test_next_month + assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-2) + assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(0) + assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(1) + assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(2) + assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month + assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month.next_month + end + + def test_prev_year + assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(-2) + assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(-1) + assert_equal date_time_init(2005, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(0) + assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(1) + assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(2) + assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year + assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year.prev_year + end + + def test_next_year + assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-2) + assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-1) + assert_equal date_time_init(2005, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(0) + assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(1) + assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(2) + assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year + assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year.next_year + end end class TimeExtMarshalingTest < ActiveSupport::TestCase diff --git a/activesupport/test/deprecation/method_wrappers_test.rb b/activesupport/test/deprecation/method_wrappers_test.rb index 0aa3233aab..8c40534452 100644 --- a/activesupport/test/deprecation/method_wrappers_test.rb +++ b/activesupport/test/deprecation/method_wrappers_test.rb @@ -10,12 +10,10 @@ class MethodWrappersTest < ActiveSupport::TestCase alias_method :old_method, :new_method protected - def new_protected_method; "abc" end alias_method :old_protected_method, :new_protected_method private - def new_private_method; "abc" end alias_method :old_private_method, :new_private_method end diff --git a/activesupport/test/descendants_tracker_test_cases.rb b/activesupport/test/descendants_tracker_test_cases.rb index f8752688d2..7d39783826 100644 --- a/activesupport/test/descendants_tracker_test_cases.rb +++ b/activesupport/test/descendants_tracker_test_cases.rb @@ -52,7 +52,6 @@ module DescendantsTrackerTestCases end private - def assert_equal_sets(expected, actual) assert_equal Set.new(expected), Set.new(actual) end diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index 8d9587f248..2e8ea01aca 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -113,7 +113,6 @@ class TestJSONDecoding < ActiveSupport::TestCase end private - def with_parse_json_times(value) old_value = ActiveSupport.parse_json_times ActiveSupport.parse_json_times = value diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index 7589ffd0ea..c4e0b71f26 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -466,7 +466,6 @@ EXPECTED end private - def object_keys(json_object) json_object[1..-2].scan(/([^{}:,\s]+):/).flatten.sort end diff --git a/activesupport/test/lazy_load_hooks_test.rb b/activesupport/test/lazy_load_hooks_test.rb index 50a703e49f..5e9a21f047 100644 --- a/activesupport/test/lazy_load_hooks_test.rb +++ b/activesupport/test/lazy_load_hooks_test.rb @@ -175,7 +175,6 @@ class LazyLoadHooksTest < ActiveSupport::TestCase end private - def incr_amt 5 end diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index 5f4e3f3fd3..e0e0d9afc0 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -783,7 +783,6 @@ class MultibyteCharsExtrasTest < ActiveSupport::TestCase end private - def string_from_classes(classes) # Characters from the character classes as described in UAX #29 character_from_class = { diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index 02b90b0297..c9c63680e4 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -20,7 +20,6 @@ module Notifications end private - def event(*args) ActiveSupport::Notifications::Event.new(*args) end diff --git a/activesupport/test/share_lock_test.rb b/activesupport/test/share_lock_test.rb index a40c813fe3..68e78ccc16 100644 --- a/activesupport/test/share_lock_test.rb +++ b/activesupport/test/share_lock_test.rb @@ -488,12 +488,10 @@ class ShareLockTest < ActiveSupport::TestCase end private - module CustomAssertions SUFFICIENT_TIMEOUT = 0.2 private - def assert_threads_stuck_but_releasable_by_latch(threads, latch) assert_threads_stuck threads latch.count_down diff --git a/activesupport/test/subscriber_test.rb b/activesupport/test/subscriber_test.rb index bc8d8f1c13..829fba6057 100644 --- a/activesupport/test/subscriber_test.rb +++ b/activesupport/test/subscriber_test.rb @@ -17,7 +17,6 @@ class TestSubscriber < ActiveSupport::Subscriber end private - def private_party(event) events << event end diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb index 56cd2665e0..dd75548e9c 100644 --- a/activesupport/test/test_case_test.rb +++ b/activesupport/test/test_case_test.rb @@ -315,7 +315,6 @@ class SetupAndTeardownTest < ActiveSupport::TestCase end private - def reset_callback_record @called_back = [] end diff --git a/guides/assets/images/getting_started/unknown_action_create_for_articles.png b/guides/assets/images/getting_started/unknown_action_create_for_articles.png Binary files differindex ec4758e085..e75b9780cc 100644 --- a/guides/assets/images/getting_started/unknown_action_create_for_articles.png +++ b/guides/assets/images/getting_started/unknown_action_create_for_articles.png diff --git a/guides/rails_guides/generator.rb b/guides/rails_guides/generator.rb index 7d4a15962c..2b2ccfa906 100644 --- a/guides/rails_guides/generator.rb +++ b/guides/rails_guides/generator.rb @@ -43,7 +43,6 @@ module RailsGuides end private - def register_kindle_mime_types Mime::Type.register_alias("application/xml", :opf, %w(opf)) Mime::Type.register_alias("application/xml", :ncx, %w(ncx)) diff --git a/guides/rails_guides/indexer.rb b/guides/rails_guides/indexer.rb index c707464cdf..576ec85b27 100644 --- a/guides/rails_guides/indexer.rb +++ b/guides/rails_guides/indexer.rb @@ -18,7 +18,6 @@ module RailsGuides end private - def process(string, current_level = 3, counters = [1]) s = StringScanner.new(string) diff --git a/guides/rails_guides/markdown.rb b/guides/rails_guides/markdown.rb index 018f49ffd0..d926d233bb 100644 --- a/guides/rails_guides/markdown.rb +++ b/guides/rails_guides/markdown.rb @@ -30,7 +30,6 @@ module RailsGuides end private - def dom_id(nodes) dom_id = dom_id_text(nodes.last.text) diff --git a/guides/rails_guides/markdown/renderer.rb b/guides/rails_guides/markdown/renderer.rb index 7f14c28bbc..4877e806fd 100644 --- a/guides/rails_guides/markdown/renderer.rb +++ b/guides/rails_guides/markdown/renderer.rb @@ -53,7 +53,6 @@ HTML end private - def convert_footnotes(text) text.gsub(/\[<sup>(\d+)\]<\/sup>/i) do %(<sup class="footnote" id="footnote-#{$1}-ref">) + diff --git a/guides/source/6_0_release_notes.md b/guides/source/6_0_release_notes.md index c826b19f1a..c152076628 100644 --- a/guides/source/6_0_release_notes.md +++ b/guides/source/6_0_release_notes.md @@ -513,7 +513,7 @@ Please refer to the [Changelog][active-record] for detailed changes. ([Pull Request](https://github.com/rails/rails/pull/34742)) * Add the ability to disable scopes generated by `ActiveRecord.enum`. - ([Pull Request](https://github.com/rails/rails/pull/34605/files)) + ([Pull Request](https://github.com/rails/rails/pull/34605)) * Make implicit ordering configurable for a column. ([Pull Request](https://github.com/rails/rails/pull/34480)) diff --git a/guides/source/action_text_overview.md b/guides/source/action_text_overview.md index 07919775e2..a735ec2b0e 100644 --- a/guides/source/action_text_overview.md +++ b/guides/source/action_text_overview.md @@ -46,6 +46,8 @@ happens after every keystroke, and avoids the need to use execCommand at all. ## Installation Run `rails action_text:install` to add the Yarn package and copy over the necessary migration. +Also, you need to set up Active Storage for embedded images and other attachments. +Please refer to the [Active Storage Overview](active_storage_overview.html) guide. ## Examples diff --git a/guides/source/active_record_multiple_databases.md b/guides/source/active_record_multiple_databases.md index 51f5cab2aa..07be21a254 100644 --- a/guides/source/active_record_multiple_databases.md +++ b/guides/source/active_record_multiple_databases.md @@ -32,6 +32,7 @@ The following features are not (yet) supported: * Sharding * Joining across clusters * Load balancing replicas +* Dumping schema caches for multiple databases ## Setting up your application @@ -121,6 +122,12 @@ config.active_record.writing_role = :default config.active_record.reading_role = :readonly ``` +It's important to connect to your database in a single model and then inherit from that model +for the tables rather than connect multiple individual models to the same database. Database +clients have a limit to the number of open connections there can be and if you do this it will +multiply the number of connections you have since Rails uses the model class name for the +connection specification name. + Now that we have the database.yml and the new model set up it's time to create the databases. Rails 6.0 ships with all the rails tasks you need to use multiple databases in Rails. @@ -173,7 +180,7 @@ to primary based on the HTTP verb and whether there was a recent write. If the application is receiving a POST, PUT, DELETE, or PATCH request the application will automatically write to the primary. For the specified time after the write the application -will read from the replica. For a GET or HEAD request the application will read from the +will read from the primary. For a GET or HEAD request the application will read from the replica unless there was a recent write. To activate the automatic connection switching middleware, add or uncomment the following @@ -253,17 +260,29 @@ for the 'nonexistent' role.)` ## Caveats +### Sharding + As noted at the top, Rails doesn't (yet) support sharding. We had to do a lot of work to support multiple databases for Rails 6.0. The lack of support for sharding isn't an oversight, but does require additional work that didn't make it in for 6.0. For now if you need sharding it may be advisable to continue using one of the many gems that supports this. +### Load Balancing Replicas + Rails also doesn't support automatic load balancing of replicas. This is very dependent on your infrastructure. We may implement basic, primitive load balancing in the future, but for an application at scale this should be something your application handles outside of Rails. -Lastly, you cannot join across databases. Rails 6.1 will support using `has_many` +### Joining Across Databases + +Applications cannot join across databases. Rails 6.1 will support using `has_many` relationships and creating 2 queries instead of joining, but Rails 6.0 will require you to split the joins into 2 selects manually. + +### Schema Cache + +If you use a schema cache and multiple databases you'll need to write an initializer +that loads the schema cache from your app. This wasn't an issue we could resolve in +time for Rails 6.0 but hope to have it in a future version soon. diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index 21901a7158..8cb49ca6ae 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -3416,56 +3416,56 @@ NOTE: Defined in `active_support/core_ext/date_and_time/calculations.rb`. #### `prev_day`, `next_day` -In Ruby 1.9 `prev_day` and `next_day` return the date in the last or next day: +`prev_day` and `next_day` return the time in the last or next day: ```ruby -d = Date.new(2010, 5, 8) # => Sat, 08 May 2010 -d.prev_day # => Fri, 07 May 2010 -d.next_day # => Sun, 09 May 2010 +t = Time.new(2010, 5, 8) # => 2010-05-08 00:00:00 +0900 +t.prev_day # => 2010-05-07 00:00:00 +0900 +t.next_day # => 2010-05-09 00:00:00 +0900 ``` -NOTE: Defined in `active_support/core_ext/date_and_time/calculations.rb`. +NOTE: Defined in `active_support/core_ext/time/calculations.rb`. #### `prev_month`, `next_month` -In Ruby 1.9 `prev_month` and `next_month` return the date with the same day in the last or next month: +`prev_month` and `next_month` return the time with the same day in the last or next month: ```ruby -d = Date.new(2010, 5, 8) # => Sat, 08 May 2010 -d.prev_month # => Thu, 08 Apr 2010 -d.next_month # => Tue, 08 Jun 2010 +t = Time.new(2010, 5, 8) # => 2010-05-08 00:00:00 +0900 +t.prev_month # => 2010-04-08 00:00:00 +0900 +t.next_month # => 2010-06-08 00:00:00 +0900 ``` If such a day does not exist, the last day of the corresponding month is returned: ```ruby -Date.new(2000, 5, 31).prev_month # => Sun, 30 Apr 2000 -Date.new(2000, 3, 31).prev_month # => Tue, 29 Feb 2000 -Date.new(2000, 5, 31).next_month # => Fri, 30 Jun 2000 -Date.new(2000, 1, 31).next_month # => Tue, 29 Feb 2000 +Time.new(2000, 5, 31).prev_month # => 2000-04-30 00:00:00 +0900 +Time.new(2000, 3, 31).prev_month # => 2000-02-29 00:00:00 +0900 +Time.new(2000, 5, 31).next_month # => 2000-06-30 00:00:00 +0900 +Time.new(2000, 1, 31).next_month # => 2000-02-29 00:00:00 +0900 ``` -NOTE: Defined in `active_support/core_ext/date_and_time/calculations.rb`. +NOTE: Defined in `active_support/core_ext/time/calculations.rb`. #### `prev_year`, `next_year` -In Ruby 1.9 `prev_year` and `next_year` return a date with the same day/month in the last or next year: +`prev_year` and `next_year` return a time with the same day/month in the last or next year: ```ruby -d = Date.new(2010, 5, 8) # => Sat, 08 May 2010 -d.prev_year # => Fri, 08 May 2009 -d.next_year # => Sun, 08 May 2011 +t = Time.new(2010, 5, 8) # => 2010-05-08 00:00:00 +0900 +t.prev_year # => 2009-05-08 00:00:00 +0900 +t.next_year # => 2011-05-08 00:00:00 +0900 ``` If date is the 29th of February of a leap year, you obtain the 28th: ```ruby -d = Date.new(2000, 2, 29) # => Tue, 29 Feb 2000 -d.prev_year # => Sun, 28 Feb 1999 -d.next_year # => Wed, 28 Feb 2001 +t = Time.new(2000, 2, 29) # => 2000-02-29 00:00:00 +0900 +t.prev_year # => 1999-02-28 00:00:00 +0900 +t.next_year # => 2001-02-28 00:00:00 +0900 ``` -NOTE: Defined in `active_support/core_ext/date_and_time/calculations.rb`. +NOTE: Defined in `active_support/core_ext/time/calculations.rb`. #### `prev_quarter`, `next_quarter` diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 4651290674..e53e8b4e92 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -553,6 +553,10 @@ Defaults to `'signed cookie'`. Any exceptions that are not configured will be mapped to 500 Internal Server Error. +* `config.action_dispatch.return_only_media_type_on_content_type` change the + return value of `ActionDispatch::Response#content_type` to the Content-Type + header without modification. Defaults to `false`. + * `ActionDispatch::Callbacks.before` takes a block of code to run before the request. * `ActionDispatch::Callbacks.after` takes a block of code to run after the request. @@ -835,10 +839,10 @@ You can find more detailed configuration options in the config.active_storage.paths[:ffprobe] = '/usr/local/bin/ffprobe' ``` -* `config.active_storage.variable_content_types` accepts an array of strings indicating the content types that Active Storage can transform through ImageMagick. The default is `%w(image/png image/gif image/jpg image/jpeg image/pjpeg image/tiff image/vnd.adobe.photoshop image/vnd.microsoft.icon)`. +* `config.active_storage.variable_content_types` accepts an array of strings indicating the content types that Active Storage can transform through ImageMagick. The default is `%w(image/png image/gif image/jpg image/jpeg image/pjpeg image/tiff image/bmp image/vnd.adobe.photoshop image/vnd.microsoft.icon)`. * `config.active_storage.content_types_to_serve_as_binary` accepts an array of strings indicating the content types that Active Storage will always serve as an attachment, rather than inline. The default is `%w(text/html -text/javascript image/svg+xml application/postscript application/x-shockwave-flash text/xml application/xml application/xhtml+xml)`. +text/javascript image/svg+xml application/postscript application/x-shockwave-flash text/xml application/xml application/xhtml+xml application/mathml+xml text/cache-manifest)`. * `config.active_storage.queues.analysis` accepts a symbol indicating the Active Job queue to use for analysis jobs. When this option is `nil`, analysis jobs are sent to the default Active Job queue (see `config.active_job.default_queue_name`). @@ -908,6 +912,7 @@ text/javascript image/svg+xml application/postscript application/x-shockwave-fla - `config.autoloader`: `:zeitwerk` - `config.action_view.default_enforce_utf8`: `false` - `config.action_dispatch.use_cookies_with_metadata`: `true` +- `config.action_dispatch.return_only_media_type_on_content_type`: `false` - `config.action_mailer.delivery_job`: `"ActionMailer::MailDeliveryJob"` - `config.active_job.return_false_on_aborted_enqueue`: `true` - `config.active_storage.queues.analysis`: `:active_storage_analysis` @@ -1536,7 +1541,7 @@ Disallow: / ``` To block just specific pages, it's necessary to use a more complex syntax. Learn -it on the [official documentation](http://www.robotstxt.org/robotstxt.html). +it on the [official documentation](https://www.robotstxt.org/robotstxt.html). Evented File System Monitor --------------------------- diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md index d3706a4dbf..9c28ff6a9c 100644 --- a/guides/source/contributing_to_ruby_on_rails.md +++ b/guides/source/contributing_to_ruby_on_rails.md @@ -139,7 +139,7 @@ changes to the master branch. When working with documentation, please take into account the [API Documentation Guidelines](api_documentation_guidelines.html) and the [Ruby on Rails Guides Guidelines](ruby_on_rails_guides_guidelines.html). -NOTE: To help our CI servers you should add [ci skip] to your documentation commit message to skip build on that commit. Please remember to use it for commits containing only documentation changes. +NOTE: For documentation changes, your commit message should include [ci skip]. This will skip running the test suite, helping us to cut down on our server costs. Keep in mind that you should only skip CI when your change touches documentation exclusively. Translating Rails Guides ------------------------ diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md index 64f4a3b6b3..ce45dbb2a7 100644 --- a/guides/source/getting_started.md +++ b/guides/source/getting_started.md @@ -28,7 +28,7 @@ curve diving straight into Rails. There are several curated lists of online reso for learning Ruby: * [Official Ruby Programming Language website](https://www.ruby-lang.org/en/documentation/) -* [List of Free Programming Books](https://github.com/vhf/free-programming-books/blob/master/free-programming-books.md#ruby) +* [List of Free Programming Books](https://github.com/EbookFoundation/free-programming-books/blob/master/free-programming-books.md#ruby) Be aware that some resources, while still excellent, cover versions of Ruby as old as 1.6, and commonly 1.8, and will not include some syntax that you will see in day-to-day diff --git a/guides/source/initialization.md b/guides/source/initialization.md index c41eae18cf..556c85cc0f 100644 --- a/guides/source/initialization.md +++ b/guides/source/initialization.md @@ -108,6 +108,8 @@ A standard Rails application depends on several gems, specifically: * activerecord * activestorage * activesupport +* actionmailbox +* actiontext * arel * builder * bundler @@ -160,8 +162,8 @@ namespace and executes the command if found. If Rails doesn't recognize the command, it hands the reins over to Rake to run a task of the same name. -As shown, `Rails::Command` displays the help output automatically if the `args` -are empty. +As shown, `Rails::Command` displays the help output automatically if the `namespace` +is empty. ```ruby module Rails::Command @@ -289,7 +291,7 @@ def default_options environment: (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup, daemonize: false, caching: nil, - pid: Options::DEFAULT_PID_PATH, + pid: ENV.fetch("PIDFILE", Options::DEFAULT_PIDFILE).dup, restart_cmd: restart_command) end ``` @@ -538,6 +540,8 @@ require "rails" action_mailer/railtie active_job/railtie action_cable/engine + action_mailbox/engine + action_text/engine rails/test_unit/railtie sprockets/railtie ).each do |railtie| diff --git a/guides/source/security.md b/guides/source/security.md index 22c122d4b9..5bb7a51524 100644 --- a/guides/source/security.md +++ b/guides/source/security.md @@ -1211,4 +1211,4 @@ The security landscape shifts and it is important to keep up to date, because mi * Subscribe to the Rails security [mailing list](https://groups.google.com/forum/#!forum/rubyonrails-security). * [Brakeman - Rails Security Scanner](https://brakemanscanner.org/) - To perform static security analysis for Rails applications. * [Keep up to date on the other application layers](http://secunia.com/) (they have a weekly newsletter, too). -* A [good security blog](https://www.owasp.org) including the [Cross-Site scripting Cheat Sheet](https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet). +* A [good security blog](https://www.owasp.org) including the [Cross-Site scripting Cheat Sheet](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md). diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index 54f014293d..4192063e9b 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -270,6 +270,16 @@ In that case, `app/models/concerns` is assumed to be a root directory (because i The `Concerns::` namespace worked with the classic autoloader as a side-effect of the implementation, but it was not really an intended behavior. An application using `Concerns::` needs to rename those classes and modules to be able to run in `zeitwerk` mode. +#### Having `app` in the autoload paths + +Some projects want something like `app/api/base.rb` to define `API::Base`, and add `app` to the autoload paths to accomplish that in `classic` mode. Since Rails adds all subdirectories of `app` to the autoload paths automatically, we have another situation in which there are nested root directories, so that setup no longer works. Similar principle we explained above with `concerns`. + +If you want to keep that structure, you'll need to delete the subdirectory from the autoload paths in an initializer: + +```ruby +ActiveSupport::Dependencies.autoload_paths.delete("#{Rails.root}/app/api") +``` + #### Autoloaded Constants and Explicit Namespaces If a namespace is defined in a file, as `Hotel` is here: @@ -391,6 +401,12 @@ To fix this, just remove the wildcards: config.autoload_paths << "#{config.root}/lib" ``` +#### Eager loading and autoloading are consistent + +In `classic` mode, if `app/models/foo.rb` defines `Bar`, you won't be able to autoload that file, but eager loading will work because it loads files recursively blindly. This can be a source of errors if you test things first eager loading, execution may fail later autoloading. + +In `zeitwerk` mode both loading modes are consistent, they fail and err in the same files. + #### How to Use the Classic Autoloader in Rails 6 Applications can load Rails 6 defaults and still use the classic autoloader by setting `config.autoloader` this way: diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 7bc7391f9e..cfb30719da 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,5 @@ +* Support using environment variable to set pidfile + *Ben Thorner* Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/railties/CHANGELOG.md) for previous changes. diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 038284ebdd..225152c50b 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -270,7 +270,8 @@ module Rails "action_dispatch.use_cookies_with_metadata" => config.action_dispatch.use_cookies_with_metadata, "action_dispatch.content_security_policy" => config.content_security_policy, "action_dispatch.content_security_policy_report_only" => config.content_security_policy_report_only, - "action_dispatch.content_security_policy_nonce_generator" => config.content_security_policy_nonce_generator + "action_dispatch.content_security_policy_nonce_generator" => config.content_security_policy_nonce_generator, + "action_dispatch.content_security_policy_nonce_directives" => config.content_security_policy_nonce_directives ) end end @@ -501,7 +502,6 @@ module Rails end protected - alias :build_middleware_stack :app def run_tasks_blocks(app) #:nodoc: @@ -581,7 +581,6 @@ module Rails end private - def generate_development_secret if secrets.secret_key_base.nil? key_file = Rails.root.join("tmp/development_secret.txt") @@ -623,7 +622,6 @@ module Rails end private - def convert_key(key) unless key.kind_of?(Symbol) ActiveSupport::Deprecation.warn(<<~MESSAGE.squish) diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index da1c433e52..f5456f4916 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -18,8 +18,8 @@ module Rails :session_options, :time_zone, :reload_classes_only_on_change, :beginning_of_week, :filter_redirect, :x, :enable_dependency_loading, :read_encrypted_secrets, :log_level, :content_security_policy_report_only, - :content_security_policy_nonce_generator, :require_master_key, :credentials, - :disable_sandbox, :add_autoload_paths_to_load_path + :content_security_policy_nonce_generator, :content_security_policy_nonce_directives, + :require_master_key, :credentials, :disable_sandbox, :add_autoload_paths_to_load_path attr_reader :encoding, :api_only, :loaded_config_version, :autoloader @@ -60,6 +60,7 @@ module Rails @content_security_policy = nil @content_security_policy_report_only = false @content_security_policy_nonce_generator = nil + @content_security_policy_nonce_directives = nil @require_master_key = false @loaded_config_version = nil @credentials = ActiveSupport::OrderedOptions.new @@ -129,6 +130,7 @@ module Rails if respond_to?(:action_dispatch) action_dispatch.use_cookies_with_metadata = true + action_dispatch.return_only_media_type_on_content_type = false end if respond_to?(:action_mailer) diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb index 9800b19274..3659c0ac3a 100644 --- a/railties/lib/rails/application/default_middleware_stack.rb +++ b/railties/lib/rails/application/default_middleware_stack.rb @@ -79,7 +79,6 @@ module Rails end private - def load_rack_cache rack_cache = config.action_dispatch.rack_cache return unless rack_cache diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb index 3ecb8e264e..1070362253 100644 --- a/railties/lib/rails/application/routes_reloader.rb +++ b/railties/lib/rails/application/routes_reloader.rb @@ -25,7 +25,6 @@ module Rails end private - def updater @updater ||= ActiveSupport::FileUpdateChecker.new(paths) { reload! } end diff --git a/railties/lib/rails/application_controller.rb b/railties/lib/rails/application_controller.rb index b3fe822218..8c00633515 100644 --- a/railties/lib/rails/application_controller.rb +++ b/railties/lib/rails/application_controller.rb @@ -12,7 +12,6 @@ class Rails::ApplicationController < ActionController::Base # :nodoc: end private - def require_local! unless local_request? render html: "<p>For security purposes, this information is only available to local requests.</p>".html_safe, status: :forbidden diff --git a/railties/lib/rails/command/spellchecker.rb b/railties/lib/rails/command/spellchecker.rb index 085d5b16df..c5d0253185 100644 --- a/railties/lib/rails/command/spellchecker.rb +++ b/railties/lib/rails/command/spellchecker.rb @@ -13,7 +13,6 @@ module Rails end private - # This code is based directly on the Text gem implementation. # Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher. # diff --git a/railties/lib/rails/commands/server/server_command.rb b/railties/lib/rails/commands/server/server_command.rb index 982b83ead5..84248e03c1 100644 --- a/railties/lib/rails/commands/server/server_command.rb +++ b/railties/lib/rails/commands/server/server_command.rb @@ -99,7 +99,7 @@ module Rails RACK_SERVERS = %w(cgi fastcgi webrick lsws scgi thin puma unicorn) DEFAULT_PORT = 3000 - DEFAULT_PID_PATH = "tmp/pids/server.pid" + DEFAULT_PIDFILE = "tmp/pids/server.pid" argument :using, optional: true @@ -114,8 +114,8 @@ module Rails desc: "Runs server as a Daemon." class_option :using, aliases: "-u", type: :string, desc: "Specifies the Rack server used to run the application (thin/puma/webrick).", banner: :name - class_option :pid, aliases: "-P", type: :string, default: DEFAULT_PID_PATH, - desc: "Specifies the PID file." + class_option :pid, aliases: "-P", type: :string, + desc: "Specifies the PID file - defaults to #{DEFAULT_PIDFILE}." class_option :dev_caching, aliases: "-C", type: :boolean, default: nil, desc: "Specifies whether to perform caching in development." class_option :restart, type: :boolean, default: nil, hide: true @@ -207,6 +207,7 @@ module Rails end user_supplied_options << :Host if ENV["HOST"] || ENV["BINDING"] user_supplied_options << :Port if ENV["PORT"] + user_supplied_options << :pid if ENV["PIDFILE"] user_supplied_options.uniq end end @@ -253,7 +254,7 @@ module Rails end def pid - File.expand_path(options[:pid]) + File.expand_path(options[:pid] || ENV.fetch("PIDFILE", DEFAULT_PIDFILE)) end def self.banner(*) @@ -261,7 +262,7 @@ module Rails end def prepare_restart - FileUtils.rm_f(options[:pid]) if options[:restart] + FileUtils.rm_f(pid) if options[:restart] end def deprecate_positional_rack_server_and_rewrite_to_option(original_options) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index d1b8c7803f..46f1d38b96 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -654,14 +654,12 @@ module Rails end protected - def run_tasks_blocks(*) #:nodoc: super paths["lib/tasks"].existent.sort.each { |ext| load(ext) } end private - def load_config_initializer(initializer) # :doc: ActiveSupport::Notifications.instrument("load_config_initializer.railties", initializer: initializer) do load(initializer) diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 0be00d5151..709863275d 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -287,7 +287,6 @@ module Rails end private - def print_list(base, namespaces) # :doc: namespaces = namespaces.reject { |n| hidden_namespaces.include?(n) } super diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 1a5f2ff203..406a5b8fc7 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -268,7 +268,6 @@ module Rails end private - # Define log for backwards compatibility. If just one argument is sent, # invoke say, otherwise invoke say_status. Differently from say and # similarly to say_status, this method respects the quiet? option given. diff --git a/railties/lib/rails/generators/actions/create_migration.rb b/railties/lib/rails/generators/actions/create_migration.rb index 05bc242447..67a8139cd3 100644 --- a/railties/lib/rails/generators/actions/create_migration.rb +++ b/railties/lib/rails/generators/actions/create_migration.rb @@ -40,7 +40,6 @@ module Rails alias :exists? :existing_migration private - def on_conflict_behavior # :doc: options = base.options.merge(config) if identical? diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 303073d867..dbfb7337f0 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -108,7 +108,6 @@ module Rails end private - def gemfile_entry(name, *args) # :doc: options = args.extract_options! version = args.first diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index 5523a3f659..0b91e3223e 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -245,7 +245,6 @@ module Rails end private - # Check whether the given class names are already taken by user # application or Ruby on Rails. def class_collisions(*class_names) diff --git a/railties/lib/rails/generators/erb.rb b/railties/lib/rails/generators/erb.rb index ba20bcd32a..aab2d634d3 100644 --- a/railties/lib/rails/generators/erb.rb +++ b/railties/lib/rails/generators/erb.rb @@ -6,7 +6,6 @@ module Erb # :nodoc: module Generators # :nodoc: class Base < Rails::Generators::NamedBase #:nodoc: private - def formats [format] end diff --git a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb index 997602cb8c..f66be1ee44 100644 --- a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb +++ b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb @@ -29,7 +29,6 @@ module Erb # :nodoc: end private - def formats [:text, :html] end diff --git a/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb index 2fc04e4094..6d3bccab0b 100644 --- a/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb +++ b/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb @@ -24,7 +24,6 @@ module Erb # :nodoc: end private - def available_views %w(index edit show new _form) end diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb index 1a80e71eae..4e348be9be 100644 --- a/railties/lib/rails/generators/generated_attribute.rb +++ b/railties/lib/rails/generators/generated_attribute.rb @@ -39,7 +39,6 @@ module Rails end private - # parse possible attribute options like :limit for string/text/binary/integer, :precision/:scale for decimals or :polymorphic for references/belongs_to # when declaring options curly brackets should be used def parse_type_and_options(type) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 578881d1ac..ea3968bf39 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -497,7 +497,6 @@ module Rails # :startdoc: private - # Define file as an alias to create_file for backwards compatibility. def file(*args, &block) create_file(*args, &block) @@ -542,7 +541,6 @@ module Rails end private - def handle_version_request!(argument) if ["--version", "-v"].include?(argument) require "rails/version" diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt index c517b0f96b..3d468f7633 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt @@ -23,6 +23,9 @@ # If you are using UJS then enable automatic nonce generation # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } +# Set the nonce only to specific directives +# Rails.application.config.content_security_policy_nonce_directives = %w(script-src) + # Report CSP violations to a specified URI # For further information see the following documentation: # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt index d25552e923..abb03e761b 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt @@ -16,6 +16,9 @@ # It's best enabled when your entire app is migrated and stable on 6.0. # Rails.application.config.action_dispatch.use_cookies_with_metadata = true +# Change the return value of `ActionDispatch::Response#content_type` to Content-Type header without modification. +# Rails.application.config.action_dispatch.return_only_media_type_on_content_type = true + # Return false instead of self when enqueuing is aborted from a callback. # Rails.application.config.active_job.return_false_on_aborted_enqueue = true diff --git a/railties/lib/rails/generators/rails/app/templates/public/robots.txt b/railties/lib/rails/generators/rails/app/templates/public/robots.txt index 37b576a4a0..c19f78ab68 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/robots.txt +++ b/railties/lib/rails/generators/rails/app/templates/public/robots.txt @@ -1 +1 @@ -# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file +# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/railties/lib/rails/generators/rails/controller/controller_generator.rb b/railties/lib/rails/generators/rails/controller/controller_generator.rb index eb75e7e661..88729545f3 100644 --- a/railties/lib/rails/generators/rails/controller/controller_generator.rb +++ b/railties/lib/rails/generators/rails/controller/controller_generator.rb @@ -25,7 +25,6 @@ module Rails end private - def file_name @_file_name ||= remove_possible_suffix(super) end diff --git a/railties/lib/rails/generators/rails/generator/generator_generator.rb b/railties/lib/rails/generators/rails/generator/generator_generator.rb index 747acd68d1..b0146641b4 100644 --- a/railties/lib/rails/generators/rails/generator/generator_generator.rb +++ b/railties/lib/rails/generators/rails/generator/generator_generator.rb @@ -15,7 +15,6 @@ module Rails hook_for :test_framework private - def generator_dir if options[:namespace] File.join("lib", "generators", regular_class_path, file_name) diff --git a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index 895b3b2e92..4c18bdb430 100644 --- a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -269,7 +269,6 @@ task default: :test end private - def create_dummy_app(path = nil) dummy_path(path) if path diff --git a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb index e1ca54ec91..b2cdeee6d1 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb @@ -34,7 +34,6 @@ module Rails end private - def permitted_params attachments, others = attributes_names.partition { |name| attachments?(name) } params = others.map { |name| ":#{name}" } diff --git a/railties/lib/rails/generators/test_unit/generator/generator_generator.rb b/railties/lib/rails/generators/test_unit/generator/generator_generator.rb index 19be4f2f51..ae7e28580e 100644 --- a/railties/lib/rails/generators/test_unit/generator/generator_generator.rb +++ b/railties/lib/rails/generators/test_unit/generator/generator_generator.rb @@ -15,7 +15,6 @@ module TestUnit # :nodoc: end private - def generator_path if options[:namespace] File.join("generators", regular_class_path, file_name, "#{file_name}_generator") diff --git a/railties/lib/rails/generators/test_unit/integration/integration_generator.rb b/railties/lib/rails/generators/test_unit/integration/integration_generator.rb index ba27ed329b..86fea3f677 100644 --- a/railties/lib/rails/generators/test_unit/integration/integration_generator.rb +++ b/railties/lib/rails/generators/test_unit/integration/integration_generator.rb @@ -12,7 +12,6 @@ module TestUnit # :nodoc: end private - def file_name @_file_name ||= super.sub(/_test\z/i, "") end diff --git a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb index 26002a0704..a4bc81cad6 100644 --- a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +++ b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb @@ -38,7 +38,6 @@ module TestUnit # :nodoc: end private - def attributes_string attributes_hash.map { |k, v| "#{k}: #{v}" }.join(", ") end diff --git a/railties/lib/rails/generators/testing/behaviour.rb b/railties/lib/rails/generators/testing/behaviour.rb index ec29ad12ba..a092faec89 100644 --- a/railties/lib/rails/generators/testing/behaviour.rb +++ b/railties/lib/rails/generators/testing/behaviour.rb @@ -88,7 +88,6 @@ module Rails end private - def destination_root_is_set? raise "You need to configure your Rails::Generators::TestCase destination root." unless destination_root end diff --git a/railties/lib/rails/info_controller.rb b/railties/lib/rails/info_controller.rb index f74d979721..d51010d422 100644 --- a/railties/lib/rails/info_controller.rb +++ b/railties/lib/rails/info_controller.rb @@ -33,7 +33,6 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc: end private - def match_route _routes.routes.select { |route| yield route.path diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb index 8367ac8980..838fe55acc 100644 --- a/railties/lib/rails/paths.rb +++ b/railties/lib/rails/paths.rb @@ -98,7 +98,6 @@ module Rails end private - def filter_by(&block) all_paths.find_all(&block).flat_map { |path| paths = path.existent @@ -223,7 +222,6 @@ module Rails alias to_a expanded private - def files_in(path) Dir.chdir(path) do files = Dir.glob(@glob) diff --git a/railties/lib/rails/rack/logger.rb b/railties/lib/rails/rack/logger.rb index 3a95b55811..8d69663dbd 100644 --- a/railties/lib/rails/rack/logger.rb +++ b/railties/lib/rails/rack/logger.rb @@ -30,7 +30,6 @@ module Rails end private - def call_app(request, env) # :doc: instrumenter = ActiveSupport::Notifications.instrumenter instrumenter.start "request.action_dispatch", request: request diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb index a67b90e285..178c584f95 100644 --- a/railties/lib/rails/railtie.rb +++ b/railties/lib/rails/railtie.rb @@ -228,7 +228,6 @@ module Rails end protected - def run_console_blocks(app) #:nodoc: each_registered_block(:console) { |block| block.call(app) } end @@ -247,7 +246,6 @@ module Rails end private - # run `&block` in every registered block in `#register_block_for` def each_registered_block(type, &block) klass = self.class diff --git a/railties/lib/rails/railtie/configurable.rb b/railties/lib/rails/railtie/configurable.rb index 7f42fae10a..ba14089a2a 100644 --- a/railties/lib/rails/railtie/configurable.rb +++ b/railties/lib/rails/railtie/configurable.rb @@ -27,7 +27,6 @@ module Rails end private - def method_missing(*args, &block) instance.send(*args, &block) end diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb index 70274b948c..c90fcac51a 100644 --- a/railties/lib/rails/railtie/configuration.rb +++ b/railties/lib/rails/railtie/configuration.rb @@ -87,7 +87,6 @@ module Rails end private - def method_missing(name, *args, &blk) if name.to_s =~ /=$/ @@options[$`.to_sym] = args.first diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index a80581211b..a7dd233f3d 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -491,7 +491,6 @@ module ApplicationTests end private - def app_with_assets_in_view app_file "app/assets/javascripts/application.js", "//= require_tree ." app_file "app/assets/javascripts/xmlhr.js", "function f1() { alert(); }" diff --git a/railties/test/application/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb index aa0da0931d..d84ab61cf9 100644 --- a/railties/test/application/bin_setup_test.rb +++ b/railties/test/application/bin_setup_test.rb @@ -31,7 +31,7 @@ module ApplicationTests Dir.chdir(app_path) do # SQLite3 seems to auto-create the database on first checkout. rails "db:system:change", "--to=postgresql" - rails "db:drop" + rails "db:drop", allow_failure: true app_file "db/schema.rb", "" diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 6f9711cb37..f6bec3242a 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -2436,6 +2436,33 @@ module ApplicationTests assert_nil ActiveStorage.queues[:purge] end + test "ActionDispatch::Response.return_only_media_type_on_content_type is false by default" do + app "development" + + assert_equal false, ActionDispatch::Response.return_only_media_type_on_content_type + end + + test "ActionDispatch::Response.return_only_media_type_on_content_type is true in the 5.x defaults" do + remove_from_config '.*config\.load_defaults.*\n' + add_to_config 'config.load_defaults "5.2"' + + app "development" + + assert_equal true, ActionDispatch::Response.return_only_media_type_on_content_type + end + + test "ActionDispatch::Response.return_only_media_type_on_content_type can be configured in the new framework defaults" do + remove_from_config '.*config\.load_defaults.*\n' + + app_file "config/initializers/new_framework_defaults_6_0.rb", <<-RUBY + Rails.application.config.action_dispatch.return_only_media_type_on_content_type = true + RUBY + + app "development" + + assert_equal true, ActionDispatch::Response.return_only_media_type_on_content_type + end + test "ActionMailbox.logger is Rails.logger by default" do app "development" diff --git a/railties/test/application/content_security_policy_test.rb b/railties/test/application/content_security_policy_test.rb index 0d28df16f8..0bb6ee917a 100644 --- a/railties/test/application/content_security_policy_test.rb +++ b/railties/test/application/content_security_policy_test.rb @@ -119,6 +119,38 @@ module ApplicationTests assert_policy "default-src 'self' https:", report_only: true end + test "global content security policy nonce directives in an initializer" do + controller :pages, <<-RUBY + class PagesController < ApplicationController + def index + render html: "<h1>Welcome to Rails!</h1>" + end + end + RUBY + + app_file "config/initializers/content_security_policy.rb", <<-RUBY + Rails.application.config.content_security_policy do |p| + p.default_src :self, :https + p.script_src :self, :https + p.style_src :self, :https + end + + Rails.application.config.content_security_policy_nonce_generator = proc { "iyhD0Yc0W+c=" } + Rails.application.config.content_security_policy_nonce_directives = %w(script-src) + RUBY + + app_file "config/routes.rb", <<-RUBY + Rails.application.routes.draw do + root to: "pages#index" + end + RUBY + + app("development") + + get "/" + assert_policy "default-src 'self' https:; script-src 'self' https: 'nonce-iyhD0Yc0W+c='; style-src 'self' https:" + end + test "override content security policy in a controller" do controller :pages, <<-RUBY class PagesController < ApplicationController @@ -204,7 +236,6 @@ module ApplicationTests end private - def assert_policy(expected, report_only: false) assert_equal 200, last_response.status diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index a35247fc43..05978e1d99 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -218,8 +218,9 @@ module ApplicationTests rails %w(generate model post title:string) rails %w(db:migrate db:schema:cache:dump) require "#{app_path}/config/environment" - ActiveRecord::Base.connection.drop_table("posts") # force drop posts table for test. assert ActiveRecord::Base.connection.schema_cache.data_sources("posts") + ensure + ActiveRecord::Base.connection.drop_table("posts", if_exists: true) # force drop posts table for test. end test "expire schema cache dump" do diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb index 322a6e1ca0..9ab400acfc 100644 --- a/railties/test/application/loading_test.rb +++ b/railties/test/application/loading_test.rb @@ -133,11 +133,12 @@ class LoadingTest < ActiveSupport::TestCase require "#{rails_root}/config/environment" setup_ar! - assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, ApplicationRecord].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort + initial = [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, ApplicationRecord, "primary::SchemaMigration"].collect(&:to_s).sort + assert_equal initial, ActiveRecord::Base.descendants.collect(&:to_s).sort get "/load" - assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, ApplicationRecord, Post].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort + assert_equal [Post].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort - initial get "/unload" - assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort + assert_equal ["ActiveRecord::InternalMetadata", "ActiveRecord::SchemaMigration", "primary::SchemaMigration"], ActiveRecord::Base.descendants.collect(&:to_s).sort.uniq end test "initialize cant be called twice" do @@ -454,7 +455,6 @@ class LoadingTest < ActiveSupport::TestCase end private - def setup_ar! ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Migration.verbose = false diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 54b2e95d75..54c84e2e7c 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -309,7 +309,6 @@ module ApplicationTests end private - def boot! require "#{app_path}/config/environment" end diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index e08cd09abd..79c521dbf6 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -40,6 +40,15 @@ module ApplicationTests end end + def db_create_with_warning(expected_database) + Dir.chdir(app_path) do + output = rails("db:create") + assert_match(/Rails couldn't infer whether you are using multiple databases/, output) + assert_match(/Created database/, output) + assert File.exist?(expected_database) + end + end + test "db:create and db:drop without database URL" do require "#{app_path}/config/environment" db_create_and_drop ActiveRecord::Base.configurations[Rails.env]["database"] @@ -86,6 +95,25 @@ module ApplicationTests db_create_and_drop("db/development.sqlite3", environment_loaded: false) end + test "db:create and db:drop show warning but doesn't raise errors when loading YAML with alias ERB" do + app_file "config/database.yml", <<-YAML + sqlite: &sqlite + adapter: sqlite3 + database: db/development.sqlite3 + + development: + <<: *<%= ENV["DB"] || "sqlite" %> + YAML + + app_file "config/environments/development.rb", <<-RUBY + Rails.application.configure do + config.database = "db/development.sqlite3" + end + RUBY + + db_create_with_warning("db/development.sqlite3") + end + test "db:create and db:drop don't raise errors when loading YAML containing conditional statements in ERB" do app_file "config/database.yml", <<-YAML development: diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb index 8c41b252da..2606e64424 100644 --- a/railties/test/application/rake/multi_dbs_test.rb +++ b/railties/test/application/rake/multi_dbs_test.rb @@ -299,6 +299,32 @@ module ApplicationTests db_migrate_and_schema_cache_dump_and_schema_cache_clear end + test "db:abort_if_pending_migrations works on all databases" do + require "#{app_path}/config/environment" + + app_file "db/animals_migrate/02_two_migration.rb", <<-MIGRATION + class TwoMigration < ActiveRecord::Migration::Current + end + MIGRATION + + output = rails("db:abort_if_pending_migrations", allow_failure: true) + assert_match(/You have 1 pending migration/, output) + end + + test "db:abort_if_pending_migrations:namespace works" do + require "#{app_path}/config/environment" + + app_file "db/animals_migrate/02_two_migration.rb", <<-MIGRATION + class TwoMigration < ActiveRecord::Migration::Current + end + MIGRATION + + output = rails("db:abort_if_pending_migrations:primary") + assert_no_match(/You have \d+ pending migration/, output) + output = rails("db:abort_if_pending_migrations:animals", allow_failure: true) + assert_match(/You have 1 pending migration/, output) + end + test "db:prepare works on all databases" do require "#{app_path}/config/environment" db_prepare diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb index 60802ef7c4..47822e55b9 100644 --- a/railties/test/application/rake/notes_test.rb +++ b/railties/test/application/rake/notes_test.rb @@ -159,7 +159,6 @@ module ApplicationTests end private - def run_rake_notes(command = "bin/rake notes") Dir.chdir(app_path) do output = `#{command}` diff --git a/railties/test/commands/console_test.rb b/railties/test/commands/console_test.rb index f6df2b694a..ee4335e31d 100644 --- a/railties/test/commands/console_test.rb +++ b/railties/test/commands/console_test.rb @@ -116,7 +116,6 @@ class Rails::ConsoleTest < ActiveSupport::TestCase private :output private - def start(argv = []) rails_console = Rails::Console.new(app, parse_arguments(argv)) @output = capture(:stdout) { rails_console.start } diff --git a/railties/test/commands/dbconsole_test.rb b/railties/test/commands/dbconsole_test.rb index 76a7cd055f..45b72fd909 100644 --- a/railties/test/commands/dbconsole_test.rb +++ b/railties/test/commands/dbconsole_test.rb @@ -275,7 +275,6 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase private :aborted, :output private - def app_db_config(results) Rails.application.config.stub(:database_configuration, results || {}) do yield diff --git a/railties/test/commands/server_test.rb b/railties/test/commands/server_test.rb index b78370a233..c9026e2d95 100644 --- a/railties/test/commands/server_test.rb +++ b/railties/test/commands/server_test.rb @@ -116,6 +116,13 @@ class Rails::Command::ServerCommandTest < ActiveSupport::TestCase end end + def test_environment_with_pidfile + switch_env "PIDFILE", "/tmp/rails.pid" do + options = parse_arguments + assert_equal "/tmp/rails.pid", options[:pid] + end + end + def test_caching_without_option args = [] options = parse_arguments(args) @@ -234,6 +241,12 @@ class Rails::Command::ServerCommandTest < ActiveSupport::TestCase options = parse_arguments(args) assert_equal "127.0.0.1", options[:Host] end + + switch_env "PIDFILE", "/tmp/rails.pid" do + args = ["-P", "/somewhere/else.pid"] + options = parse_arguments(args) + assert_equal "/somewhere/else.pid", options[:pid] + end end def test_records_user_supplied_options @@ -253,6 +266,16 @@ class Rails::Command::ServerCommandTest < ActiveSupport::TestCase server_options = parse_arguments assert_equal [:Host], server_options[:user_supplied_options] end + + switch_env "PORT", "3001" do + server_options = parse_arguments + assert_equal [:Port], server_options[:user_supplied_options] + end + + switch_env "PIDFILE", "/tmp/server.pid" do + server_options = parse_arguments + assert_equal [:pid], server_options[:user_supplied_options] + end end def test_default_options diff --git a/railties/test/configuration/middleware_stack_proxy_test.rb b/railties/test/configuration/middleware_stack_proxy_test.rb index bc72b7f0c9..b67142f4c2 100644 --- a/railties/test/configuration/middleware_stack_proxy_test.rb +++ b/railties/test/configuration/middleware_stack_proxy_test.rb @@ -51,7 +51,6 @@ module Rails end private - def assert_playback(msg_name, args) mock = Minitest::Mock.new mock.expect :send, nil, [msg_name, args] diff --git a/railties/test/env_helpers.rb b/railties/test/env_helpers.rb index 336832b867..e3157e0c77 100644 --- a/railties/test/env_helpers.rb +++ b/railties/test/env_helpers.rb @@ -4,7 +4,6 @@ require "rails" module EnvHelpers private - def with_rails_env(env) Rails.instance_variable_set :@_env, nil switch_env "RAILS_ENV", env do diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index d913bb5438..150836d4ce 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -505,7 +505,6 @@ F end private - def action(*args, &block) capture(:stdout) { generator.send(*args, &block) } end diff --git a/railties/test/generators/api_app_generator_test.rb b/railties/test/generators/api_app_generator_test.rb index d03178da66..099bad8fb9 100644 --- a/railties/test/generators/api_app_generator_test.rb +++ b/railties/test/generators/api_app_generator_test.rb @@ -109,7 +109,6 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase end private - def default_files %w(.gitignore .ruby-version diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb index 65cde91436..080e54a1ca 100644 --- a/railties/test/generators/migration_generator_test.rb +++ b/railties/test/generators/migration_generator_test.rb @@ -445,7 +445,6 @@ class MigrationGeneratorTest < Rails::Generators::TestCase end private - def with_singular_table_name old_state = ActiveRecord::Base.pluralize_table_names ActiveRecord::Base.pluralize_table_names = false diff --git a/railties/test/generators/named_base_test.rb b/railties/test/generators/named_base_test.rb index 4e61b660d7..1b45c58b0e 100644 --- a/railties/test/generators/named_base_test.rb +++ b/railties/test/generators/named_base_test.rb @@ -169,7 +169,6 @@ class NamedBaseTest < Rails::Generators::TestCase end private - def assert_name(generator, value, method) assert_equal value, generator.send(method) end diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index f45464f8d0..db774f6ac1 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -713,7 +713,6 @@ class PluginGeneratorTest < Rails::Generators::TestCase end private - def action(*args, &block) silence(:stdout) { generator.send(*args, &block) } end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 8ce68dbcfa..7f05b9d9cf 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -34,7 +34,7 @@ module RailtiesTest def migrations migration_root = File.expand_path(ActiveRecord::Migrator.migrations_paths.first, app_path) - ActiveRecord::MigrationContext.new(migration_root).migrations + ActiveRecord::MigrationContext.new(migration_root, ActiveRecord::SchemaMigration).migrations end test "serving sprocket's assets" do diff --git a/tools/profile b/tools/profile index 6fb571f43b..d38ba1dd84 100755 --- a/tools/profile +++ b/tools/profile @@ -68,7 +68,6 @@ module CodeTools end private - def assert_ruby_file_exists(path) fail Error.new("No such file") unless File.exist?(path) fail Error.new("#{path} is a directory") if File.directory?(path) |