diff options
204 files changed, 865 insertions, 786 deletions
diff --git a/.gitignore b/.gitignore index ab9ca8a6ac..d44875ed9a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ debug.log node_modules/ package-lock.json pkg/ +/tmp/ +/yarn.lock
\ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml index 2ac31637ef..33791588cb 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -130,6 +130,12 @@ Style/FrozenStringLiteralComment: - 'actionpack/test/**/*.ruby' - 'activestorage/db/migrate/**/*.rb' +Style/RedundantFreeze: + Enabled: true + Exclude: + - 'actionpack/lib/action_dispatch/journey/router/utils.rb' + - 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb' + # Use `foo {}` not `foo{}`. Layout/SpaceBeforeBlockBraces: Enabled: true diff --git a/.travis.yml b/.travis.yml index 109005b407..a4f5fa045d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,6 +42,8 @@ before_install: - "[[ $GEM != 'av:ujs' ]] || nvm install node" - "[[ $GEM != 'av:ujs' ]] || node --version" - "[[ $GEM != 'av:ujs' ]] || (cd actionview && npm install)" + - "[[ $GEM != 'railties' ]] || (curl -o- -L https://yarnpkg.com/install.sh | bash)" + - "[[ $GEM != 'railties' ]] || export PATH=$HOME/.yarn/bin:$PATH" before_script: # Set Sauce Labs username and access key. Obfuscated, purposefully not encrypted. diff --git a/.yarnrc b/.yarnrc new file mode 100644 index 0000000000..6be74e145d --- /dev/null +++ b/.yarnrc @@ -0,0 +1,2 @@ +workspaces-experimental true +--add.prefer-offline true
\ No newline at end of file @@ -12,10 +12,9 @@ gem "rake", ">= 11.1" gem "capybara", ">= 2.15" gem "rack-cache", "~> 1.2" -gem "coffee-rails" gem "sass-rails" gem "turbolinks", "~> 5" - +gem "webpacker", github: "rails/webpacker", require: ENV["SKIP_REQUIRE_WEBPACKER"] != "true" # require: false so bcrypt is loaded only when has_secure_password is used. # This is to avoid Active Model (and by extension the entire framework) # being dependent on a binary library. diff --git a/Gemfile.lock b/Gemfile.lock index e6fc04b5ca..727489b50a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -30,6 +30,15 @@ GIT queue_classic (3.2.0.RC1) pg (>= 0.17, < 2.0) +GIT + remote: https://github.com/rails/webpacker.git + revision: 48d9fd52c3e9637dbb21e551b48c84c0f2dbb2ed + specs: + webpacker (4.0.0.pre.pre.2) + activesupport (>= 4.2) + rack-proxy (>= 0.6.1) + railties (>= 4.2) + PATH remote: . specs: @@ -184,9 +193,6 @@ GEM chromedriver-helper (2.0.0) archive-zip (~> 0.10) nokogiri (~> 1.8) - coffee-rails (4.2.2) - coffee-script (>= 2.2.0) - railties (>= 4.0.0) coffee-script (2.4.1) coffee-script-source execjs @@ -364,6 +370,8 @@ GEM rack (>= 0.4) rack-protection (2.0.3) rack + rack-proxy (0.6.5) + rack rack-test (1.1.0) rack (>= 1.0, < 3) rails-dom-testing (2.0.3) @@ -518,7 +526,6 @@ DEPENDENCIES byebug capybara (>= 2.15) chromedriver-helper - coffee-rails connection_pool dalli delayed_job @@ -565,6 +572,7 @@ DEPENDENCIES uglifier (>= 1.3.0) w3c_validators wdm (>= 0.1.0) + webpacker! websocket-client-simple! BUNDLED WITH diff --git a/actioncable/lib/action_cable.rb b/actioncable/lib/action_cable.rb index 35eacc2f4f..d261d4112e 100644 --- a/actioncable/lib/action_cable.rb +++ b/actioncable/lib/action_cable.rb @@ -32,13 +32,13 @@ module ActionCable INTERNAL = { message_types: { - welcome: "welcome".freeze, - ping: "ping".freeze, - confirmation: "confirm_subscription".freeze, - rejection: "reject_subscription".freeze + welcome: "welcome", + ping: "ping", + confirmation: "confirm_subscription", + rejection: "reject_subscription" }, - default_mount_path: "/cable".freeze, - protocols: ["actioncable-v1-json".freeze, "actioncable-unsupported".freeze].freeze + default_mount_path: "/cable", + protocols: ["actioncable-v1-json", "actioncable-unsupported"].freeze } # Singleton instance of the server diff --git a/actioncable/lib/action_cable/channel/test_case.rb b/actioncable/lib/action_cable/channel/test_case.rb index a26051d687..dd2762ccd0 100644 --- a/actioncable/lib/action_cable/channel/test_case.rb +++ b/actioncable/lib/action_cable/channel/test_case.rb @@ -131,7 +131,7 @@ module ActionCable # # == Specifying connection identifiers # - # You need to set up your connection manually to privide values for the identifiers. + # You need to set up your connection manually to provide values for the identifiers. # To do this just use: # # stub_connection(user: users[:john]) @@ -212,7 +212,7 @@ module ActionCable @connection = ConnectionStub.new(identifiers) end - # Subsribe to the channel under test. Optionally pass subscription parameters as a Hash. + # Subscribe to the channel under test. Optionally pass subscription parameters as a Hash. def subscribe(params = {}) @connection ||= stub_connection @subscription = self.class.channel_class.new(connection, CHANNEL_IDENTIFIER, params.with_indifferent_access) diff --git a/actioncable/lib/rails/generators/channel/USAGE b/actioncable/lib/rails/generators/channel/USAGE index dd109fda80..ea9662436c 100644 --- a/actioncable/lib/rails/generators/channel/USAGE +++ b/actioncable/lib/rails/generators/channel/USAGE @@ -1,14 +1,12 @@ Description: ============ - Stubs out a new cable channel for the server (in Ruby) and client (in CoffeeScript). + Stubs out a new cable channel for the server (in Ruby) and client (in JavaScript). Pass the channel name, either CamelCased or under_scored, and an optional list of channel actions as arguments. - Note: Turn on the cable connection in app/assets/javascripts/cable.js after generating any channels. - Example: ======== rails generate channel Chat speak - creates a Chat channel class and CoffeeScript asset: + creates a Chat channel class and JavaScript asset: Channel: app/channels/chat_channel.rb - Assets: app/assets/javascripts/channels/chat.coffee + Assets: app/javascript/channels/chat_channel.js diff --git a/actioncable/lib/rails/generators/channel/channel_generator.rb b/actioncable/lib/rails/generators/channel/channel_generator.rb index 427eef1f55..ef51981e89 100644 --- a/actioncable/lib/rails/generators/channel/channel_generator.rb +++ b/actioncable/lib/rails/generators/channel/channel_generator.rb @@ -16,10 +16,11 @@ module Rails if options[:assets] if behavior == :invoke - template "assets/cable.js", "app/assets/javascripts/cable.js" + template "javascript/index.js", "app/javascript/channels/index.js" + template "javascript/consumer.js", "app/javascript/channels/consumer.js" end - js_template "assets/channel", File.join("app/assets/javascripts/channels", class_path, "#{file_name}") + js_template "javascript/channel", File.join("app/javascript/channels", class_path, "#{file_name}_channel") end generate_application_cable_files diff --git a/actioncable/lib/rails/generators/channel/templates/assets/channel.coffee.tt b/actioncable/lib/rails/generators/channel/templates/assets/channel.coffee.tt deleted file mode 100644 index 5467811aba..0000000000 --- a/actioncable/lib/rails/generators/channel/templates/assets/channel.coffee.tt +++ /dev/null @@ -1,14 +0,0 @@ -App.<%= class_name.underscore %> = App.cable.subscriptions.create "<%= class_name %>Channel", - connected: -> - # Called when the subscription is ready for use on the server - - disconnected: -> - # Called when the subscription has been terminated by the server - - received: (data) -> - # Called when there's incoming data on the websocket for this channel -<% actions.each do |action| -%> - - <%= action %>: -> - @perform '<%= action %>' -<% end -%> diff --git a/actioncable/lib/rails/generators/channel/templates/assets/channel.js.tt b/actioncable/lib/rails/generators/channel/templates/javascript/channel.js.tt index ab0e68b11a..33baaa5a22 100644 --- a/actioncable/lib/rails/generators/channel/templates/assets/channel.js.tt +++ b/actioncable/lib/rails/generators/channel/templates/javascript/channel.js.tt @@ -1,4 +1,6 @@ -App.<%= class_name.underscore %> = App.cable.subscriptions.create("<%= class_name %>Channel", { +import consumer from "./consumer" + +consumer.subscriptions.create("<%= class_name %>Channel", { connected: function() { // Called when the subscription is ready for use on the server }, diff --git a/actioncable/lib/rails/generators/channel/templates/assets/cable.js.tt b/actioncable/lib/rails/generators/channel/templates/javascript/consumer.js.tt index 739aa5f022..76ca3d0f2f 100644 --- a/actioncable/lib/rails/generators/channel/templates/assets/cable.js.tt +++ b/actioncable/lib/rails/generators/channel/templates/javascript/consumer.js.tt @@ -1,13 +1,6 @@ // Action Cable provides the framework to deal with WebSockets in Rails. // You can generate new channels where WebSocket features live using the `rails generate channel` command. -// -//= require action_cable -//= require_self -//= require_tree ./channels -(function() { - this.App || (this.App = {}); +import ActionCable from "actioncable" - App.cable = ActionCable.createConsumer(); - -}).call(this); +export default ActionCable.createConsumer() diff --git a/actioncable/lib/rails/generators/channel/templates/javascript/index.js.tt b/actioncable/lib/rails/generators/channel/templates/javascript/index.js.tt new file mode 100644 index 0000000000..5da1ce2dce --- /dev/null +++ b/actioncable/lib/rails/generators/channel/templates/javascript/index.js.tt @@ -0,0 +1,5 @@ +// Load all the channels within this directory and all subdirectories. +// Channel files must be named *_channel.js. + +const channels = require.context('.', true, /\_channel\.js$/) +channels.keys().forEach(channels) diff --git a/actioncable/test/channel/stream_test.rb b/actioncable/test/channel/stream_test.rb index f2fe8b4ce7..9ad2213d47 100644 --- a/actioncable/test/channel/stream_test.rb +++ b/actioncable/test/channel/stream_test.rb @@ -193,7 +193,7 @@ module ActionCable::StreamTests end end - test "subscription confirmation should only be sent out once with muptiple stream_from" do + test "subscription confirmation should only be sent out once with multiple stream_from" do run_in_eventmachine do connection = open_connection expected = { "identifier" => { "channel" => MultiChatChannel.name }.to_json, "type" => "confirm_subscription" } diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 55f701b18e..02e5ac2a3e 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -1008,7 +1008,7 @@ module ActionMailer end def instrument_name - "action_mailer".freeze + "action_mailer" end ActiveSupport.run_load_hooks(:action_mailer, self) diff --git a/actionmailer/lib/action_mailer/message_delivery.rb b/actionmailer/lib/action_mailer/message_delivery.rb index 2377aeb9a5..a57980c322 100644 --- a/actionmailer/lib/action_mailer/message_delivery.rb +++ b/actionmailer/lib/action_mailer/message_delivery.rb @@ -29,7 +29,7 @@ module ActionMailer @mail_message ||= processed_mailer.message end - # Unused except for delegator internals (dup, marshaling). + # Unused except for delegator internals (dup, marshalling). def __setobj__(mail_message) #:nodoc: @mail_message = mail_message end diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index dfe6e00865..c972c64766 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,7 @@ +* Remove undocumented `params` option from `url_for` helper. + + *Ilkka Oksanen* + * Encode Content-Disposition filenames on `send_data` and `send_file`. Previously, `send_data 'data', filename: "\u{3042}.txt"` sends `"filename=\"\u{3042}.txt\""` as Content-Disposition and it can be diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 6e6786d0be..bb42f2e119 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -104,7 +104,7 @@ module AbstractController # ==== Returns # * <tt>String</tt> def controller_path - @controller_path ||= name.sub(/Controller$/, "".freeze).underscore unless anonymous? + @controller_path ||= name.sub(/Controller$/, "").underscore unless anonymous? end # Refresh the cached action_methods when a new action_method is added. diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb index 3191584770..3913259ecc 100644 --- a/actionpack/lib/abstract_controller/helpers.rb +++ b/actionpack/lib/abstract_controller/helpers.rb @@ -181,7 +181,7 @@ module AbstractController end def default_helper_module! - module_name = name.sub(/Controller$/, "".freeze) + module_name = name.sub(/Controller$/, "") module_path = module_name.underscore helper module_path rescue LoadError => e diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index 97775d1dc8..bf3b00a7b7 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -40,7 +40,7 @@ module ActionController end def instrument_name - "action_controller".freeze + "action_controller" end end end diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb index 203653354a..6de1fb2c19 100644 --- a/actionpack/lib/action_controller/log_subscriber.rb +++ b/actionpack/lib/action_controller/log_subscriber.rb @@ -27,7 +27,7 @@ module ActionController status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name) end message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms" - message << " (#{additions.join(" | ".freeze)})" unless additions.empty? + message << " (#{additions.join(" | ")})" unless additions.empty? message << "\n\n" if defined?(Rails.env) && Rails.env.development? message diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb index 5140a667de..9ef4f50df1 100644 --- a/actionpack/lib/action_controller/metal/data_streaming.rb +++ b/actionpack/lib/action_controller/metal/data_streaming.rb @@ -11,8 +11,8 @@ module ActionController #:nodoc: include ActionController::Rendering - DEFAULT_SEND_FILE_TYPE = "application/octet-stream".freeze #:nodoc: - DEFAULT_SEND_FILE_DISPOSITION = "attachment".freeze #:nodoc: + DEFAULT_SEND_FILE_TYPE = "application/octet-stream" #:nodoc: + DEFAULT_SEND_FILE_DISPOSITION = "attachment" #:nodoc: private # Sends the file. This uses a server-appropriate method (such as X-Sendfile) diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 5794e0fb97..7036123d5d 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -127,7 +127,7 @@ module ActionController def authentication_request(controller, realm, message) message ||= "HTTP Basic: Access denied.\n" - controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.tr('"'.freeze, "".freeze)}") + controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.tr('"', "")}") controller.status = 401 controller.response_body = message end @@ -511,7 +511,7 @@ module ActionController # Returns nothing. def authentication_request(controller, realm, message = nil) message ||= "HTTP Token: Access denied.\n" - controller.headers["WWW-Authenticate"] = %(Token realm="#{realm.tr('"'.freeze, "".freeze)}") + controller.headers["WWW-Authenticate"] = %(Token realm="#{realm.tr('"', "")}") controller.__send__ :render, plain: message, status: :unauthorized end end diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index 5680ef08a1..1482b2999a 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -117,7 +117,7 @@ module ActionController end end - message = json.gsub("\n".freeze, "\ndata: ".freeze) + message = json.gsub("\n", "\ndata: ") @stream.write "data: #{message}\n\n" end end diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index 84dbb59a63..f077e765ab 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -44,7 +44,7 @@ module ActionController options[:original_script_name] = original_script_name else if same_origin - options[:script_name] = request.script_name.empty? ? "".freeze : request.script_name.dup + options[:script_name] = request.script_name.empty? ? "" : request.script_name.dup else options[:script_name] = script_name end diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index a7c7cfc1e5..f67b13f657 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -4,8 +4,8 @@ module ActionDispatch module Http module Cache module Request - HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze - HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze + HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE" + HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH" def if_modified_since if since = get_header(HTTP_IF_MODIFIED_SINCE) @@ -124,8 +124,8 @@ module ActionDispatch private - DATE = "Date".freeze - LAST_MODIFIED = "Last-Modified".freeze + DATE = "Date" + LAST_MODIFIED = "Last-Modified" SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public private must-revalidate]) def generate_weak_etag(validators) @@ -166,11 +166,11 @@ module ActionDispatch @cache_control = cache_control_headers end - DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate".freeze - NO_CACHE = "no-cache".freeze - PUBLIC = "public".freeze - PRIVATE = "private".freeze - MUST_REVALIDATE = "must-revalidate".freeze + DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate" + NO_CACHE = "no-cache" + PUBLIC = "public" + PRIVATE = "private" + MUST_REVALIDATE = "must-revalidate" def handle_conditional_get! # Normally default cache control setting is handled by ETag diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb index 855be5ce2e..50953e32b5 100644 --- a/actionpack/lib/action_dispatch/http/content_security_policy.rb +++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb @@ -5,9 +5,9 @@ require "active_support/core_ext/object/deep_dup" module ActionDispatch #:nodoc: class ContentSecurityPolicy class Middleware - CONTENT_TYPE = "Content-Type".freeze - POLICY = "Content-Security-Policy".freeze - POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only".freeze + CONTENT_TYPE = "Content-Type" + POLICY = "Content-Security-Policy" + POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only" def initialize(app) @app = app @@ -50,10 +50,10 @@ module ActionDispatch #:nodoc: end module Request - POLICY = "action_dispatch.content_security_policy".freeze - POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only".freeze - NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator".freeze - NONCE = "action_dispatch.content_security_policy_nonce".freeze + POLICY = "action_dispatch.content_security_policy" + 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" def content_security_policy get_header(POLICY) diff --git a/actionpack/lib/action_dispatch/http/filter_redirect.rb b/actionpack/lib/action_dispatch/http/filter_redirect.rb index 25394fe5dd..8c4e852235 100644 --- a/actionpack/lib/action_dispatch/http/filter_redirect.rb +++ b/actionpack/lib/action_dispatch/http/filter_redirect.rb @@ -3,7 +3,7 @@ module ActionDispatch module Http module FilterRedirect - FILTERED = "[FILTERED]".freeze # :nodoc: + FILTERED = "[FILTERED]" # :nodoc: def filtered_location # :nodoc: if location_filter_match? diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 295539281f..dd74695229 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -74,7 +74,7 @@ module Mime def initialize(index, name, q = nil) @index = index @name = name - q ||= 0.0 if @name == "*/*".freeze # Default wildcard match to end of list. + q ||= 0.0 if @name == "*/*" # Default wildcard match to end of list. @q = ((q || 1.0).to_f * 100).to_i end diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb index 09aab631ed..6689092859 100644 --- a/actionpack/lib/action_dispatch/http/parameter_filter.rb +++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb @@ -6,7 +6,7 @@ require "active_support/core_ext/array/extract" module ActionDispatch module Http class ParameterFilter - FILTERED = "[FILTERED]".freeze # :nodoc: + FILTERED = "[FILTERED]" # :nodoc: def initialize(filters = []) @filters = filters @@ -39,11 +39,11 @@ module ActionDispatch end end - deep_regexps = regexps.extract! { |r| r.to_s.include?("\\.".freeze) } - deep_strings = strings.extract! { |s| s.include?("\\.".freeze) } + deep_regexps = regexps.extract! { |r| r.to_s.include?("\\.") } + deep_strings = strings.extract! { |s| s.include?("\\.") } - regexps << Regexp.new(strings.join("|".freeze), true) unless strings.empty? - deep_regexps << Regexp.new(deep_strings.join("|".freeze), true) unless deep_strings.empty? + regexps << Regexp.new(strings.join("|"), true) unless strings.empty? + deep_regexps << Regexp.new(deep_strings.join("|"), true) unless deep_strings.empty? new regexps, deep_regexps, blocks end diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 3838b84a7a..7bc364d370 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -136,11 +136,11 @@ module ActionDispatch end def routes # :nodoc: - get_header("action_dispatch.routes".freeze) + get_header("action_dispatch.routes") end def routes=(routes) # :nodoc: - set_header("action_dispatch.routes".freeze, routes) + set_header("action_dispatch.routes", routes) end def engine_script_name(_routes) # :nodoc: @@ -158,11 +158,11 @@ module ActionDispatch end def controller_instance # :nodoc: - get_header("action_controller.instance".freeze) + get_header("action_controller.instance") end def controller_instance=(controller) # :nodoc: - set_header("action_controller.instance".freeze, controller) + set_header("action_controller.instance", controller) end def http_auth_salt @@ -173,7 +173,7 @@ module ActionDispatch # We're treating `nil` as "unset", and we want the default setting to be # `true`. This logic should be extracted to `env_config` and calculated # once. - !(get_header("action_dispatch.show_exceptions".freeze) == false) + !(get_header("action_dispatch.show_exceptions") == false) end # Returns a symbol form of the #request_method. @@ -280,10 +280,10 @@ module ActionDispatch end def remote_ip=(remote_ip) - set_header "action_dispatch.remote_ip".freeze, remote_ip + set_header "action_dispatch.remote_ip", remote_ip end - ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id".freeze # :nodoc: + ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc: # Returns the unique request id, which is based on either the X-Request-Id header that can # be generated by a firewall, load balancer, or web server or by the RequestId middleware @@ -407,18 +407,18 @@ module ActionDispatch def request_parameters=(params) raise if params.nil? - set_header("action_dispatch.request.request_parameters".freeze, params) + set_header("action_dispatch.request.request_parameters", params) end def logger - get_header("action_dispatch.logger".freeze) + get_header("action_dispatch.logger") end def commit_flash end def ssl? - super || scheme == "wss".freeze + super || scheme == "wss" end private diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index f07be831d4..1d38942a31 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -78,9 +78,9 @@ module ActionDispatch # :nodoc: x end - CONTENT_TYPE = "Content-Type".freeze - SET_COOKIE = "Set-Cookie".freeze - LOCATION = "Location".freeze + CONTENT_TYPE = "Content-Type" + SET_COOKIE = "Set-Cookie" + LOCATION = "Location" NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304] cattr_accessor :default_charset, default: "utf-8" diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index db6d8188d3..3af4c176a7 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -67,7 +67,7 @@ module ActionDispatch end def path_for(options) - path = options[:script_name].to_s.chomp("/".freeze) + path = options[:script_name].to_s.chomp("/") path << options[:path] if options.key?(:path) add_trailing_slash(path) if options[:trailing_slash] @@ -231,7 +231,7 @@ module ActionDispatch # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.host # => "example.com" def host - raw_host_with_port.sub(/:\d+$/, "".freeze) + raw_host_with_port.sub(/:\d+$/, "") end # Returns a \host:\port string for this request, such as "example.com" or diff --git a/actionpack/lib/action_dispatch/journey/router/utils.rb b/actionpack/lib/action_dispatch/journey/router/utils.rb index 3bbb187f5c..3c8b9a6eaa 100644 --- a/actionpack/lib/action_dispatch/journey/router/utils.rb +++ b/actionpack/lib/action_dispatch/journey/router/utils.rb @@ -18,10 +18,10 @@ module ActionDispatch path ||= "" encoding = path.encoding path = +"/#{path}" - path.squeeze!("/".freeze) - path.sub!(%r{/+\Z}, "".freeze) + path.squeeze!("/") + path.sub!(%r{/+\Z}, "") path.gsub!(/(%[a-f0-9]{2})/) { $1.upcase } - path = +"/" if path == "".freeze + path = +"/" if path == "" path.force_encoding(encoding) path end @@ -29,16 +29,16 @@ module ActionDispatch # URI path and fragment escaping # https://tools.ietf.org/html/rfc3986 class UriEncoder # :nodoc: - ENCODE = "%%%02X".freeze + ENCODE = "%%%02X" US_ASCII = Encoding::US_ASCII UTF_8 = Encoding::UTF_8 EMPTY = (+"").force_encoding(US_ASCII).freeze DEC2HEX = (0..255).to_a.map { |i| ENCODE % i }.map { |s| s.force_encoding(US_ASCII) } - ALPHA = "a-zA-Z".freeze - DIGIT = "0-9".freeze - UNRESERVED = "#{ALPHA}#{DIGIT}\\-\\._~".freeze - SUB_DELIMS = "!\\$&'\\(\\)\\*\\+,;=".freeze + ALPHA = "a-zA-Z" + DIGIT = "0-9" + UNRESERVED = "#{ALPHA}#{DIGIT}\\-\\._~" + SUB_DELIMS = "!\\$&'\\(\\)\\*\\+,;=" ESCAPED = /%[a-zA-Z0-9]{2}/.freeze diff --git a/actionpack/lib/action_dispatch/journey/visitors.rb b/actionpack/lib/action_dispatch/journey/visitors.rb index 3395471a85..d2619cbf3a 100644 --- a/actionpack/lib/action_dispatch/journey/visitors.rb +++ b/actionpack/lib/action_dispatch/journey/visitors.rb @@ -40,7 +40,7 @@ module ActionDispatch @parameters.each do |index| param = parts[index] value = hash[param.name] - return "".freeze unless value + return "" unless value parts[index] = param.escape value end diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 34331b7e4b..26d3fd936f 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -9,7 +9,7 @@ require "rack/utils" module ActionDispatch class Request def cookie_jar - fetch_header("action_dispatch.cookies".freeze) do + fetch_header("action_dispatch.cookies") do self.cookie_jar = Cookies::CookieJar.build(self, cookies) end end @@ -22,11 +22,11 @@ module ActionDispatch } def have_cookie_jar? - has_header? "action_dispatch.cookies".freeze + has_header? "action_dispatch.cookies" end def cookie_jar=(jar) - set_header "action_dispatch.cookies".freeze, jar + set_header "action_dispatch.cookies", jar end def key_generator @@ -172,21 +172,21 @@ module ActionDispatch # * <tt>:httponly</tt> - Whether this cookie is accessible via scripting or # only HTTP. Defaults to +false+. class Cookies - HTTP_HEADER = "Set-Cookie".freeze - GENERATOR_KEY = "action_dispatch.key_generator".freeze - SIGNED_COOKIE_SALT = "action_dispatch.signed_cookie_salt".freeze - ENCRYPTED_COOKIE_SALT = "action_dispatch.encrypted_cookie_salt".freeze - ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt".freeze - AUTHENTICATED_ENCRYPTED_COOKIE_SALT = "action_dispatch.authenticated_encrypted_cookie_salt".freeze - USE_AUTHENTICATED_COOKIE_ENCRYPTION = "action_dispatch.use_authenticated_cookie_encryption".freeze - ENCRYPTED_COOKIE_CIPHER = "action_dispatch.encrypted_cookie_cipher".freeze - SIGNED_COOKIE_DIGEST = "action_dispatch.signed_cookie_digest".freeze - SECRET_TOKEN = "action_dispatch.secret_token".freeze - SECRET_KEY_BASE = "action_dispatch.secret_key_base".freeze - COOKIES_SERIALIZER = "action_dispatch.cookies_serializer".freeze - COOKIES_DIGEST = "action_dispatch.cookies_digest".freeze - COOKIES_ROTATIONS = "action_dispatch.cookies_rotations".freeze - USE_COOKIES_WITH_METADATA = "action_dispatch.use_cookies_with_metadata".freeze + HTTP_HEADER = "Set-Cookie" + GENERATOR_KEY = "action_dispatch.key_generator" + SIGNED_COOKIE_SALT = "action_dispatch.signed_cookie_salt" + ENCRYPTED_COOKIE_SALT = "action_dispatch.encrypted_cookie_salt" + ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt" + AUTHENTICATED_ENCRYPTED_COOKIE_SALT = "action_dispatch.authenticated_encrypted_cookie_salt" + USE_AUTHENTICATED_COOKIE_ENCRYPTION = "action_dispatch.use_authenticated_cookie_encryption" + ENCRYPTED_COOKIE_CIPHER = "action_dispatch.encrypted_cookie_cipher" + SIGNED_COOKIE_DIGEST = "action_dispatch.signed_cookie_digest" + SECRET_TOKEN = "action_dispatch.secret_token" + SECRET_KEY_BASE = "action_dispatch.secret_key_base" + COOKIES_SERIALIZER = "action_dispatch.cookies_serializer" + COOKIES_DIGEST = "action_dispatch.cookies_digest" + COOKIES_ROTATIONS = "action_dispatch.cookies_rotations" + USE_COOKIES_WITH_METADATA = "action_dispatch.use_cookies_with_metadata" # Cookies can typically store 4096 bytes. MAX_COOKIE_SIZE = 4096 @@ -535,7 +535,7 @@ module ActionDispatch end module SerializedCookieJars # :nodoc: - MARSHAL_SIGNATURE = "\x04\x08".freeze + MARSHAL_SIGNATURE = "\x04\x08" SERIALIZER = ActiveSupport::MessageEncryptor::NullSerializer protected diff --git a/actionpack/lib/action_dispatch/middleware/debug_locks.rb b/actionpack/lib/action_dispatch/middleware/debug_locks.rb index d39377f174..93c6c85a71 100644 --- a/actionpack/lib/action_dispatch/middleware/debug_locks.rb +++ b/actionpack/lib/action_dispatch/middleware/debug_locks.rb @@ -32,7 +32,7 @@ module ActionDispatch req = ActionDispatch::Request.new env if req.get? - path = req.path_info.chomp("/".freeze) + path = req.path_info.chomp("/") if path == @path return render_details(req) end diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb index fd05eec172..cf9165d008 100644 --- a/actionpack/lib/action_dispatch/middleware/flash.rb +++ b/actionpack/lib/action_dispatch/middleware/flash.rb @@ -38,7 +38,7 @@ module ActionDispatch # # See docs on the FlashHash class for more details about the flash. class Flash - KEY = "action_dispatch.request.flash_hash".freeze + KEY = "action_dispatch.request.flash_hash" module RequestMethods # Access the contents of the flash. Use <tt>flash["notice"]</tt> to diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb index da2871b551..fcc0c72240 100644 --- a/actionpack/lib/action_dispatch/middleware/request_id.rb +++ b/actionpack/lib/action_dispatch/middleware/request_id.rb @@ -15,7 +15,7 @@ module ActionDispatch # The unique request id can be used to trace a request end-to-end and would typically end up being part of log files # from multiple pieces of the stack. class RequestId - X_REQUEST_ID = "X-Request-Id".freeze #:nodoc: + X_REQUEST_ID = "X-Request-Id" #:nodoc: def initialize(app) @app = app @@ -30,7 +30,7 @@ module ActionDispatch private def make_request_id(request_id) if request_id.presence - request_id.gsub(/[^\w\-@]/, "".freeze).first(255) + request_id.gsub(/[^\w\-@]/, "").first(255) else internal_request_id end diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb index 9c9ccfa16f..00902ede21 100644 --- a/actionpack/lib/action_dispatch/middleware/ssl.rb +++ b/actionpack/lib/action_dispatch/middleware/ssl.rb @@ -83,7 +83,7 @@ module ActionDispatch private def set_hsts_header!(headers) - headers["Strict-Transport-Security".freeze] ||= @hsts_header + headers["Strict-Transport-Security"] ||= @hsts_header end def normalize_hsts_options(options) @@ -109,16 +109,16 @@ module ActionDispatch end def flag_cookies_as_secure!(headers) - if cookies = headers["Set-Cookie".freeze] - cookies = cookies.split("\n".freeze) + if cookies = headers["Set-Cookie"] + cookies = cookies.split("\n") - headers["Set-Cookie".freeze] = cookies.map { |cookie| + headers["Set-Cookie"] = cookies.map { |cookie| if !/;\s*secure\s*(;|$)/i.match?(cookie) "#{cookie}; secure" else cookie end - }.join("\n".freeze) + }.join("\n") end end diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index 277074f216..1f2f7757a3 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -79,7 +79,7 @@ module ActionDispatch end def content_type(path) - ::Rack::Mime.mime_type(::File.extname(path), "text/plain".freeze) + ::Rack::Mime.mime_type(::File.extname(path), "text/plain") end def gzip_encoding_accepted?(request) @@ -116,7 +116,7 @@ module ActionDispatch req = Rack::Request.new env if req.get? || req.head? - path = req.path_info.chomp("/".freeze) + path = req.path_info.chomp("/") if match = @file_handler.match?(path) req.path_info = match return @file_handler.serve(req) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 8b5a39dcaf..2f68cefa94 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -679,7 +679,7 @@ module ActionDispatch script_namer = ->(options) do prefix_options = options.slice(*_route.segment_keys) - prefix_options[:relative_url_root] = "".freeze + prefix_options[:relative_url_root] = "" if options[:_recall] prefix_options.reverse_merge!(options[:_recall].slice(*_route.segment_keys)) diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index e17ccaf986..4de5f9e2f7 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -181,8 +181,8 @@ module ActionDispatch CACHE[type].fetch(action) { build action, type } end - def self.url; CACHE["url".freeze][nil]; end - def self.path; CACHE["path".freeze][nil]; end + def self.url; CACHE["url"][nil]; end + def self.path; CACHE["path"][nil]; end def self.build(action, type) prefix = action ? "#{action}_" : "" diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index da4f285f61..3b7611acc0 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -377,7 +377,7 @@ module ActionDispatch @prepend = [] @disable_clear_and_finalize = false @finalized = false - @env_key = "ROUTES_#{object_id}_SCRIPT_NAME".freeze + @env_key = "ROUTES_#{object_id}_SCRIPT_NAME" @url_helpers = nil @deferred_classes = [] @@ -767,7 +767,7 @@ module ActionDispatch # Remove leading slashes from controllers def normalize_controller! if controller - if controller.start_with?("/".freeze) + if controller.start_with?("/") @options[:controller] = controller[1..-1] else @options[:controller] = controller @@ -858,10 +858,6 @@ module ActionDispatch path, params = generate(route_name, path_options, recall) - if options.key? :params - params.merge! options[:params] - end - options[:path] = path options[:script_name] = script_name options[:params] = params diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index d8cea10153..558e710df9 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -193,7 +193,7 @@ class UrlOptionsTest < ActionController::TestCase action: "home", controller: "pages", only_path: true, - params: { "token" => "secret" } + token: "secret" } assert_equal "/home?token=secret", rs.url_for(options) diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index b97454f1a4..30f2a23b33 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -25,8 +25,8 @@ class UriReservedCharactersRoutingTest < ActiveSupport::TestCase safe, unsafe = %w(: @ & = + $ , ;), %w(^ ? # [ ]) hex = unsafe.map { |char| "%" + char.unpack1("H2").upcase } - @segment = "#{safe.join}#{unsafe.join}".freeze - @escaped = "#{safe.join}#{hex.join}".freeze + @segment = "#{safe.join}#{unsafe.join}" + @escaped = "#{safe.join}#{hex.join}" end def test_route_generation_escapes_unsafe_path_characters diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb index dda2686a9b..6fc70d6248 100644 --- a/actionpack/test/controller/test_case_test.rb +++ b/actionpack/test/controller/test_case_test.rb @@ -542,7 +542,7 @@ XML def test_params_passing_with_frozen_values assert_nothing_raised do get :test_params, params: { - frozen: "icy".freeze, frozens: ["icy".freeze].freeze, deepfreeze: { frozen: "icy".freeze }.freeze + frozen: -"icy", frozens: [-"icy"].freeze, deepfreeze: { frozen: -"icy" }.freeze } end parsed_params = ::JSON.parse(@response.body) diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb index cbcce4a4dc..3d7c8dae75 100644 --- a/actionview/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb @@ -98,7 +98,7 @@ module ActionView if tag_options["nonce"] == true tag_options["nonce"] = content_security_policy_nonce end - content_tag("script".freeze, "", tag_options) + content_tag("script", "", tag_options) }.join("\n").html_safe request.send_early_hints("Link" => early_hints_links.join("\n")) if respond_to?(:request) && request @@ -375,7 +375,7 @@ module ActionView def image_alt(src) ActiveSupport::Deprecation.warn("image_alt is deprecated and will be removed from Rails 6.0. You must explicitly set alt text on images.") - File.basename(src, ".*".freeze).sub(/-[[:xdigit:]]{32,64}\z/, "".freeze).tr("-_".freeze, " ".freeze).capitalize + File.basename(src, ".*").sub(/-[[:xdigit:]]{32,64}\z/, "").tr("-_", " ").capitalize end # Returns an HTML video tag for the +sources+. If +sources+ is a string, diff --git a/actionview/lib/action_view/helpers/asset_url_helper.rb b/actionview/lib/action_view/helpers/asset_url_helper.rb index 1808765666..cc62783d60 100644 --- a/actionview/lib/action_view/helpers/asset_url_helper.rb +++ b/actionview/lib/action_view/helpers/asset_url_helper.rb @@ -188,7 +188,7 @@ module ActionView return "" if source.blank? return source if URI_REGEXP.match?(source) - tail, source = source[/([\?#].+)$/], source.sub(/([\?#].+)$/, "".freeze) + tail, source = source[/([\?#].+)$/], source.sub(/([\?#].+)$/, "") if extname = compute_asset_extname(source, options) source = "#{source}#{extname}" diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb index ecdad14f90..9d5e5eaba3 100644 --- a/actionview/lib/action_view/helpers/date_helper.rb +++ b/actionview/lib/action_view/helpers/date_helper.rb @@ -684,7 +684,7 @@ module ActionView format = options.delete(:format) || :long content = args.first || I18n.l(date_or_time, format: format) - content_tag("time".freeze, content, options.reverse_merge(datetime: date_or_time.iso8601), &block) + content_tag("time", content, options.reverse_merge(datetime: date_or_time.iso8601), &block) end private @@ -703,7 +703,7 @@ module ActionView class DateTimeSelector #:nodoc: include ActionView::Helpers::TagHelper - DEFAULT_PREFIX = "date".freeze + DEFAULT_PREFIX = "date" POSITION = { year: 1, month: 2, day: 3, hour: 4, minute: 5, second: 6 }.freeze @@ -824,7 +824,7 @@ module ActionView 1.upto(12) do |month_number| options = { value: month_number } options[:selected] = "selected" if month == month_number - month_options << content_tag("option".freeze, month_name(month_number), options) + "\n" + month_options << content_tag("option", month_name(month_number), options) + "\n" end build_select(:month, month_options.join) end @@ -1006,7 +1006,7 @@ module ActionView tag_options[:selected] = "selected" if selected == i text = options[:use_two_digit_numbers] ? sprintf("%02d", i) : value text = options[:ampm] ? AMPM_TRANSLATION[i] : text - select_options << content_tag("option".freeze, text, tag_options) + select_options << content_tag("option", text, tag_options) end (select_options.join("\n") + "\n").html_safe @@ -1034,7 +1034,7 @@ module ActionView tag_options = { value: value } tag_options[:selected] = "selected" if selected == value text = year_name(value) - select_options << content_tag("option".freeze, text, tag_options) + select_options << content_tag("option", text, tag_options) end (select_options.join("\n") + "\n").html_safe @@ -1054,11 +1054,11 @@ module ActionView select_options[:class] = css_class_attribute(type, select_options[:class], @options[:with_css_classes]) if @options[:with_css_classes] select_html = +"\n" - select_html << content_tag("option".freeze, "", value: "") + "\n" if @options[:include_blank] + select_html << content_tag("option", "", value: "") + "\n" if @options[:include_blank] select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt] select_html << select_options_as_html - (content_tag("select".freeze, select_html.html_safe, select_options) + "\n").html_safe + (content_tag("select", select_html.html_safe, select_options) + "\n").html_safe end # Builds the css class value for the select element @@ -1091,7 +1091,7 @@ module ActionView I18n.translate(:"datetime.prompts.#{type}", locale: @options[:locale]) end - prompt ? content_tag("option".freeze, prompt, value: "") : "" + prompt ? content_tag("option", prompt, value: "") : "" end # Builds hidden input tag for date part and value. diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index 2b9d55a019..ebdd96f570 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -463,7 +463,7 @@ module ActionView option_tags = options_from_collection_for_select( value_for_collection(group, group_method), option_key_method, option_value_method, selected_key) - content_tag("optgroup".freeze, option_tags, label: value_for_collection(group, group_label_method)) + content_tag("optgroup", option_tags, label: value_for_collection(group, group_label_method)) end.join.html_safe end @@ -535,7 +535,7 @@ module ActionView body = "".html_safe if prompt - body.safe_concat content_tag("option".freeze, prompt_text(prompt), value: "") + body.safe_concat content_tag("option", prompt_text(prompt), value: "") end grouped_options.each do |container| @@ -548,7 +548,7 @@ module ActionView end html_attributes = { label: label }.merge!(html_attributes) - body.safe_concat content_tag("optgroup".freeze, options_for_select(container, selected_key), html_attributes) + body.safe_concat content_tag("optgroup", options_for_select(container, selected_key), html_attributes) end body @@ -584,7 +584,7 @@ module ActionView end zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected) - zone_options.safe_concat content_tag("option".freeze, "-------------", value: "", disabled: true) + zone_options.safe_concat content_tag("option", "-------------", value: "", disabled: true) zone_options.safe_concat "\n" zones = zones - priority_zones diff --git a/actionview/lib/action_view/helpers/form_tag_helper.rb b/actionview/lib/action_view/helpers/form_tag_helper.rb index ba09738beb..c0996049f0 100644 --- a/actionview/lib/action_view/helpers/form_tag_helper.rb +++ b/actionview/lib/action_view/helpers/form_tag_helper.rb @@ -146,15 +146,15 @@ module ActionView end if include_blank - option_tags = content_tag("option".freeze, include_blank, options_for_blank_options_tag).safe_concat(option_tags) + option_tags = content_tag("option", include_blank, options_for_blank_options_tag).safe_concat(option_tags) end end if prompt = options.delete(:prompt) - option_tags = content_tag("option".freeze, prompt, value: "").safe_concat(option_tags) + option_tags = content_tag("option", prompt, value: "").safe_concat(option_tags) end - content_tag "select".freeze, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys) + content_tag "select", option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys) end # Creates a standard text field; use these text fields to input smaller chunks of text like a username @@ -577,7 +577,7 @@ module ActionView # # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset> def field_set_tag(legend = nil, options = nil, &block) output = tag(:fieldset, options, true) - output.safe_concat(content_tag("legend".freeze, legend)) unless legend.blank? + output.safe_concat(content_tag("legend", legend)) unless legend.blank? output.concat(capture(&block)) if block_given? output.safe_concat("</fieldset>") end diff --git a/actionview/lib/action_view/helpers/javascript_helper.rb b/actionview/lib/action_view/helpers/javascript_helper.rb index ac6ec5a86c..b680cb1bd3 100644 --- a/actionview/lib/action_view/helpers/javascript_helper.rb +++ b/actionview/lib/action_view/helpers/javascript_helper.rb @@ -84,7 +84,7 @@ module ActionView html_options[:nonce] = content_security_policy_nonce end - content_tag("script".freeze, javascript_cdata_section(content), html_options) + content_tag("script", javascript_cdata_section(content), html_options) end def javascript_cdata_section(content) #:nodoc: diff --git a/actionview/lib/action_view/helpers/tag_helper.rb b/actionview/lib/action_view/helpers/tag_helper.rb index a93d7faa32..3979721d34 100644 --- a/actionview/lib/action_view/helpers/tag_helper.rb +++ b/actionview/lib/action_view/helpers/tag_helper.rb @@ -86,11 +86,11 @@ module ActionView def tag_option(key, value, escape) if value.is_a?(Array) - value = escape ? safe_join(value, " ".freeze) : value.join(" ".freeze) + value = escape ? safe_join(value, " ") : value.join(" ") else value = escape ? ERB::Util.unwrapped_html_escape(value) : value.to_s.dup end - value.gsub!('"'.freeze, """.freeze) + value.gsub!('"', """) %(#{key}="#{value}") end diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb index 52bffaab84..948dd1551f 100644 --- a/actionview/lib/action_view/helpers/url_helper.rb +++ b/actionview/lib/action_view/helpers/url_helper.rb @@ -200,9 +200,9 @@ module ActionView html_options = convert_options_to_data_attributes(options, html_options) url = url_for(options) - html_options["href".freeze] ||= url + html_options["href"] ||= url - content_tag("a".freeze, name || url, html_options, &block) + content_tag("a", name || url, html_options, &block) end # Generates a form containing a single button that submits to the URL created @@ -308,7 +308,7 @@ module ActionView params = html_options.delete("params") method = html_options.delete("method").to_s - method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : "".freeze.html_safe + method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : "".html_safe form_method = method == "get" ? "get" : "post" form_options = html_options.delete("form") || {} @@ -321,7 +321,7 @@ module ActionView request_method = method.empty? ? "post" : method token_tag(nil, form_options: { action: url, method: request_method }) else - "".freeze + "" end html_options = convert_options_to_data_attributes(options, html_options) @@ -487,12 +487,12 @@ module ActionView option = html_options.delete(item).presence || next "#{item.dasherize}=#{ERB::Util.url_encode(option)}" }.compact - extras = extras.empty? ? "".freeze : "?" + extras.join("&") + extras = extras.empty? ? "" : "?" + extras.join("&") encoded_email_address = ERB::Util.url_encode(email_address).gsub("%40", "@") html_options["href"] = "mailto:#{encoded_email_address}#{extras}" - content_tag("a".freeze, name || email_address, html_options, &block) + content_tag("a", name || email_address, html_options, &block) end # True if the current request URI was generated by the given +options+. @@ -575,21 +575,21 @@ module ActionView def convert_options_to_data_attributes(options, html_options) if html_options html_options = html_options.stringify_keys - html_options["data-remote"] = "true".freeze if link_to_remote_options?(options) || link_to_remote_options?(html_options) + html_options["data-remote"] = "true" if link_to_remote_options?(options) || link_to_remote_options?(html_options) - method = html_options.delete("method".freeze) + method = html_options.delete("method") add_method_to_attributes!(html_options, method) if method html_options else - link_to_remote_options?(options) ? { "data-remote" => "true".freeze } : {} + link_to_remote_options?(options) ? { "data-remote" => "true" } : {} end end def link_to_remote_options?(options) if options.is_a?(Hash) - options.delete("remote".freeze) || options.delete(:remote) + options.delete("remote") || options.delete(:remote) end end @@ -622,7 +622,7 @@ module ActionView token ||= form_authenticity_token(form_options: form_options) tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token) else - "".freeze + "" end end diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb index 0e56eca35c..af67ffa12d 100644 --- a/actionview/lib/action_view/lookup_context.rb +++ b/actionview/lib/action_view/lookup_context.rb @@ -202,13 +202,13 @@ module ActionView # name instead of the prefix. def normalize_name(name, prefixes) prefixes = prefixes.presence - parts = name.to_s.split("/".freeze) + parts = name.to_s.split("/") parts.shift if parts.first.empty? name = parts.pop return name, prefixes || [""] if parts.empty? - parts = parts.join("/".freeze) + parts = parts.join("/") prefixes = prefixes ? prefixes.map { |p| "#{p}/#{parts}" } : [parts] return name, prefixes @@ -245,7 +245,7 @@ module ActionView # add :html as fallback to :js. def formats=(values) if values - values.concat(default_formats) if values.delete "*/*".freeze + values.concat(default_formats) if values.delete "*/*" if values == [:js] values << :html @html_fallback_for_js = true diff --git a/actionview/lib/action_view/record_identifier.rb b/actionview/lib/action_view/record_identifier.rb index 1310a1ce0a..ee39b6050d 100644 --- a/actionview/lib/action_view/record_identifier.rb +++ b/actionview/lib/action_view/record_identifier.rb @@ -59,8 +59,8 @@ module ActionView include ModelNaming - JOIN = "_".freeze - NEW = "new".freeze + JOIN = "_" + NEW = "new" # The DOM class convention is to use the singular form of an object or class. # diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb index d7f97c3b50..cb850d75ee 100644 --- a/actionview/lib/action_view/renderer/partial_renderer.rb +++ b/actionview/lib/action_view/renderer/partial_renderer.rb @@ -523,7 +523,7 @@ module ActionView def retrieve_variable(path, as) variable = as || begin - base = path[-1] == "/".freeze ? "".freeze : File.basename(path) + base = path[-1] == "/" ? "" : File.basename(path) raise_invalid_identifier(path) unless base =~ /\A_?(.*?)(?:\.\w+)*\z/ $1.to_sym end diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb index 18a5dae270..d7aee18a84 100644 --- a/actionview/lib/action_view/template.rb +++ b/actionview/lib/action_view/template.rb @@ -188,7 +188,7 @@ module ActionView end def inspect - @inspect ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", "".freeze) : identifier + @inspect ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", "") : identifier end # This method is responsible for properly setting the encoding of the @@ -235,6 +235,19 @@ module ActionView end end + + # Exceptions are marshalled when using the parallel test runner with DRb, so we need + # to ensure that references to the template object can be marshalled as well. This means forgoing + # the marshalling of the compiler mutex and instantiating that again on unmarshalling. + def marshal_dump # :nodoc: + [ @source, @identifier, @handler, @compiled, @original_encoding, @locals, @virtual_path, @updated_at, @formats, @variants ] + end + + def marshal_load(array) # :nodoc: + @source, @identifier, @handler, @compiled, @original_encoding, @locals, @virtual_path, @updated_at, @formats, @variants = *array + @compile_mutex = Mutex.new + end + private # Compile a template. This method ensures a template is compiled @@ -341,13 +354,13 @@ module ActionView def method_name @method_name ||= begin m = +"_#{identifier_method_name}__#{@identifier.hash}_#{__id__}" - m.tr!("-".freeze, "_".freeze) + m.tr!("-", "_") m end end def identifier_method_name - inspect.tr("^a-z_".freeze, "_".freeze) + inspect.tr("^a-z_", "_") end def instrument(action, &block) # :doc: @@ -355,7 +368,7 @@ module ActionView end def instrument_render_template(&block) - ActiveSupport::Notifications.instrument("!render_template.action_view".freeze, instrument_payload, &block) + ActiveSupport::Notifications.instrument("!render_template.action_view", instrument_payload, &block) end def instrument_payload diff --git a/actionview/lib/action_view/template/resolver.rb b/actionview/lib/action_view/template/resolver.rb index 5027303e86..08dd6fb510 100644 --- a/actionview/lib/action_view/template/resolver.rb +++ b/actionview/lib/action_view/template/resolver.rb @@ -282,7 +282,7 @@ module ActionView end def escape_entry(entry) - entry.gsub(/[*?{}\[\]]/, '\\\\\\&'.freeze) + entry.gsub(/[*?{}\[\]]/, '\\\\\\&') end # Returns the file mtime from the filesystem. @@ -294,7 +294,7 @@ module ActionView # from the path, or the handler, we should return the array of formats given # to the resolver. def extract_handler_and_format_and_variant(path) - pieces = File.basename(path).split(".".freeze) + pieces = File.basename(path).split(".") pieces.shift extension = pieces.pop diff --git a/actionview/test/template/template_test.rb b/actionview/test/template/template_test.rb index 3dc14e36e0..b348d1f17b 100644 --- a/actionview/test/template/template_test.rb +++ b/actionview/test/template/template_test.rb @@ -196,6 +196,13 @@ class TestERBTemplate < ActiveSupport::TestCase assert_match(Regexp.new("\xFC"), e.message) end + def test_template_is_marshalable + template = new_template + serialized = Marshal.load(Marshal.dump(template)) + assert_equal template.identifier, serialized.identifier + assert_equal template.source, serialized.source + end + def with_external_encoding(encoding) old = Encoding.default_external Encoding::Converter.new old, encoding if old != encoding diff --git a/actionview/test/template/text_helper_test.rb b/actionview/test/template/text_helper_test.rb index c4e420a95b..2925489f5d 100644 --- a/actionview/test/template/text_helper_test.rb +++ b/actionview/test/template/text_helper_test.rb @@ -34,10 +34,10 @@ class TextHelperTest < ActionView::TestCase assert_equal "<p>A paragraph</p>\n\n<p>and another one!</p>", simple_format("A paragraph\n\nand another one!") assert_equal "<p>A paragraph\n<br /> With a newline</p>", simple_format("A paragraph\n With a newline") - text = "A\nB\nC\nD".freeze + text = "A\nB\nC\nD" assert_equal "<p>A\n<br />B\n<br />C\n<br />D</p>", simple_format(text) - text = "A\r\n \nB\n\n\r\n\t\nC\nD".freeze + text = "A\r\n \nB\n\n\r\n\t\nC\nD" assert_equal "<p>A\n<br /> \n<br />B</p>\n\n<p>\t\n<br />C\n<br />D</p>", simple_format(text) assert_equal '<p class="test">This is a classy test</p>', simple_format("This is a classy test", class: "test") diff --git a/activejob/lib/active_job/arguments.rb b/activejob/lib/active_job/arguments.rb index b344c44aef..8dcf588f35 100644 --- a/activejob/lib/active_job/arguments.rb +++ b/activejob/lib/active_job/arguments.rb @@ -47,11 +47,11 @@ module ActiveJob private # :nodoc: - GLOBALID_KEY = "_aj_globalid".freeze + GLOBALID_KEY = "_aj_globalid" # :nodoc: - SYMBOL_KEYS_KEY = "_aj_symbol_keys".freeze + SYMBOL_KEYS_KEY = "_aj_symbol_keys" # :nodoc: - WITH_INDIFFERENT_ACCESS_KEY = "_aj_hash_with_indifferent_access".freeze + WITH_INDIFFERENT_ACCESS_KEY = "_aj_hash_with_indifferent_access" # :nodoc: OBJECT_SERIALIZER_KEY = "_aj_serialized" diff --git a/activejob/lib/active_job/queue_adapters.rb b/activejob/lib/active_job/queue_adapters.rb index 00c7b407b1..3e3a474fbb 100644 --- a/activejob/lib/active_job/queue_adapters.rb +++ b/activejob/lib/active_job/queue_adapters.rb @@ -121,7 +121,7 @@ module ActiveJob autoload :SuckerPunchAdapter autoload :TestAdapter - ADAPTER = "Adapter".freeze + ADAPTER = "Adapter" private_constant :ADAPTER class << self diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 888a431e5f..1ad9071cc2 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -369,7 +369,7 @@ module ActiveModel "define_method(:'#{name}') do |*args|" end - extra = (extra.map!(&:inspect) << "*args").join(", ".freeze) + extra = (extra.map!(&:inspect) << "*args").join(", ") target = if CALL_COMPILABLE_REGEXP.match?(send) "#{"self." unless include_private}#{send}(#{extra})" diff --git a/activemodel/lib/active_model/attributes.rb b/activemodel/lib/active_model/attributes.rb index 5bf213d593..41fe5168f3 100644 --- a/activemodel/lib/active_model/attributes.rb +++ b/activemodel/lib/active_model/attributes.rb @@ -29,7 +29,7 @@ module ActiveModel private def define_method_attribute=(name) - safe_name = name.unpack1("h*".freeze) + safe_name = name.unpack1("h*") ActiveModel::AttributeMethods::AttrNames.set_name_cache safe_name, name generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1 diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb index cdc1282817..82713ddc81 100644 --- a/activemodel/lib/active_model/conversion.rb +++ b/activemodel/lib/active_model/conversion.rb @@ -103,7 +103,7 @@ module ActiveModel @_to_partial_path ||= begin element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(name)) collection = ActiveSupport::Inflector.tableize(name) - "#{collection}/#{element}".freeze + "#{collection}/#{element}" end end end diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index 983401801f..5f3d674c4e 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -209,7 +209,7 @@ module ActiveModel private def _singularize(string) - ActiveSupport::Inflector.underscore(string).tr("/".freeze, "_".freeze) + ActiveSupport::Inflector.underscore(string).tr("/", "_") end end diff --git a/activemodel/lib/active_model/type/string.rb b/activemodel/lib/active_model/type/string.rb index 36f13945b1..a9c9bfadb6 100644 --- a/activemodel/lib/active_model/type/string.rb +++ b/activemodel/lib/active_model/type/string.rb @@ -16,8 +16,8 @@ module ActiveModel def cast_value(value) case value when ::String then ::String.new(value) - when true then "t".freeze - when false then "f".freeze + when true then "t" + when false then "f" else value.to_s end end diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 88cca318ef..21c4ce0dfe 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -116,7 +116,7 @@ module ActiveModel key = "#{key.to_s.camelize}Validator" begin - validator = key.include?("::".freeze) ? key.constantize : const_get(key) + validator = key.include?("::") ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end diff --git a/activemodel/test/cases/attribute_set_test.rb b/activemodel/test/cases/attribute_set_test.rb index b868dba743..62feb9074e 100644 --- a/activemodel/test/cases/attribute_set_test.rb +++ b/activemodel/test/cases/attribute_set_test.rb @@ -217,7 +217,7 @@ module ActiveModel assert_equal({ foo: "1" }, attributes.to_hash) end - test "marshaling dump/load legacy materialized attribute hash" do + test "marshalling dump/load legacy materialized attribute hash" do builder = AttributeSet::Builder.new(foo: Type::String.new) attributes = builder.build_from_database(foo: "1") diff --git a/activemodel/test/cases/type/string_test.rb b/activemodel/test/cases/type/string_test.rb index 5469fdb7af..2d85556d20 100644 --- a/activemodel/test/cases/type/string_test.rb +++ b/activemodel/test/cases/type/string_test.rb @@ -19,7 +19,7 @@ module ActiveModel assert_equal false, type.cast(s).frozen? assert_equal false, s.frozen? - f = "foo".freeze + f = -"foo" assert_equal false, type.cast(f).frozen? assert_equal true, f.frozen? end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 7bcf755258..96fd6a62c6 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,15 @@ +* Added `index` option for `change_table` migration helpers. + With this change you can create indexes while adding new + columns into the existing tables. + + Example: + + change_table(:languages) do |t| + t.string :country_code, index: true + end + + *Mehmet Emin İNAÇ* + * Fix `transaction` reverting for migrations. Before: Commands inside a `transaction` in a reverted migration ran uninverted. 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 e3070e0472..0140aa15c8 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 @@ -63,7 +63,7 @@ module ActiveRecord::Associations::Builder # :nodoc: def middle_reflection(join_model) middle_name = [lhs_model.name.downcase.pluralize, - association_name].join("_".freeze).gsub("::".freeze, "_".freeze).to_sym + association_name].join("_").gsub("::", "_").to_sym middle_options = middle_options join_model HasMany.create_reflection(lhs_model, diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 42eba27b2a..221ebea8ea 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -272,9 +272,9 @@ module ActiveRecord case name when :to_partial_path - name = "to_partial_path".freeze + name = "to_partial_path" when :to_model - name = "to_model".freeze + name = "to_model" else name = name.to_s end diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 0f7bcba564..903fe86e04 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -27,7 +27,7 @@ module ActiveRecord # Making it frozen means that it doesn't get duped when used to # key the @attributes in read_attribute. def define_method_attribute(name) - safe_name = name.unpack1("h*".freeze) + safe_name = name.unpack1("h*") temp_method = "__temp__#{safe_name}" ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name @@ -59,7 +59,7 @@ module ActiveRecord end primary_key = self.class.primary_key - name = primary_key if name == "id".freeze && primary_key + name = primary_key if name == "id" && primary_key sync_with_transaction_state if name == primary_key _read_attribute(name, &block) end diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index c7521422bb..62743bc9d8 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -13,7 +13,7 @@ module ActiveRecord private def define_method_attribute=(name) - safe_name = name.unpack1("h*".freeze) + safe_name = name.unpack1("h*") ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key @@ -40,7 +40,7 @@ module ActiveRecord end primary_key = self.class.primary_key - name = primary_key if name == "id".freeze && primary_key + name = primary_key if name == "id" && primary_key sync_with_transaction_state if name == primary_key _write_attribute(name, value) end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index c10da813ec..feacdf6931 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -35,7 +35,7 @@ module ActiveRecord sql, binds = visitor.compile(arel.ast, collector) query = klass.query(sql) else - collector = PartialQueryCollector.new + collector = klass.partial_query_collector parts, binds = visitor.compile(arel.ast, collector) query = klass.partial_query(parts) end @@ -507,28 +507,6 @@ module ActiveRecord value end end - - class PartialQueryCollector - def initialize - @parts = [] - @binds = [] - end - - def <<(str) - @parts << str - self - end - - def add_bind(obj) - @binds << obj - @parts << Arel::Nodes::BindParam.new(1) - self - end - - def value - [@parts, @binds] - end - end end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 98b1348135..07e86afe9a 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -60,7 +60,7 @@ module ActiveRecord # Quotes a string, escaping any ' (single quote) and \ (backslash) # characters. def quote_string(s) - s.gsub('\\'.freeze, '\&\&'.freeze).gsub("'".freeze, "''".freeze) # ' (for ruby-mode) + s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode) end # Quotes the column name. Defaults to no quoting. @@ -95,7 +95,7 @@ module ActiveRecord end def quoted_true - "TRUE".freeze + "TRUE" end def unquoted_true @@ -103,7 +103,7 @@ module ActiveRecord end def quoted_false - "FALSE".freeze + "FALSE" end def unquoted_false diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 582ac516c7..015204c056 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -527,7 +527,9 @@ module ActiveRecord # # See TableDefinition#column for details of the options you can use. def column(column_name, type, options = {}) + index_options = options.delete(:index) @base.add_column(name, column_name, type, options) + index(column_name, index_options.is_a?(Hash) ? index_options : {}) if index_options end # Checks to see if a column exists. diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 79aafc956f..fa10f18cb7 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -65,7 +65,7 @@ module ActiveRecord # Most of the methods in the adapter are useful during migrations. Most # notably, the instance methods provided by SchemaStatements are very useful. class AbstractAdapter - ADAPTER_NAME = "Abstract".freeze + ADAPTER_NAME = "Abstract" include ActiveSupport::Callbacks define_callbacks :checkout, :checkin diff --git a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb index be038403b8..75564a61d6 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb @@ -5,7 +5,7 @@ module ActiveRecord module MySQL module Quoting # :nodoc: def quote_column_name(name) - @quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`".freeze + @quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`" end def quote_table_name(name) diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index 10c8c8e8ab..9bdaa00336 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -14,7 +14,7 @@ module ActiveRecord config[:flags] ||= 0 if config[:flags].kind_of? Array - config[:flags].push "FOUND_ROWS".freeze + config[:flags].push "FOUND_ROWS" else config[:flags] |= Mysql2::Client::FOUND_ROWS end @@ -32,7 +32,7 @@ module ActiveRecord module ConnectionAdapters class Mysql2Adapter < AbstractMysqlAdapter - ADAPTER_NAME = "Mysql2".freeze + ADAPTER_NAME = "Mysql2" include MySQL::DatabaseStatements diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb index 79351bc3a4..83c21ba6ea 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb @@ -19,10 +19,10 @@ module ActiveRecord def run(records) nodes = records.reject { |row| @store.key? row["oid"].to_i } mapped = nodes.extract! { |row| @store.key? row["typname"] } - ranges = nodes.extract! { |row| row["typtype"] == "r".freeze } - enums = nodes.extract! { |row| row["typtype"] == "e".freeze } - domains = nodes.extract! { |row| row["typtype"] == "d".freeze } - arrays = nodes.extract! { |row| row["typinput"] == "array_in".freeze } + ranges = nodes.extract! { |row| row["typtype"] == "r" } + enums = nodes.extract! { |row| row["typtype"] == "e" } + domains = nodes.extract! { |row| row["typtype"] == "d" } + arrays = nodes.extract! { |row| row["typinput"] == "array_in" } composites = nodes.extract! { |row| row["typelem"].to_i != 0 } mapped.each { |row| register_mapped_type(row) } 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 ffd3be26b0..cd69d28139 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata.rb @@ -17,7 +17,7 @@ module ActiveRecord end def sql_type - super.gsub(/\[\]$/, "".freeze) + super.gsub(/\[\]$/, "") end def ==(other) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 11593f71c9..bc6eb11572 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -78,7 +78,7 @@ module ActiveRecord # In addition, default connection parameters of libpq can be set per environment variables. # See https://www.postgresql.org/docs/current/static/libpq-envars.html . class PostgreSQLAdapter < AbstractAdapter - ADAPTER_NAME = "PostgreSQL".freeze + ADAPTER_NAME = "PostgreSQL" NATIVE_DATABASE_TYPES = { primary_key: "bigserial primary key", @@ -448,7 +448,7 @@ module ActiveRecord end end - def get_oid_type(oid, fmod, column_name, sql_type = "".freeze) + def get_oid_type(oid, fmod, column_name, sql_type = "") if !type_map.key?(oid) load_additional_types([oid]) end @@ -537,13 +537,13 @@ module ActiveRecord # Quoted types when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m # The default 'now'::date is CURRENT_DATE - if $1 == "now".freeze && $2 == "date".freeze + if $1 == "now" && $2 == "date" nil else - $1.gsub("''".freeze, "'".freeze) + $1.gsub("''", "'") end # Boolean types - when "true".freeze, "false".freeze + when "true", "false" default # Numeric types when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/ @@ -655,7 +655,7 @@ module ActiveRecord # # Check here for more details: # https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573 - CACHED_PLAN_HEURISTIC = "cached plan must not change result type".freeze + CACHED_PLAN_HEURISTIC = "cached plan must not change result type" def is_cached_plan_failure?(e) pgerror = e.cause code = pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE) diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb index abedf01f10..b2dcdb5373 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb @@ -13,7 +13,7 @@ module ActiveRecord end def quote_column_name(name) - @quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}").freeze + @quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}") end def quoted_time(value) @@ -26,19 +26,19 @@ module ActiveRecord end def quoted_true - ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "1".freeze : "'t'".freeze + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "1" : "'t'" end def unquoted_true - ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 1 : "t".freeze + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 1 : "t" end def quoted_false - ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "0".freeze : "'f'".freeze + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "0" : "'f'" end def unquoted_false - ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 0 : "f".freeze + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 0 : "f" end private diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index baa0a29afd..81882f6cc1 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -56,7 +56,7 @@ module ActiveRecord # # * <tt>:database</tt> - Path to the database file. class SQLite3Adapter < AbstractAdapter - ADAPTER_NAME = "SQLite".freeze + ADAPTER_NAME = "SQLite" include SQLite3::Quoting include SQLite3::SchemaStatements diff --git a/activerecord/lib/active_record/database_configurations/database_config.rb b/activerecord/lib/active_record/database_configurations/database_config.rb index 6250827b34..adc37cc439 100644 --- a/activerecord/lib/active_record/database_configurations/database_config.rb +++ b/activerecord/lib/active_record/database_configurations/database_config.rb @@ -17,6 +17,10 @@ module ActiveRecord raise NotImplementedError end + def migrations_paths + raise NotImplementedError + end + def url_config? false end diff --git a/activerecord/lib/active_record/database_configurations/hash_config.rb b/activerecord/lib/active_record/database_configurations/hash_config.rb index 13ffe566cf..c176a62458 100644 --- a/activerecord/lib/active_record/database_configurations/hash_config.rb +++ b/activerecord/lib/active_record/database_configurations/hash_config.rb @@ -38,6 +38,13 @@ module ActiveRecord def replica? config["replica"] end + + # The migrations paths for a database configuration. If the + # `migrations_paths` key is present in the config, `migrations_paths` + # will return its value. + def migrations_paths + config["migrations_paths"] + end end end end diff --git a/activerecord/lib/active_record/database_configurations/url_config.rb b/activerecord/lib/active_record/database_configurations/url_config.rb index f526c59d56..81917fc4c1 100644 --- a/activerecord/lib/active_record/database_configurations/url_config.rb +++ b/activerecord/lib/active_record/database_configurations/url_config.rb @@ -48,6 +48,13 @@ module ActiveRecord config["replica"] end + # The migrations paths for a database configuration. If the + # `migrations_paths` key is present in the config, `migrations_paths` + # will return its value. + def migrations_paths + config["migrations_paths"] + end + private def build_config(original_config, url) if /^jdbc:/.match?(url) diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index b25057acda..138fd1cf53 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -180,7 +180,7 @@ module ActiveRecord # 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) - if type_name.start_with?("::".freeze) + if type_name.start_with?("::") # If the type is prefixed with a scope operator then we assume that # the type_name is an absolute reference. ActiveSupport::Dependencies.constantize(type_name) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index d712d4b3cf..6e5a610642 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -140,8 +140,8 @@ module ActiveRecord end class ConcurrentMigrationError < MigrationError #:nodoc: - DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running.".freeze - RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock".freeze + DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running." + RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock" def initialize(message = DEFAULT_MESSAGE) super diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index db06bd9e26..d8cff30b88 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -356,11 +356,12 @@ module ActiveRecord stmt.set Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name)) end - if has_join_values? || offset_value + if has_join_values? @klass.connection.join_to_update(stmt, arel, arel_attribute(primary_key)) else stmt.key = arel_attribute(primary_key) stmt.take(arel.limit) + stmt.offset(arel.offset) stmt.order(*arel.orders) stmt.wheres = arel.constraints end @@ -484,9 +485,13 @@ module ActiveRecord stmt = Arel::DeleteManager.new stmt.from(table) - if has_join_values? || has_limit_or_offset? + if has_join_values? @klass.connection.join_to_delete(stmt, arel, arel_attribute(primary_key)) else + stmt.key = arel_attribute(primary_key) + stmt.take(arel.limit) + stmt.offset(arel.offset) + stmt.order(*arel.orders) stmt.wheres = arel.constraints end diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index 488f71cdde..8f657840f5 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -17,7 +17,7 @@ module ActiveRecord delegate = Class.new(klass) { include ClassSpecificRelation } - mangled_name = klass.name.gsub("::".freeze, "_".freeze) + mangled_name = klass.name.gsub("::", "_") const_set mangled_name, delegate private_constant mangled_name diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index f734cd0ad8..b59ff912fe 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -27,7 +27,7 @@ module ActiveRecord key else key = key.to_s - key.split(".".freeze).first if key.include?(".".freeze) + key.split(".").first if key.include?(".") end end.compact end @@ -115,11 +115,11 @@ module ActiveRecord def convert_dot_notation_to_hash(attributes) dot_notation = attributes.select do |k, v| - k.include?(".".freeze) && !v.is_a?(Hash) + k.include?(".") && !v.is_a?(Hash) end dot_notation.each_key do |key| - table_name, column_name = key.split(".".freeze) + table_name, column_name = key.split(".") value = attributes.delete(key) attributes[table_name] ||= {} diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 56497e11cb..5170d38fa8 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -939,7 +939,7 @@ module ActiveRecord arel.having(having_clause.ast) unless having_clause.empty? if limit_value limit_attribute = ActiveModel::Attribute.with_cast_value( - "LIMIT".freeze, + "LIMIT", connection.sanitize_limit(limit_value), Type.default_value, ) @@ -947,7 +947,7 @@ module ActiveRecord end if offset_value offset_attribute = ActiveModel::Attribute.with_cast_value( - "OFFSET".freeze, + "OFFSET", offset_value.to_i, Type.default_value, ) diff --git a/activerecord/lib/active_record/statement_cache.rb b/activerecord/lib/active_record/statement_cache.rb index b41d3504fd..1b1736dcab 100644 --- a/activerecord/lib/active_record/statement_cache.rb +++ b/activerecord/lib/active_record/statement_cache.rb @@ -44,7 +44,7 @@ module ActiveRecord def initialize(values) @values = values @indexes = values.each_with_index.find_all { |thing, i| - Arel::Nodes::BindParam === thing + Substitute === thing }.map(&:last) end @@ -56,6 +56,28 @@ module ActiveRecord end end + class PartialQueryCollector + def initialize + @parts = [] + @binds = [] + end + + def <<(str) + @parts << str + self + end + + def add_bind(obj) + @binds << obj + @parts << Substitute.new + self + end + + def value + [@parts, @binds] + end + end + def self.query(sql) Query.new(sql) end @@ -64,6 +86,10 @@ module ActiveRecord PartialQuery.new(values) end + def self.partial_query_collector + PartialQueryCollector.new + end + class Params # :nodoc: def bind; Substitute.new; end end diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index d3c85b161e..8acb11f75f 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -6,8 +6,8 @@ module ActiveRecord module Tasks # :nodoc: class PostgreSQLDatabaseTasks # :nodoc: DEFAULT_ENCODING = ENV["CHARSET"] || "utf8" - ON_ERROR_STOP_1 = "ON_ERROR_STOP=1".freeze - SQL_COMMENT_BEGIN = "--".freeze + ON_ERROR_STOP_1 = "ON_ERROR_STOP=1" + SQL_COMMENT_BEGIN = "--" delegate :connection, :establish_connection, :clear_active_connections!, to: ActiveRecord::Base diff --git a/activerecord/lib/arel/collectors/composite.rb b/activerecord/lib/arel/collectors/composite.rb index d040d8598d..0533544993 100644 --- a/activerecord/lib/arel/collectors/composite.rb +++ b/activerecord/lib/arel/collectors/composite.rb @@ -24,8 +24,7 @@ module Arel # :nodoc: all [left.value, right.value] end - protected - + private attr_reader :left, :right end end diff --git a/activerecord/lib/arel/collectors/sql_string.rb b/activerecord/lib/arel/collectors/sql_string.rb index c293a89a74..54e1e562c2 100644 --- a/activerecord/lib/arel/collectors/sql_string.rb +++ b/activerecord/lib/arel/collectors/sql_string.rb @@ -15,10 +15,6 @@ module Arel # :nodoc: all @bind_index += 1 self end - - def compile(bvs) - value - end end end end diff --git a/activerecord/lib/arel/collectors/substitute_binds.rb b/activerecord/lib/arel/collectors/substitute_binds.rb index 3f40eec8a8..4b894bc4b1 100644 --- a/activerecord/lib/arel/collectors/substitute_binds.rb +++ b/activerecord/lib/arel/collectors/substitute_binds.rb @@ -21,8 +21,7 @@ module Arel # :nodoc: all delegate.value end - protected - + private attr_reader :quoter, :delegate end end diff --git a/activerecord/lib/arel/delete_manager.rb b/activerecord/lib/arel/delete_manager.rb index 2def581009..fdba937d64 100644 --- a/activerecord/lib/arel/delete_manager.rb +++ b/activerecord/lib/arel/delete_manager.rb @@ -2,6 +2,8 @@ module Arel # :nodoc: all class DeleteManager < Arel::TreeManager + include TreeManager::StatementMethods + def initialize super @ast = Nodes::DeleteStatement.new @@ -12,14 +14,5 @@ module Arel # :nodoc: all @ast.relation = relation self end - - def take(limit) - @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit - self - end - - def wheres=(list) - @ast.wheres = list - end end end diff --git a/activerecord/lib/arel/nodes/delete_statement.rb b/activerecord/lib/arel/nodes/delete_statement.rb index eaac05e2f6..a419975335 100644 --- a/activerecord/lib/arel/nodes/delete_statement.rb +++ b/activerecord/lib/arel/nodes/delete_statement.rb @@ -3,8 +3,7 @@ module Arel # :nodoc: all module Nodes class DeleteStatement < Arel::Nodes::Node - attr_accessor :left, :right - attr_accessor :limit + attr_accessor :left, :right, :orders, :limit, :offset, :key alias :relation :left alias :relation= :left= @@ -15,6 +14,10 @@ module Arel # :nodoc: all super() @left = relation @right = wheres + @orders = [] + @limit = nil + @offset = nil + @key = nil end def initialize_copy(other) @@ -24,13 +27,17 @@ module Arel # :nodoc: all end def hash - [self.class, @left, @right].hash + [self.class, @left, @right, @orders, @limit, @offset, @key].hash end def eql?(other) self.class == other.class && self.left == other.left && - self.right == other.right + self.right == other.right && + self.orders == other.orders && + self.limit == other.limit && + self.offset == other.offset && + self.key == other.key end alias :== :eql? end diff --git a/activerecord/lib/arel/nodes/update_statement.rb b/activerecord/lib/arel/nodes/update_statement.rb index 5184b1180f..cfaa19e392 100644 --- a/activerecord/lib/arel/nodes/update_statement.rb +++ b/activerecord/lib/arel/nodes/update_statement.rb @@ -3,8 +3,7 @@ module Arel # :nodoc: all module Nodes class UpdateStatement < Arel::Nodes::Node - attr_accessor :relation, :wheres, :values, :orders, :limit - attr_accessor :key + attr_accessor :relation, :wheres, :values, :orders, :limit, :offset, :key def initialize @relation = nil @@ -12,6 +11,7 @@ module Arel # :nodoc: all @values = [] @orders = [] @limit = nil + @offset = nil @key = nil end @@ -22,7 +22,7 @@ module Arel # :nodoc: all end def hash - [@relation, @wheres, @values, @orders, @limit, @key].hash + [@relation, @wheres, @values, @orders, @limit, @offset, @key].hash end def eql?(other) @@ -32,6 +32,7 @@ module Arel # :nodoc: all self.values == other.values && self.orders == other.orders && self.limit == other.limit && + self.offset == other.offset && self.key == other.key end alias :== :eql? diff --git a/activerecord/lib/arel/table.rb b/activerecord/lib/arel/table.rb index 686fcdf962..c40c68715a 100644 --- a/activerecord/lib/arel/table.rb +++ b/activerecord/lib/arel/table.rb @@ -104,8 +104,7 @@ module Arel # :nodoc: all !type_caster.nil? end - protected - + private attr_reader :type_caster end end diff --git a/activerecord/lib/arel/tree_manager.rb b/activerecord/lib/arel/tree_manager.rb index ed47b09a37..0476399618 100644 --- a/activerecord/lib/arel/tree_manager.rb +++ b/activerecord/lib/arel/tree_manager.rb @@ -4,6 +4,40 @@ module Arel # :nodoc: all class TreeManager include Arel::FactoryMethods + module StatementMethods + def take(limit) + @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit + self + end + + def offset(offset) + @ast.offset = Nodes::Offset.new(Nodes.build_quoted(offset)) if offset + self + end + + def order(*expr) + @ast.orders = expr + self + end + + def key=(key) + @ast.key = Nodes.build_quoted(key) + end + + def key + @ast.key + end + + def wheres=(exprs) + @ast.wheres = exprs + end + + def where(expr) + @ast.wheres << expr + self + end + end + attr_reader :ast def initialize diff --git a/activerecord/lib/arel/update_manager.rb b/activerecord/lib/arel/update_manager.rb index fe444343ba..a809dbb307 100644 --- a/activerecord/lib/arel/update_manager.rb +++ b/activerecord/lib/arel/update_manager.rb @@ -2,30 +2,14 @@ module Arel # :nodoc: all class UpdateManager < Arel::TreeManager + include TreeManager::StatementMethods + def initialize super @ast = Nodes::UpdateStatement.new @ctx = @ast end - def take(limit) - @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit - self - end - - def key=(key) - @ast.key = Nodes.build_quoted(key) - end - - def key - @ast.key - end - - def order(*expr) - @ast.orders = expr - self - end - ### # UPDATE +table+ def table(table) @@ -33,15 +17,6 @@ module Arel # :nodoc: all self end - def wheres=(exprs) - @ast.wheres = exprs - end - - def where(expr) - @ast.wheres << expr - self - end - def set(values) if String === values @ast.values = [values] diff --git a/activerecord/lib/arel/visitors/depth_first.rb b/activerecord/lib/arel/visitors/depth_first.rb index 5948622aea..8f65d303ac 100644 --- a/activerecord/lib/arel/visitors/depth_first.rb +++ b/activerecord/lib/arel/visitors/depth_first.rb @@ -135,12 +135,10 @@ module Arel # :nodoc: all alias :visit_Arel_Nodes_True :terminal alias :visit_Arel_Nodes_False :terminal alias :visit_BigDecimal :terminal - alias :visit_Bignum :terminal alias :visit_Class :terminal alias :visit_Date :terminal alias :visit_DateTime :terminal alias :visit_FalseClass :terminal - alias :visit_Fixnum :terminal alias :visit_Float :terminal alias :visit_Integer :terminal alias :visit_NilClass :terminal diff --git a/activerecord/lib/arel/visitors/dot.rb b/activerecord/lib/arel/visitors/dot.rb index 76830412d4..9054f0159b 100644 --- a/activerecord/lib/arel/visitors/dot.rb +++ b/activerecord/lib/arel/visitors/dot.rb @@ -211,7 +211,6 @@ module Arel # :nodoc: all alias :visit_TrueClass :visit_String alias :visit_FalseClass :visit_String alias :visit_Integer :visit_String - alias :visit_Fixnum :visit_String alias :visit_BigDecimal :visit_String alias :visit_Float :visit_String alias :visit_Symbol :visit_String diff --git a/activerecord/lib/arel/visitors/mysql.rb b/activerecord/lib/arel/visitors/mysql.rb index ee75b6bb25..eb8a449079 100644 --- a/activerecord/lib/arel/visitors/mysql.rb +++ b/activerecord/lib/arel/visitors/mysql.rb @@ -56,14 +56,31 @@ module Arel # :nodoc: all super end - def visit_Arel_Nodes_UpdateStatement(o, collector) - collector << "UPDATE " - collector = visit o.relation, collector + def visit_Arel_Nodes_Concat(o, collector) + collector << " CONCAT(" + visit o.left, collector + collector << ", " + visit o.right, collector + collector << ") " + collector + end + + def build_subselect(key, o) + subselect = super - unless o.values.empty? - collector << " SET " - collector = inject_join o.values, collector, ", " + # Materialize subquery by adding distinct + # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on' + subselect.distinct unless subselect.limit || subselect.offset || subselect.orders.any? + + Nodes::SelectStatement.new.tap do |stmt| + core = stmt.cores.last + core.froms = Nodes::Grouping.new(subselect).as("__active_record_temp") + core.projections = [Arel.sql(quote_column_name(key.name))] end + end + + def collect_where_for(o, collector) + return super if o.offset unless o.wheres.empty? collector << " WHERE " @@ -77,15 +94,6 @@ module Arel # :nodoc: all maybe_visit o.limit, collector end - - def visit_Arel_Nodes_Concat(o, collector) - collector << " CONCAT(" - visit o.left, collector - collector << ", " - visit o.right, collector - collector << ") " - collector - end end end end diff --git a/activerecord/lib/arel/visitors/to_sql.rb b/activerecord/lib/arel/visitors/to_sql.rb index 1ed41ff577..0172204fc8 100644 --- a/activerecord/lib/arel/visitors/to_sql.rb +++ b/activerecord/lib/arel/visitors/to_sql.rb @@ -67,8 +67,8 @@ module Arel # :nodoc: all @connection = connection end - def compile(node, collector = Arel::Collectors::SQLString.new, &block) - accept(node, collector, &block).value + def compile(node, collector = Arel::Collectors::SQLString.new) + accept(node, collector).value end private @@ -76,12 +76,8 @@ module Arel # :nodoc: all def visit_Arel_Nodes_DeleteStatement(o, collector) collector << "DELETE FROM " collector = visit o.relation, collector - if o.wheres.any? - collector << WHERE - collector = inject_join o.wheres, collector, AND - end - maybe_visit o.limit, collector + collect_where_for(o, collector) end # FIXME: we should probably have a 2-pass visitor for this @@ -92,17 +88,12 @@ module Arel # :nodoc: all core.wheres = o.wheres core.projections = [key] stmt.limit = o.limit + stmt.offset = o.offset stmt.orders = o.orders stmt end def visit_Arel_Nodes_UpdateStatement(o, collector) - if o.orders.empty? && o.limit.nil? - wheres = o.wheres - else - wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])] - end - collector << "UPDATE " collector = visit o.relation, collector unless o.values.empty? @@ -110,12 +101,7 @@ module Arel # :nodoc: all collector = inject_join o.values, collector, ", " end - unless wheres.empty? - collector << " WHERE " - collector = inject_join wheres, collector, " AND " - end - - collector + collect_where_for(o, collector) end def visit_Arel_Nodes_InsertStatement(o, collector) @@ -814,6 +800,21 @@ module Arel # :nodoc: all } end + def collect_where_for(o, collector) + if o.orders.empty? && o.limit.nil? && o.offset.nil? + wheres = o.wheres + else + wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])] + end + + unless wheres.empty? + collector << " WHERE " + collector = inject_join wheres, collector, " AND " + end + + collector + end + def infix_value(o, collector, value) collector = visit o.left, collector collector << value diff --git a/activerecord/lib/rails/generators/active_record/migration.rb b/activerecord/lib/rails/generators/active_record/migration.rb index 4a17082d66..cbb88d571d 100644 --- a/activerecord/lib/rails/generators/active_record/migration.rb +++ b/activerecord/lib/rails/generators/active_record/migration.rb @@ -24,14 +24,25 @@ module ActiveRecord end def db_migrate_path - if migrations_paths = options[:migrations_paths] - migrations_paths - elsif defined?(Rails.application) && Rails.application - Rails.application.config.paths["db/migrate"].to_ary.first + if defined?(Rails.application) && Rails.application + configured_migrate_path || default_migrate_path else "db/migrate" end end + + def default_migrate_path + Rails.application.config.paths["db/migrate"].to_ary.first + end + + def configured_migrate_path + return unless database = options[:database] + config = ActiveRecord::Base.configurations.configs_for( + env_name: Rails.env, + spec_name: database, + ) + config&.migrations_paths + end end end end diff --git a/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb b/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb index 281b7afb50..dd79bcf542 100644 --- a/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb +++ b/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb @@ -8,7 +8,7 @@ module ActiveRecord argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]" class_option :primary_key_type, type: :string, desc: "The type for primary key" - class_option :migrations_paths, type: :string, desc: "The migration path for your generated migrations. If this is not set it will default to db/migrate" + class_option :database, type: :string, aliases: %i(db), desc: "The database for your migration. By default, the current environment's primary database is used." def create_migration_file set_local_assigns! 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 747c8493b1..eac504f9f1 100644 --- a/activerecord/lib/rails/generators/active_record/model/model_generator.rb +++ b/activerecord/lib/rails/generators/active_record/model/model_generator.rb @@ -14,7 +14,7 @@ module ActiveRecord class_option :parent, type: :string, desc: "The parent class for the generated model" class_option :indexes, type: :boolean, default: true, desc: "Add indexes for references and belongs_to columns" class_option :primary_key_type, type: :string, desc: "The type for primary key" - class_option :migrations_paths, type: :string, desc: "The migration path for your generated migrations. If this is not set it will default to db/migrate" + class_option :database, type: :string, aliases: %i(db), desc: "The database for your model's migration. By default, the current environment's primary database is used." # creates the migration file for the model. def create_migration_file diff --git a/activerecord/test/cases/arel/collectors/sql_string_test.rb b/activerecord/test/cases/arel/collectors/sql_string_test.rb index 380573494d..443c7eb54b 100644 --- a/activerecord/test/cases/arel/collectors/sql_string_test.rb +++ b/activerecord/test/cases/arel/collectors/sql_string_test.rb @@ -19,27 +19,21 @@ module Arel collect(node).value end - def ast_with_binds(bv) + def ast_with_binds table = Table.new(:users) manager = Arel::SelectManager.new table - manager.where(table[:age].eq(bv)) - manager.where(table[:name].eq(bv)) + manager.where(table[:age].eq(Nodes::BindParam.new("hello"))) + manager.where(table[:name].eq(Nodes::BindParam.new("world"))) manager.ast end def test_compile - bv = Nodes::BindParam.new(1) - collector = collect ast_with_binds bv - - sql = collector.compile ["hello", "world"] + sql = compile(ast_with_binds) assert_equal 'SELECT FROM "users" WHERE "users"."age" = ? AND "users"."name" = ?', sql end def test_returned_sql_uses_utf8_encoding - bv = Nodes::BindParam.new(1) - collector = collect ast_with_binds bv - - sql = collector.compile ["hello", "world"] + sql = compile(ast_with_binds) assert_equal sql.encoding, Encoding::UTF_8 end end diff --git a/activerecord/test/cases/arel/delete_manager_test.rb b/activerecord/test/cases/arel/delete_manager_test.rb index 17a5271039..0bad02f4d2 100644 --- a/activerecord/test/cases/arel/delete_manager_test.rb +++ b/activerecord/test/cases/arel/delete_manager_test.rb @@ -15,6 +15,7 @@ module Arel dm = Arel::DeleteManager.new dm.take 10 dm.from table + dm.key = table[:id] assert_match(/LIMIT 10/, dm.to_sql) end diff --git a/activerecord/test/cases/arel/visitors/to_sql_test.rb b/activerecord/test/cases/arel/visitors/to_sql_test.rb index e8ac50bfa3..b6426a211e 100644 --- a/activerecord/test/cases/arel/visitors/to_sql_test.rb +++ b/activerecord/test/cases/arel/visitors/to_sql_test.rb @@ -221,7 +221,7 @@ module Arel sql.must_be_like "foo AS bar" end - it "should visit_Bignum" do + it "should visit_Integer" do compile 8787878092 end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index f6311f9256..09e5517449 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -282,11 +282,13 @@ class BasicsTest < ActiveRecord::TestCase end def test_initialize_with_invalid_attribute - Topic.new("title" => "test", - "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31") - rescue ActiveRecord::MultiparameterAssignmentErrors => ex + ex = assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do + Topic.new("title" => "test", + "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00") + end + assert_equal(1, ex.errors.size) - assert_equal("last_read", ex.errors[0].attribute) + assert_equal("written_on", ex.errors[0].attribute) end def test_create_after_initialize_without_block diff --git a/activerecord/test/cases/migration/change_table_test.rb b/activerecord/test/cases/migration/change_table_test.rb index 034bf32165..c108d372d1 100644 --- a/activerecord/test/cases/migration/change_table_test.rb +++ b/activerecord/test/cases/migration/change_table_test.rb @@ -164,6 +164,14 @@ module ActiveRecord end end + def test_column_creates_column_with_index + with_change_table do |t| + @connection.expect :add_column, nil, [:delete_me, :bar, :integer, {}] + @connection.expect :add_index, nil, [:delete_me, :bar, {}] + t.column :bar, :integer, index: true + end + end + def test_index_creates_index with_change_table do |t| @connection.expect :add_index, nil, [:delete_me, :bar, {}] diff --git a/activestorage/test/dummy/app/assets/config/manifest.js b/activestorage/test/dummy/app/assets/config/manifest.js index a8adebe722..bb109908b2 100644 --- a/activestorage/test/dummy/app/assets/config/manifest.js +++ b/activestorage/test/dummy/app/assets/config/manifest.js @@ -1,5 +1,3 @@ //= link_tree ../images -//= link_directory ../javascripts .js //= link_directory ../stylesheets .css -//= link active_storage_manifest.js diff --git a/activestorage/test/dummy/config/environments/production.rb b/activestorage/test/dummy/config/environments/production.rb index 34ac3bc561..be7f5b80d4 100644 --- a/activestorage/test/dummy/config/environments/production.rb +++ b/activestorage/test/dummy/config/environments/production.rb @@ -25,8 +25,7 @@ Rails.application.configure do # Apache or NGINX already handles this. config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? - # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier + # Compress CSS using a preprocessor. # config.assets.css_compressor = :sass # Do not fallback to assets pipeline if a precompiled asset is missed. diff --git a/activestorage/test/dummy/config/webpacker.yml b/activestorage/test/dummy/config/webpacker.yml new file mode 100644 index 0000000000..c1515a2e95 --- /dev/null +++ b/activestorage/test/dummy/config/webpacker.yml @@ -0,0 +1,72 @@ +# Note: You must restart bin/webpack-dev-server for changes to take effect + +default: &default + source_path: app/javascript + source_entry_path: packs + public_output_path: packs + cache_path: tmp/cache/webpacker + check_yarn_integrity: false + + # Additional paths webpack should lookup modules + # ['app/assets', 'engine/foo/app/assets'] + resolved_paths: [] + + # Reload manifest.json on all requests so we reload latest compiled packs + cache_manifest: false + + extensions: + - .js + - .sass + - .scss + - .css + - .module.sass + - .module.scss + - .module.css + - .png + - .svg + - .gif + - .jpeg + - .jpg + +development: + <<: *default + compile: true + + # Verifies that versions and hashed value of the package contents in the project's package.json + check_yarn_integrity: true + + # Reference: https://webpack.js.org/configuration/dev-server/ + dev_server: + https: false + host: localhost + port: 3035 + public: localhost:3035 + hmr: false + # Inline should be set to true if using HMR + inline: true + overlay: true + compress: true + disable_host_check: true + use_local_ip: false + quiet: false + headers: + 'Access-Control-Allow-Origin': '*' + watch_options: + ignored: /node_modules/ + + +test: + <<: *default + compile: true + + # Compile test packs to a separate directory + public_output_path: packs-test + +production: + <<: *default + + # Production depends on precompilation of packs prior to booting for performance. + compile: false + + # Cache manifest.json for performance + cache_manifest: true diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb index 1796956bd7..62973eca58 100644 --- a/activesupport/lib/active_support/backtrace_cleaner.rb +++ b/activesupport/lib/active_support/backtrace_cleaner.rb @@ -93,7 +93,7 @@ module ActiveSupport return if gems_paths.empty? gems_regexp = %r{(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)} - gems_result = '\3 (\4) \5'.freeze + gems_result = '\3 (\4) \5' add_filter { |line| line.sub(gems_regexp, gems_result) } end diff --git a/activesupport/lib/active_support/core_ext/load_error.rb b/activesupport/lib/active_support/core_ext/load_error.rb index 6b0dcab905..b81ed0605e 100644 --- a/activesupport/lib/active_support/core_ext/load_error.rb +++ b/activesupport/lib/active_support/core_ext/load_error.rb @@ -4,6 +4,6 @@ class LoadError # Returns true if the given path name (except perhaps for the ".rb" # extension) is the missing file which caused the exception to be raised. def is_missing?(location) - location.sub(/\.rb$/, "".freeze) == path.to_s.sub(/\.rb$/, "".freeze) + location.sub(/\.rb$/, "") == path.to_s.sub(/\.rb$/, "") end end diff --git a/activesupport/lib/active_support/core_ext/string/strip.rb b/activesupport/lib/active_support/core_ext/string/strip.rb index 6f9834bb16..60e9952ee6 100644 --- a/activesupport/lib/active_support/core_ext/string/strip.rb +++ b/activesupport/lib/active_support/core_ext/string/strip.rb @@ -20,7 +20,7 @@ class String # Technically, it looks for the least indented non-empty line # in the whole string, and removes that amount of leading whitespace. def strip_heredoc - gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "".freeze).tap do |stripped| + gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped| stripped.freeze if frozen? end end diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 238a9f0ee6..063d8d1587 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -144,7 +144,7 @@ module ActiveSupport #:nodoc: # Normalize the list of new constants, and add them to the list we will return new_constants.each do |suffix| - constants << ([namespace, suffix] - ["Object"]).join("::".freeze) + constants << ([namespace, suffix] - ["Object"]).join("::") end end constants @@ -410,7 +410,7 @@ module ActiveSupport #:nodoc: next unless expanded_path.start_with?(expanded_root) root_size = expanded_root.size - next if expanded_path[root_size] != ?/.freeze + next if expanded_path[root_size] != ?/ nesting = expanded_path[(root_size + 1)..-1] paths << nesting.camelize unless nesting.blank? @@ -505,7 +505,7 @@ module ActiveSupport #:nodoc: if file_path expanded = File.expand_path(file_path) - expanded.sub!(/\.rb\z/, "".freeze) + expanded.sub!(/\.rb\z/, "") if loading.include?(expanded) raise "Circular dependency detected while autoloading constant #{qualified_name}" diff --git a/activesupport/lib/active_support/duration/iso8601_parser.rb b/activesupport/lib/active_support/duration/iso8601_parser.rb index 414f727705..d3233e6111 100644 --- a/activesupport/lib/active_support/duration/iso8601_parser.rb +++ b/activesupport/lib/active_support/duration/iso8601_parser.rb @@ -13,8 +13,8 @@ module ActiveSupport class ParsingError < ::ArgumentError; end PERIOD_OR_COMMA = /\.|,/ - PERIOD = ".".freeze - COMMA = ",".freeze + PERIOD = "." + COMMA = "," SIGN_MARKER = /\A\-|\+|/ DATE_MARKER = /P/ diff --git a/activesupport/lib/active_support/duration/iso8601_serializer.rb b/activesupport/lib/active_support/duration/iso8601_serializer.rb index 0fb0e3f3a5..1125454919 100644 --- a/activesupport/lib/active_support/duration/iso8601_serializer.rb +++ b/activesupport/lib/active_support/duration/iso8601_serializer.rb @@ -14,7 +14,7 @@ module ActiveSupport # Builds and returns output string. def serialize parts, sign = normalize - return "PT0S".freeze if parts.empty? + return "PT0S" if parts.empty? output = +"P" output << "#{parts[:years]}Y" if parts.key?(:years) diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index b9e64ed05d..2fac579469 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -2,6 +2,7 @@ require "active_support/core_ext/hash/keys" require "active_support/core_ext/hash/reverse_merge" +require "active_support/core_ext/hash/except" module ActiveSupport # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 7359de762a..1af9833d46 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -73,7 +73,7 @@ module ActiveSupport string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase } end string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" } - string.gsub!("/".freeze, "::".freeze) + string.gsub!("/", "::") string end @@ -90,11 +90,11 @@ module ActiveSupport # camelize(underscore('SSLError')) # => "SslError" def underscore(camel_cased_word) return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word) - word = camel_cased_word.to_s.gsub("::".freeze, "/".freeze) - word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_'.freeze }#{$2.downcase}" } - word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze) - word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'.freeze) - word.tr!("-".freeze, "_".freeze) + word = camel_cased_word.to_s.gsub("::", "/") + word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" } + word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2') + word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') + word.tr!("-", "_") word.downcase! word end @@ -130,11 +130,11 @@ module ActiveSupport inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) } - result.sub!(/\A_+/, "".freeze) + result.sub!(/\A_+/, "") unless keep_id_suffix - result.sub!(/_id\z/, "".freeze) + result.sub!(/_id\z/, "") end - result.tr!("_".freeze, " ".freeze) + result.tr!("_", " ") result.gsub!(/([a-z\d]*)/i) do |match| "#{inflections.acronyms[match.downcase] || match.downcase}" @@ -199,14 +199,14 @@ module ActiveSupport # classify('calculus') # => "Calculus" def classify(table_name) # strip out any leading schema name - camelize(singularize(table_name.to_s.sub(/.*\./, "".freeze))) + camelize(singularize(table_name.to_s.sub(/.*\./, ""))) end # Replaces underscores with dashes in the string. # # dasherize('puni_puni') # => "puni-puni" def dasherize(underscored_word) - underscored_word.tr("_".freeze, "-".freeze) + underscored_word.tr("_", "-") end # Removes the module part from the expression in the string. @@ -269,7 +269,7 @@ module ActiveSupport # NameError is raised when the name is not in CamelCase or the constant is # unknown. def constantize(camel_cased_word) - names = camel_cased_word.split("::".freeze) + names = camel_cased_word.split("::") # Trigger a built-in NameError exception including the ill-formed constant in the message. Object.const_get(camel_cased_word) if names.empty? @@ -364,7 +364,7 @@ module ActiveSupport # const_regexp("Foo::Bar::Baz") # => "Foo(::Bar(::Baz)?)?" # const_regexp("::") # => "::" def const_regexp(camel_cased_word) - parts = camel_cased_word.split("::".freeze) + parts = camel_cased_word.split("::") return Regexp.escape(camel_cased_word) if parts.blank? diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb index 6f2ca4999c..dbc8b8a2fa 100644 --- a/activesupport/lib/active_support/inflector/transliterate.rb +++ b/activesupport/lib/active_support/inflector/transliterate.rb @@ -58,7 +58,7 @@ module ActiveSupport # I18n.locale = :de # transliterate('Jürgen') # # => "Juergen" - def transliterate(string, replacement = "?".freeze) + def transliterate(string, replacement = "?") raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String) I18n.transliterate( @@ -97,7 +97,7 @@ module ActiveSupport parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator) unless separator.nil? || separator.empty? - if separator == "-".freeze + if separator == "-" re_duplicate_separator = /-{2,}/ re_leading_trailing_separator = /^-|-$/i else @@ -108,7 +108,7 @@ module ActiveSupport # No more than one of the separator in a row. parameterized_string.gsub!(re_duplicate_separator, separator) # Remove leading/trailing separator. - parameterized_string.gsub!(re_leading_trailing_separator, "".freeze) + parameterized_string.gsub!(re_leading_trailing_separator, "") end parameterized_string.downcase! unless preserve_case diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 404404cad1..6f7302e732 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -182,7 +182,7 @@ module ActiveSupport def _decrypt(encrypted_message, purpose) cipher = new_cipher - encrypted_data, iv, auth_tag = encrypted_message.split("--".freeze).map { |v| ::Base64.strict_decode64(v) } + encrypted_data, iv, auth_tag = encrypted_message.split("--").map { |v| ::Base64.strict_decode64(v) } # Currently the OpenSSL bindings do not raise an error if auth_tag is # truncated, which would allow an attacker to easily forge it. See diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 83c39c0a86..64c557bec6 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -122,7 +122,7 @@ module ActiveSupport def valid_message?(signed_message) return if signed_message.nil? || !signed_message.valid_encoding? || signed_message.blank? - data, digest = signed_message.split("--".freeze) + data, digest = signed_message.split("--") data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data)) end @@ -150,7 +150,7 @@ module ActiveSupport def verified(signed_message, purpose: nil, **) if valid_message?(signed_message) begin - data = signed_message.split("--".freeze)[0] + data = signed_message.split("--")[0] message = Messages::Metadata.verify(decode(data), purpose) @serializer.load(message) if message rescue ArgumentError => argument_error 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 a25e22cbd3..aef5b62aed 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 @@ -15,7 +15,7 @@ module ActiveSupport end rounded_number = NumberToRoundedConverter.convert(number, options) - format.gsub("%n".freeze, rounded_number).gsub("%u".freeze, options[:unit]) + format.gsub("%n", rounded_number).gsub("%u", options[:unit]) end private 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 d5b5706705..05427fef53 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,7 @@ module ActiveSupport private def parts - left, right = number.to_s.split(".".freeze) + left, right = number.to_s.split(".") left.gsub!(delimiter_pattern) do |digit_to_delimit| "#{digit_to_delimit}#{options[:delimiter]}" end 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 03eb6671ec..908f788ee3 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 @@ -25,7 +25,7 @@ module ActiveSupport rounded_number = NumberToRoundedConverter.convert(number, options) unit = determine_unit(units, exponent) - format.gsub("%n".freeze, rounded_number).gsub("%u".freeze, unit).strip + format.gsub("%n", rounded_number).gsub("%u", unit).strip end private 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 842f2fc8df..0c72096b72 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 @@ -22,7 +22,7 @@ module ActiveSupport human_size = number / (base**exponent) number_to_format = NumberToRoundedConverter.convert(human_size, options) end - conversion_format.gsub("%n".freeze, number_to_format).gsub("%u".freeze, unit) + conversion_format.gsub("%n", number_to_format).gsub("%u", unit) end private diff --git a/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb b/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb index 4dcdad2e2c..6618ecffd5 100644 --- a/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb @@ -7,7 +7,7 @@ module ActiveSupport def convert rounded_number = NumberToRoundedConverter.convert(number, options) - options[:format].gsub("%n".freeze, rounded_number) + options[:format].gsub("%n", rounded_number) end end end 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 eb528a0583..0ee5ef92dd 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 @@ -20,9 +20,9 @@ module ActiveSupport formatted_string = if BigDecimal === rounded_number && rounded_number.finite? s = rounded_number.to_s("F") - s << "0".freeze * precision - a, b = s.split(".".freeze, 2) - a << ".".freeze + s << "0" * precision + a, b = s.split(".", 2) + a << "." a << b[0, precision] else "%00.#{precision}f" % rounded_number diff --git a/activesupport/lib/active_support/subscriber.rb b/activesupport/lib/active_support/subscriber.rb index 5a4c3d74af..9562149f8d 100644 --- a/activesupport/lib/active_support/subscriber.rb +++ b/activesupport/lib/active_support/subscriber.rb @@ -92,7 +92,7 @@ module ActiveSupport event.finish! event.payload.merge!(payload) - method = name.split(".".freeze).first + method = name.split(".").first send(method, event) end diff --git a/activesupport/lib/active_support/tagged_logging.rb b/activesupport/lib/active_support/tagged_logging.rb index dd72da500c..d8a86d997e 100644 --- a/activesupport/lib/active_support/tagged_logging.rb +++ b/activesupport/lib/active_support/tagged_logging.rb @@ -46,7 +46,7 @@ module ActiveSupport def current_tags # We use our object ID here to avoid conflicting with other instances - thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}".freeze + thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}" Thread.current[thread_key] ||= [] end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index fb6956f64f..3be5f6f7b5 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -43,8 +43,8 @@ module ActiveSupport "Time" end - PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N".freeze } - PRECISIONS[0] = "%FT%T".freeze + PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N" } + PRECISIONS[0] = "%FT%T" include Comparable, DateAndTime::Compatibility attr_reader :time_zone @@ -147,7 +147,7 @@ module ActiveSupport # # Time.zone.now.xmlschema # => "2014-12-04T11:02:37-05:00" def xmlschema(fraction_digits = 0) - "#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z'.freeze)}" + "#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z')}" end alias_method :iso8601, :xmlschema alias_method :rfc3339, :xmlschema diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb index 59c65db2d5..32fe6ade28 100644 --- a/activesupport/lib/active_support/xml_mini/jdom.rb +++ b/activesupport/lib/active_support/xml_mini/jdom.rb @@ -18,7 +18,7 @@ module ActiveSupport module XmlMini_JDOM #:nodoc: extend self - CONTENT_KEY = "__content__".freeze + CONTENT_KEY = "__content__" NODE_TYPE_NAMES = %w{ATTRIBUTE_NODE CDATA_SECTION_NODE COMMENT_NODE DOCUMENT_FRAGMENT_NODE DOCUMENT_NODE DOCUMENT_TYPE_NODE ELEMENT_NODE ENTITY_NODE ENTITY_REFERENCE_NODE NOTATION_NODE diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb index 2a16932f03..c2e999ef6c 100644 --- a/activesupport/lib/active_support/xml_mini/libxml.rb +++ b/activesupport/lib/active_support/xml_mini/libxml.rb @@ -34,7 +34,7 @@ module LibXML #:nodoc: end module Node #:nodoc: - CONTENT_ROOT = "__content__".freeze + CONTENT_ROOT = "__content__" # Convert XML document to hash. # diff --git a/activesupport/lib/active_support/xml_mini/libxmlsax.rb b/activesupport/lib/active_support/xml_mini/libxmlsax.rb index a22a2c9cb7..ac8acdfc3c 100644 --- a/activesupport/lib/active_support/xml_mini/libxmlsax.rb +++ b/activesupport/lib/active_support/xml_mini/libxmlsax.rb @@ -13,8 +13,8 @@ module ActiveSupport class HashBuilder include LibXML::XML::SaxParser::Callbacks - CONTENT_KEY = "__content__".freeze - HASH_SIZE_KEY = "__hash_size__".freeze + CONTENT_KEY = "__content__" + HASH_SIZE_KEY = "__hash_size__" attr_reader :hash diff --git a/activesupport/lib/active_support/xml_mini/nokogiri.rb b/activesupport/lib/active_support/xml_mini/nokogiri.rb index 4762a759d6..f76513f48b 100644 --- a/activesupport/lib/active_support/xml_mini/nokogiri.rb +++ b/activesupport/lib/active_support/xml_mini/nokogiri.rb @@ -38,7 +38,7 @@ module ActiveSupport end module Node #:nodoc: - CONTENT_ROOT = "__content__".freeze + CONTENT_ROOT = "__content__" # Convert XML document to hash. # diff --git a/activesupport/lib/active_support/xml_mini/nokogirisax.rb b/activesupport/lib/active_support/xml_mini/nokogirisax.rb index 0bbb4e258a..55cd72e093 100644 --- a/activesupport/lib/active_support/xml_mini/nokogirisax.rb +++ b/activesupport/lib/active_support/xml_mini/nokogirisax.rb @@ -16,8 +16,8 @@ module ActiveSupport # Class that will build the hash while the XML document # is being parsed using SAX events. class HashBuilder < Nokogiri::XML::SAX::Document - CONTENT_KEY = "__content__".freeze - HASH_SIZE_KEY = "__hash_size__".freeze + CONTENT_KEY = "__content__" + HASH_SIZE_KEY = "__hash_size__" attr_reader :hash diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb index 55a155d4ee..8d6e3af066 100644 --- a/activesupport/lib/active_support/xml_mini/rexml.rb +++ b/activesupport/lib/active_support/xml_mini/rexml.rb @@ -8,7 +8,7 @@ module ActiveSupport module XmlMini_REXML #:nodoc: extend self - CONTENT_KEY = "__content__".freeze + CONTENT_KEY = "__content__" # Parse an XML Document string or IO into a simple hash. # diff --git a/activesupport/test/core_ext/date_and_time_compatibility_test.rb b/activesupport/test/core_ext/date_and_time_compatibility_test.rb index 266829a452..58a24b60b6 100644 --- a/activesupport/test/core_ext/date_and_time_compatibility_test.rb +++ b/activesupport/test/core_ext/date_and_time_compatibility_test.rb @@ -248,7 +248,7 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase def test_string_to_time_frozen_preserves_timezone with_preserve_timezone(true) do with_env_tz "US/Eastern" do - source = "2016-04-23T15:11:12+01:00".freeze + source = "2016-04-23T15:11:12+01:00" time = source.to_time assert_instance_of Time, time @@ -262,7 +262,7 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase def test_string_to_time_frozen_does_not_preserve_time_zone with_preserve_timezone(false) do with_env_tz "US/Eastern" do - source = "2016-04-23T15:11:12+01:00".freeze + source = "2016-04-23T15:11:12+01:00" time = source.to_time assert_instance_of Time, time diff --git a/activesupport/test/core_ext/object/instance_variables_test.rb b/activesupport/test/core_ext/object/instance_variables_test.rb index cf1fe5dfa4..9052d209a3 100644 --- a/activesupport/test/core_ext/object/instance_variables_test.rb +++ b/activesupport/test/core_ext/object/instance_variables_test.rb @@ -23,7 +23,7 @@ class ObjectInstanceVariableTest < ActiveSupport::TestCase end def test_instance_exec_with_frozen_obj - assert_equal %w(olleh goodbye), "hello".freeze.instance_exec("goodbye") { |v| [reverse, v] } + assert_equal %w(olleh goodbye), "hello".instance_exec("goodbye") { |v| [reverse, v] } end def test_instance_exec_nested diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 1febb6a775..2468fe3603 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -25,7 +25,7 @@ class StringInflectionsTest < ActiveSupport::TestCase end def test_strip_heredoc_on_a_frozen_string - assert "".freeze.strip_heredoc.frozen? + assert "".strip_heredoc.frozen? end def test_strip_heredoc_on_a_string_with_no_lines diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index e1cb22fda8..7078f3506d 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -950,39 +950,39 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end class TimeExtMarshalingTest < ActiveSupport::TestCase - def test_marshaling_with_utc_instance + def test_marshalling_with_utc_instance t = Time.utc(2000) - unmarshaled = Marshal.load(Marshal.dump(t)) - assert_equal "UTC", unmarshaled.zone - assert_equal t, unmarshaled + unmarshalled = Marshal.load(Marshal.dump(t)) + assert_equal "UTC", unmarshalled.zone + assert_equal t, unmarshalled end - def test_marshaling_with_local_instance + def test_marshalling_with_local_instance t = Time.local(2000) - unmarshaled = Marshal.load(Marshal.dump(t)) - assert_equal t.zone, unmarshaled.zone - assert_equal t, unmarshaled + unmarshalled = Marshal.load(Marshal.dump(t)) + assert_equal t.zone, unmarshalled.zone + assert_equal t, unmarshalled end - def test_marshaling_with_frozen_utc_instance + def test_marshalling_with_frozen_utc_instance t = Time.utc(2000).freeze - unmarshaled = Marshal.load(Marshal.dump(t)) - assert_equal "UTC", unmarshaled.zone - assert_equal t, unmarshaled + unmarshalled = Marshal.load(Marshal.dump(t)) + assert_equal "UTC", unmarshalled.zone + assert_equal t, unmarshalled end - def test_marshaling_with_frozen_local_instance + def test_marshalling_with_frozen_local_instance t = Time.local(2000).freeze - unmarshaled = Marshal.load(Marshal.dump(t)) - assert_equal t.zone, unmarshaled.zone - assert_equal t, unmarshaled + unmarshalled = Marshal.load(Marshal.dump(t)) + assert_equal t.zone, unmarshalled.zone + assert_equal t, unmarshalled end def test_marshalling_preserves_fractional_seconds t = Time.parse("00:00:00.500") - unmarshaled = Marshal.load(Marshal.dump(t)) - assert_equal t.to_f, unmarshaled.to_f - assert_equal t, unmarshaled + unmarshalled = Marshal.load(Marshal.dump(t)) + assert_equal t.to_f, unmarshalled.to_f + assert_equal t, unmarshalled end def test_last_quarter_on_31st diff --git a/activesupport/test/multibyte_test_helpers.rb b/activesupport/test/multibyte_test_helpers.rb index d97ce6727a..7565655f25 100644 --- a/activesupport/test/multibyte_test_helpers.rb +++ b/activesupport/test/multibyte_test_helpers.rb @@ -27,8 +27,8 @@ module MultibyteTestHelpers CACHE_DIR = "#{Dir.tmpdir}/cache/unicode_conformance/#{ActiveSupport::Multibyte::Unicode::UNICODE_VERSION}" FileUtils.mkdir_p(CACHE_DIR) - UNICODE_STRING = "こにちわ".freeze - ASCII_STRING = "ohayo".freeze + UNICODE_STRING = "こにちわ" + ASCII_STRING = "ohayo" BYTE_STRING = (+"\270\236\010\210\245").force_encoding("ASCII-8BIT").freeze def chars(str) diff --git a/activesupport/test/xml_mini/rexml_engine_test.rb b/activesupport/test/xml_mini/rexml_engine_test.rb index 34bf81fa75..b711619ba7 100644 --- a/activesupport/test/xml_mini/rexml_engine_test.rb +++ b/activesupport/test/xml_mini/rexml_engine_test.rb @@ -12,7 +12,7 @@ class REXMLEngineTest < XMLMiniEngineTest end def test_parse_from_frozen_string - xml_string = "<root></root>".freeze + xml_string = "<root></root>" assert_equal({ "root" => {} }, ActiveSupport::XmlMini.parse(xml_string)) end diff --git a/activesupport/test/xml_mini/xml_mini_engine_test.rb b/activesupport/test/xml_mini/xml_mini_engine_test.rb index 5c4c28d9b7..c62e7e32c9 100644 --- a/activesupport/test/xml_mini/xml_mini_engine_test.rb +++ b/activesupport/test/xml_mini/xml_mini_engine_test.rb @@ -78,7 +78,7 @@ class XMLMiniEngineTest < ActiveSupport::TestCase end def test_parse_from_frozen_string - xml_string = "<root/>".freeze + xml_string = "<root/>" assert_equal({ "root" => {} }, ActiveSupport::XmlMini.parse(xml_string)) end diff --git a/guides/source/3_0_release_notes.md b/guides/source/3_0_release_notes.md index e793146c2c..e936644daf 100644 --- a/guides/source/3_0_release_notes.md +++ b/guides/source/3_0_release_notes.md @@ -38,7 +38,7 @@ If you're upgrading an existing application, it's a great idea to have good test Rails 3.0 requires Ruby 1.8.7 or higher. Support for all of the previous Ruby versions has been dropped officially and you should upgrade as early as possible. Rails 3.0 is also compatible with Ruby 1.9.2. -TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails 3.0. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02 though. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults on Rails 3.0, so if you want to use Rails 3 with 1.9.x jump on 1.9.2 for smooth sailing. +TIP: Note that Ruby 1.8.7 p248 and p249 have marshalling bugs that crash Rails 3.0. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02 though. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults on Rails 3.0, so if you want to use Rails 3 with 1.9.x jump on 1.9.2 for smooth sailing. ### Rails Application object diff --git a/guides/source/3_1_release_notes.md b/guides/source/3_1_release_notes.md index 8c3dc3454d..d6981656ee 100644 --- a/guides/source/3_1_release_notes.md +++ b/guides/source/3_1_release_notes.md @@ -26,7 +26,7 @@ If you're upgrading an existing application, it's a great idea to have good test Rails 3.1 requires Ruby 1.8.7 or higher. Support for all of the previous Ruby versions has been dropped officially and you should upgrade as early as possible. Rails 3.1 is also compatible with Ruby 1.9.2. -TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02 though. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults, so if you want to use 1.9.x jump on 1.9.2 for smooth sailing. +TIP: Note that Ruby 1.8.7 p248 and p249 have marshalling bugs that crash Rails. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02 though. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults, so if you want to use 1.9.x jump on 1.9.2 for smooth sailing. ### What to update in your apps diff --git a/guides/source/4_2_release_notes.md b/guides/source/4_2_release_notes.md index f7c40d19e9..51d06bd07d 100644 --- a/guides/source/4_2_release_notes.md +++ b/guides/source/4_2_release_notes.md @@ -44,7 +44,7 @@ to their respective adapters. Active Job comes pre-configured with an inline runner that executes jobs right away. Jobs often need to take Active Record objects as arguments. Active Job passes -object references as URIs (uniform resource identifiers) instead of marshaling +object references as URIs (uniform resource identifiers) instead of marshalling the object itself. The new [Global ID](https://github.com/rails/globalid) library builds URIs and looks up the objects they reference. Passing Active Record objects as job arguments just works by using Global ID internally. diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md index 8aaa71c557..321eee637f 100644 --- a/guides/source/caching_with_rails.md +++ b/guides/source/caching_with_rails.md @@ -362,7 +362,7 @@ This class provides the foundation for interacting with the cache in Rails. This The main methods to call are `read`, `write`, `delete`, `exist?`, and `fetch`. The fetch method takes a block and will either return an existing value from the cache, or evaluate the block and write the result to the cache if no value exists. -There are some common options used by all cache implementations. These can be passed to the constructor or the various methods to interact with entries. +There are some common options that can be used by all cache implementations. These can be passed to the constructor or the various methods to interact with entries. * `:namespace` - This option can be used to create a namespace within the cache store. It is especially useful if your application shares a cache with other applications. @@ -370,7 +370,7 @@ There are some common options used by all cache implementations. These can be pa * `:compress_threshold` - Defaults to 1kB. Cache entries larger than this threshold, specified in bytes, are compressed. -* `:expires_in` - This option sets an expiration time in seconds for the cache entry when it will be automatically removed from the cache. +* `:expires_in` - This option sets an expiration time in seconds for the cache entry, if the cache store supports it, when it will be automatically removed from the cache. * `:race_condition_ttl` - This option is used in conjunction with the `:expires_in` option. It will prevent race conditions when cache entries expire by preventing multiple processes from simultaneously regenerating the same entry (also known as the dog pile effect). This option sets the number of seconds that an expired entry can be reused while a new value is being regenerated. It's a good practice to set this value if you use the `:expires_in` option. diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index befd4e08c0..a0553c1ccc 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -41,7 +41,7 @@ Rails generally stays close to the latest released Ruby version when it's releas * Rails 3.2.x is the last branch to support Ruby 1.8.7. * Rails 3 and above require Ruby 1.8.7 or higher. Support for all of the previous Ruby versions has been dropped officially. You should upgrade as early as possible. -TIP: Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails. Ruby Enterprise Edition has these fixed since the release of 1.8.7-2010.02. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults, so if you want to use 1.9.x, jump straight to 1.9.3 for smooth sailing. +TIP: Ruby 1.8.7 p248 and p249 have marshalling bugs that crash Rails. Ruby Enterprise Edition has these fixed since the release of 1.8.7-2010.02. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults, so if you want to use 1.9.x, jump straight to 1.9.3 for smooth sailing. ### The Update Task diff --git a/package.json b/package.json new file mode 100644 index 0000000000..88029de141 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "private": true, + "workspaces": [ + "actioncable", + "activestorage", + "actionview", + "tmp/templates/app_template", + "railties/test/fixtures/tmp/bukkits/**/test/dummy", + "railties/test/fixtures/tmp/bukkits/**/spec/dummy" + ], + "dependencies": { + "webpack": "^4.17.1" + } +} diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index a839f80eb3..925dac7b3c 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,26 @@ +* Use Webpacker by default to manage app-level JavaScript through the new app/javascript directory. + Sprockets is now solely in charge, by default, of compiling CSS and other static assets. + Action Cable channel generators will create ES6 stubs rather than use CoffeeScript. + Active Storage, Action Cable, Turbolinks, and Rails-UJS are loaded by a new application.js pack. + Generators no longer generate JavaScript stubs. + + *DHH*, *Lachlan Sylvester* + +* Refactors `migrations_paths` command option in generators + to `database` (aliased as `db`). Now, the migrations paths + will be read from the specified database configuration in the + current environment. + + ``` + bin/rails g model Chair brand:string --database=kingston + invoke active_record + create db/kingston_migrate/20180830151055_create_chairs.rb + ``` + + `--database` can be used with the migration, model, and scaffold generators. + + *Gannon McGibbon* + * Adds an option to the model generator to allow setting the migrations paths for that migration. This is useful for applications that use multiple databases and put migrations diff --git a/railties/Rakefile b/railties/Rakefile index e1be0ceb40..445f6217b3 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -28,6 +28,9 @@ namespace :test do require "bundler/setup" unless defined?(Bundler) require "active_support" + # Only generate the template app once. + require_relative "test/isolation/abstract_unit" + failing_files = [] dirs = (ENV["TEST_DIR"] || ENV["TEST_DIRS"] || "**").split(",") diff --git a/railties/lib/rails/backtrace_cleaner.rb b/railties/lib/rails/backtrace_cleaner.rb index b1e3c923b7..7c2eb1dc42 100644 --- a/railties/lib/rails/backtrace_cleaner.rb +++ b/railties/lib/rails/backtrace_cleaner.rb @@ -6,13 +6,13 @@ module Rails class BacktraceCleaner < ActiveSupport::BacktraceCleaner APP_DIRS_PATTERN = /^\/?(app|config|lib|test|\(\w*\))/ RENDER_TEMPLATE_PATTERN = /:in `.*_\w+_{2,3}\d+_\d+'/ - EMPTY_STRING = "".freeze - SLASH = "/".freeze - DOT_SLASH = "./".freeze + EMPTY_STRING = "" + SLASH = "/" + DOT_SLASH = "./" def initialize super - @root = "#{Rails.root}/".freeze + @root = "#{Rails.root}/" add_filter { |line| line.sub(@root, EMPTY_STRING) } add_filter { |line| line.sub(RENDER_TEMPLATE_PATTERN, EMPTY_STRING) } add_filter { |line| line.sub(DOT_SLASH, SLASH) } # for tests diff --git a/railties/lib/rails/commands/server/server_command.rb b/railties/lib/rails/commands/server/server_command.rb index 9d517f3239..70789e0303 100644 --- a/railties/lib/rails/commands/server/server_command.rb +++ b/railties/lib/rails/commands/server/server_command.rb @@ -109,7 +109,7 @@ module Rails RACK_SERVERS = %w(cgi fastcgi webrick lsws scgi thin puma unicorn) DEFAULT_PORT = 3000 - DEFAULT_PID_PATH = "tmp/pids/server.pid".freeze + DEFAULT_PID_PATH = "tmp/pids/server.pid" argument :using, optional: true diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index ed672ae48e..cd8f16e247 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -33,8 +33,6 @@ module Rails rails: { actions: "-a", orm: "-o", - javascripts: "-j", - javascript_engine: "-je", resource_controller: "-c", scaffold_controller: "-c", stylesheets: "-y", diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 8991c547ca..410e53b4c0 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -68,10 +68,7 @@ module Rails class_option :skip_listen, type: :boolean, default: false, desc: "Don't generate configuration that depends on the listen gem" - class_option :skip_coffee, type: :boolean, default: false, - desc: "Don't use CoffeeScript" - - class_option :skip_javascript, type: :boolean, aliases: "-J", default: false, + class_option :skip_javascript, type: :boolean, aliases: "-J", default: name == "plugin", desc: "Skip JavaScript files" class_option :skip_turbolinks, type: :boolean, default: false, @@ -327,24 +324,17 @@ module Rails def assets_gemfile_entry return [] if options[:skip_sprockets] - gems = [] - gems << GemfileEntry.version("sass-rails", "~> 5.0", - "Use SCSS for stylesheets") - - if !options[:skip_javascript] - gems << GemfileEntry.version("uglifier", - ">= 1.3.0", - "Use Uglifier as compressor for JavaScript assets") - end - - gems + GemfileEntry.version("sass-rails", "~> 5.0", "Use SCSS for stylesheets") end def webpacker_gemfile_entry - return [] unless options[:webpack] + return [] if options[:skip_javascript] - comment = "Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker" - GemfileEntry.new "webpacker", nil, comment + if options.dev? || options.edge? + GemfileEntry.github "webpacker", "rails/webpacker", nil, "Use development version of Webpacker" + else + GemfileEntry.new "webpacker", nil, "Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker" + end end def jbuilder_gemfile_entry @@ -352,34 +342,12 @@ module Rails GemfileEntry.new "jbuilder", "~> 2.5", comment, {}, options[:api] end - def coffee_gemfile_entry - GemfileEntry.version "coffee-rails", "~> 4.2", "Use CoffeeScript for .coffee assets and views" - end - def javascript_gemfile_entry - if options[:skip_javascript] || options[:skip_sprockets] + if options[:skip_javascript] || options[:skip_turbolinks] [] else - gems = [javascript_runtime_gemfile_entry] - gems << coffee_gemfile_entry unless options[:skip_coffee] - - unless options[:skip_turbolinks] - gems << GemfileEntry.version("turbolinks", "~> 5", - "Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks") - end - - gems - end - end - - def javascript_runtime_gemfile_entry - comment = "See https://github.com/rails/execjs#readme for more supported runtimes" - if defined?(JRUBY_VERSION) - GemfileEntry.version "therubyrhino", nil, comment - elsif RUBY_PLATFORM.match?(/mingw|mswin/) - GemfileEntry.version "duktape", nil, comment - else - GemfileEntry.new "mini_racer", nil, comment, { platforms: :ruby }, true + [ GemfileEntry.version("turbolinks", "~> 5", + "Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks") ] end end @@ -452,9 +420,9 @@ module Rails end def run_webpack - if !(webpack = options[:webpack]).nil? + unless options[:skip_javascript] rails_command "webpacker:install" - rails_command "webpacker:install:#{webpack}" unless webpack == "webpack" + rails_command "webpacker:install:#{options[:webpack]}" if options[:webpack] && options[:webpack] != "webpack" end end diff --git a/railties/lib/rails/generators/js/assets/assets_generator.rb b/railties/lib/rails/generators/js/assets/assets_generator.rb deleted file mode 100644 index 9d32c666dc..0000000000 --- a/railties/lib/rails/generators/js/assets/assets_generator.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -require "rails/generators/named_base" - -module Js # :nodoc: - module Generators # :nodoc: - class AssetsGenerator < Rails::Generators::NamedBase # :nodoc: - source_root File.expand_path("templates", __dir__) - - def copy_javascript - copy_file "javascript.js", File.join("app/assets/javascripts", class_path, "#{file_name}.js") - end - end - end -end diff --git a/railties/lib/rails/generators/js/assets/templates/javascript.js b/railties/lib/rails/generators/js/assets/templates/javascript.js deleted file mode 100644 index dee720facd..0000000000 --- a/railties/lib/rails/generators/js/assets/templates/javascript.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index a6d160f1eb..cefaffcb20 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -80,7 +80,6 @@ module Rails directory "app" keep_file "app/assets/images" - empty_directory_with_keep_file "app/assets/javascripts/channels" unless options[:skip_action_cable] keep_file "app/controllers/concerns" keep_file "app/models/concerns" @@ -260,7 +259,7 @@ module Rails desc: "Don't run bundle install" class_option :webpack, type: :string, default: nil, - desc: "Preconfigure for app-like JavaScript with Webpack (options: #{WEBPACKS.join('/')})" + desc: "Preconfigure Webpack with a particular framework (options: #{WEBPACKS.join('/')})" def initialize(*args) super @@ -409,7 +408,7 @@ module Rails def delete_js_folder_skipping_javascript if options[:skip_javascript] - remove_dir "app/assets/javascripts" + remove_dir "app/javascript" end end @@ -436,7 +435,8 @@ module Rails def delete_action_cable_files_skipping_action_cable if options[:skip_action_cable] - remove_file "app/assets/javascripts/cable.js" + remove_file "app/javascript/channels/consumer.js" + remove_dir "app/javascript/channels" remove_dir "app/channels" end end diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt index 70b579d10e..591819335f 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt @@ -1,5 +1,2 @@ //= link_tree ../images -<% unless options.skip_javascript -%> -//= link_directory ../javascripts .js -<% end -%> //= link_directory ../stylesheets .css diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt deleted file mode 100644 index 5183bcd256..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +++ /dev/null @@ -1,22 +0,0 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's -// vendor/assets/javascripts directory can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. JavaScript code in this file should be added after the last require_* statement. -// -// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details -// about supported directives. -// -<% unless options[:skip_javascript] -%> -//= require rails-ujs -<% unless skip_active_storage? -%> -//= require activestorage -<% end -%> -<% unless options[:skip_turbolinks] -%> -//= require turbolinks -<% end -%> -<% end -%> -//= require_tree . diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.js.tt b/railties/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js index 739aa5f022..76ca3d0f2f 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.js.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js @@ -1,13 +1,6 @@ // Action Cable provides the framework to deal with WebSockets in Rails. // You can generate new channels where WebSocket features live using the `rails generate channel` command. -// -//= require action_cable -//= require_self -//= require_tree ./channels -(function() { - this.App || (this.App = {}); +import ActionCable from "actioncable" - App.cable = ActionCable.createConsumer(); - -}).call(this); +export default ActionCable.createConsumer() diff --git a/railties/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js b/railties/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js new file mode 100644 index 0000000000..5da1ce2dce --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js @@ -0,0 +1,5 @@ +// Load all the channels within this directory and all subdirectories. +// Channel files must be named *_channel.js. + +const channels = require.context('.', true, /\_channel\.js$/) +channels.keys().forEach(channels) diff --git a/railties/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt b/railties/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt new file mode 100644 index 0000000000..4d7a145cd6 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt @@ -0,0 +1,21 @@ +// This file is automatically compiled by Webpack, along with any other files +// present in this directory. You're encouraged to place your actual application logic in +// a relevant structure within app/javascript and only use these pack files to reference +// that code so it'll be compiled. + +import Rails from "rails-ujs" +Rails.start() +<%- unless options[:skip_turbolinks] -%> + +import Turbolinks from "turbolinks" +Turbolinks.start() +<%- end -%> +<%- unless skip_active_storage? -%> + +import * as ActiveStorage from "activestorage" +ActiveStorage.start() +<%- end -%> +<%- unless options[:skip_action_cable] -%> + +import "channels" +<%- end -%> diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt index ef715f1368..9a7267c783 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt @@ -9,11 +9,11 @@ <%%= stylesheet_link_tag 'application', media: 'all' %> <%- else -%> <%- unless options[:skip_turbolinks] -%> - <%%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> - <%%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + <%%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> <%- else -%> - <%%= stylesheet_link_tag 'application', media: 'all' %> - <%%= javascript_include_tag 'application' %> + <%%= stylesheet_link_tag 'application', media: 'all' %> + <%%= javascript_pack_tag 'application' %> <%- end -%> <%- end -%> </head> diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index 888336af92..08befd9196 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -23,12 +23,7 @@ Rails.application.configure do config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? <%- unless options.skip_sprockets? -%> - <%- if options.skip_javascript? -%> - # Compress CSS. - <%- else -%> - # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier - <%- end -%> + # Compress CSS using a preprocessor. # config.assets.css_compressor = :sass # Do not fallback to assets pipeline if a precompiled asset is missed. diff --git a/railties/lib/rails/generators/rails/app/templates/package.json.tt b/railties/lib/rails/generators/rails/app/templates/package.json.tt index 46db57dcbe..a654cba39c 100644 --- a/railties/lib/rails/generators/rails/app/templates/package.json.tt +++ b/railties/lib/rails/generators/rails/app/templates/package.json.tt @@ -1,5 +1,11 @@ { "name": "<%= app_name %>", "private": true, - "dependencies": {} + "dependencies": { + "rails-ujs": ">=5.2.1"<% unless options[:skip_turbolinks] %>, + "turbolinks": "5.1.1"<% end -%><% unless skip_active_storage? %>, + "activestorage": ">=5.2.1"<% end -%><% unless options[:skip_action_cable] %>, + "actioncable": ">=5.2.1"<% end -%> + }, + "version": "0.1.0" } diff --git a/railties/lib/rails/generators/rails/assets/USAGE b/railties/lib/rails/generators/rails/assets/USAGE index d2e5ed4482..ee73d05808 100644 --- a/railties/lib/rails/generators/rails/assets/USAGE +++ b/railties/lib/rails/generators/rails/assets/USAGE @@ -5,16 +5,13 @@ Description: To create an asset within a folder, specify the asset's name as a path like 'parent/name'. - This generates a JavaScript stub in app/assets/javascripts and a stylesheet - stub in app/assets/stylesheets. + This generates a stylesheet stub in app/assets/stylesheets. - If CoffeeScript is available, JavaScripts will be generated with the .coffee extension. If Sass 3 is available, stylesheets will be generated with the .scss extension. Example: `rails generate assets posts` Posts assets. - JavaScript: app/assets/javascripts/posts.js Stylesheet: app/assets/stylesheets/posts.css diff --git a/railties/lib/rails/generators/rails/assets/assets_generator.rb b/railties/lib/rails/generators/rails/assets/assets_generator.rb index ffb695a1f3..9ce8570172 100644 --- a/railties/lib/rails/generators/rails/assets/assets_generator.rb +++ b/railties/lib/rails/generators/rails/assets/assets_generator.rb @@ -3,22 +3,14 @@ module Rails module Generators class AssetsGenerator < NamedBase # :nodoc: - class_option :javascripts, type: :boolean, desc: "Generate JavaScripts" class_option :stylesheets, type: :boolean, desc: "Generate Stylesheets" - - class_option :javascript_engine, desc: "Engine for JavaScripts" class_option :stylesheet_engine, desc: "Engine for Stylesheets" private - def asset_name file_name end - hook_for :javascript_engine do |javascript_engine| - invoke javascript_engine, [name] if options[:javascripts] - end - hook_for :stylesheet_engine do |stylesheet_engine| invoke stylesheet_engine, [name] if options[:stylesheets] end diff --git a/railties/lib/rails/generators/rails/assets/templates/javascript.js b/railties/lib/rails/generators/rails/assets/templates/javascript.js deleted file mode 100644 index dee720facd..0000000000 --- a/railties/lib/rails/generators/rails/assets/templates/javascript.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index 8cc42325bb..9ec0ccbe7a 100644 --- a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -113,7 +113,7 @@ task default: :test end def test_dummy_assets - template "rails/javascripts.js", "#{dummy_path}/app/assets/javascripts/application.js", force: true + template "rails/javascripts.js", "#{dummy_path}/app/javascript/packs/application.js", force: true template "rails/stylesheets.css", "#{dummy_path}/app/assets/stylesheets/application.css", force: true template "rails/dummy_manifest.js", "#{dummy_path}/app/assets/config/manifest.js", force: true end diff --git a/railties/lib/rails/generators/testing/behaviour.rb b/railties/lib/rails/generators/testing/behaviour.rb index 6ab88bd59f..238ffdd677 100644 --- a/railties/lib/rails/generators/testing/behaviour.rb +++ b/railties/lib/rails/generators/testing/behaviour.rb @@ -67,6 +67,9 @@ module Rails def run_generator(args = default_arguments, config = {}) capture(:stdout) do args += ["--skip-bundle"] unless args.include? "--dev" + args |= ["--skip-bootsnap"] unless args.include? "--no-skip-bootsnap" + args |= ["--skip-javascript"] unless args.include? "--no-skip-javascript" + generator_class.start(args, config.reverse_merge(destination_root: destination_root)) end end diff --git a/railties/lib/rails/tasks/statistics.rake b/railties/lib/rails/tasks/statistics.rake index 594db91eec..8cacf4a49f 100644 --- a/railties/lib/rails/tasks/statistics.rake +++ b/railties/lib/rails/tasks/statistics.rake @@ -11,6 +11,7 @@ STATS_DIRECTORIES = [ %w(Mailers app/mailers), %w(Channels app/channels), %w(JavaScripts app/assets/javascripts), + %w(JavaScript app/javascript), %w(Libraries lib/), %w(APIs app/apis), %w(Controller\ tests test/controllers), diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 4ca6d02b85..46ee0d670e 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -68,20 +68,6 @@ module ApplicationTests assert_equal 'a = "/assets/rails.png";', last_response.body.strip end - test "assets do not require compressors until it is used" do - app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" - add_to_env_config "production", "config.assets.compile = true" - add_to_env_config "production", "config.assets.precompile = []" - - # Load app env - app "production" - - assert_not defined?(Uglifier) - get "/assets/demo.js" - assert_match "alert()", last_response.body - assert defined?(Uglifier) - end - test "precompile creates the file, gives it the original asset's content and run in production as default" do app_file "app/assets/config/manifest.js", "//= link_tree ../javascripts" app_file "app/assets/javascripts/application.js", "alert();" @@ -443,13 +429,13 @@ module ApplicationTests end test "digested assets are not mistakenly removed" do - app_file "app/assets/application.js", "alert();" + app_file "app/assets/application.css", "div { font-weight: bold }" add_to_config "config.assets.compile = true" precompile! - files = Dir["#{app_path}/public/assets/application-*.js"] - assert_equal 1, files.length, "Expected digested application.js asset to be generated, but none found" + files = Dir["#{app_path}/public/assets/application-*.css"] + assert_equal 1, files.length, "Expected digested application.css asset to be generated, but none found" end test "digested assets are removed from configured path" do diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 5efaf841d4..631f5bac7f 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -25,6 +25,7 @@ module ApplicationTests boot! assert_equal [ + "Webpacker::DevServerProxy", "Rack::Sendfile", "ActionDispatch::Static", "ActionDispatch::Executor", @@ -56,6 +57,7 @@ module ApplicationTests boot! assert_equal [ + "Webpacker::DevServerProxy", "Rack::Sendfile", "ActionDispatch::Static", "ActionDispatch::Executor", @@ -138,7 +140,7 @@ module ApplicationTests add_to_config "config.ssl_options = { redirect: { host: 'example.com' } }" boot! - assert_equal [{ redirect: { host: "example.com" } }], Rails.application.middleware.first.args + assert_equal [{ redirect: { host: "example.com" } }], Rails.application.middleware[1].args end test "removing Active Record omits its middleware" do @@ -222,30 +224,31 @@ module ApplicationTests test "insert middleware after" do add_to_config "config.middleware.insert_after Rack::Sendfile, Rack::Config" boot! - assert_equal "Rack::Config", middleware.second + assert_equal "Rack::Config", middleware.third end test "unshift middleware" do add_to_config "config.middleware.unshift Rack::Config" boot! - assert_equal "Rack::Config", middleware.first + assert_equal "Rack::Config", middleware.second end test "Rails.cache does not respond to middleware" do add_to_config "config.cache_store = :memory_store" boot! - assert_equal "Rack::Runtime", middleware.fourth + assert_equal "Rack::Runtime", middleware.fifth end test "Rails.cache does respond to middleware" do boot! - assert_equal "Rack::Runtime", middleware.fifth + assert_equal "ActiveSupport::Cache::Strategy::LocalCache", middleware.fifth + assert_equal "Rack::Runtime", middleware[5] end test "insert middleware before" do add_to_config "config.middleware.insert_before Rack::Sendfile, Rack::Config" boot! - assert_equal "Rack::Config", middleware.first + assert_equal "Rack::Config", middleware.second end test "can't change middleware after it's built" do diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index 1522a2bbc5..a0cdae898b 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -118,7 +118,7 @@ module ApplicationTests end def test_code_statistics_sanity - assert_match "Code LOC: 25 Test LOC: 0 Code to Test Ratio: 1:0.0", + assert_match "Code LOC: 32 Test LOC: 0 Code to Test Ratio: 1:0.0", rails("stats") end @@ -190,6 +190,7 @@ module ApplicationTests rails "generate", "model", "Cart" rails "generate", "scaffold", "LineItems", "product:references", "cart:belongs_to" with_rails_env("test") { rails("db:migrate") } + rails("webpacker:compile") output = rails("test") assert_match(/7 runs, 9 assertions, 0 failures, 0 errors/, output) diff --git a/railties/test/engine/commands_test.rb b/railties/test/engine/commands_test.rb index 48c93af80c..0e5167578d 100644 --- a/railties/test/engine/commands_test.rb +++ b/railties/test/engine/commands_test.rb @@ -24,7 +24,7 @@ class Rails::Engine::CommandsTest < ActiveSupport::TestCase def test_runner_command_work_inside_engine output = capture(:stdout) do - Dir.chdir(plugin_path) { system("bin/rails runner 'puts Rails.env'") } + Dir.chdir(plugin_path) { system({ "SKIP_REQUIRE_WEBPACKER" => "true" }, "bin/rails runner 'puts Rails.env'") } end assert_equal "test", output.strip @@ -67,6 +67,7 @@ class Rails::Engine::CommandsTest < ActiveSupport::TestCase def spawn_command(command, fd) Process.spawn( + { "SKIP_REQUIRE_WEBPACKER" => "true" }, "#{plugin_path}/bin/rails #{command}", in: fd, out: fd, err: fd ) diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index da52b6076a..6d53230eab 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -125,7 +125,7 @@ class ActionsTest < Rails::Generators::TestCase def test_gem_works_even_if_frozen_string_is_passed_as_argument run_generator - action :gem, "frozen_gem".freeze, "1.0.0".freeze + action :gem, -"frozen_gem", -"1.0.0" assert_file "Gemfile", /^gem 'frozen_gem', '1.0.0'$/ end diff --git a/railties/test/generators/api_app_generator_test.rb b/railties/test/generators/api_app_generator_test.rb index c2540f4091..4f2894e71e 100644 --- a/railties/test/generators/api_app_generator_test.rb +++ b/railties/test/generators/api_app_generator_test.rb @@ -40,7 +40,6 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase end assert_file "Gemfile" do |content| - assert_no_match(/gem 'coffee-rails'/, content) assert_no_match(/gem 'sass-rails'/, content) assert_no_match(/gem 'web-console'/, content) assert_no_match(/gem 'capybara'/, content) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 1169633244..48e8b7123f 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -13,10 +13,9 @@ DEFAULT_APP_FILES = %w( config.ru app/assets/config/manifest.js app/assets/images - app/assets/javascripts - app/assets/javascripts/application.js - app/assets/javascripts/cable.js - app/assets/javascripts/channels + app/javascript + app/javascript/channels + app/javascript/packs/application.js app/assets/stylesheets app/assets/stylesheets/application.css app/channels/application_cable/channel.rb @@ -114,12 +113,12 @@ class AppGeneratorTest < Rails::Generators::TestCase end def test_assets - run_generator + run_generator [destination_root, "--no-skip-javascript"] assert_file("app/views/layouts/application.html.erb", /stylesheet_link_tag\s+'application', media: 'all', 'data-turbolinks-track': 'reload'/) - assert_file("app/views/layouts/application.html.erb", /javascript_include_tag\s+'application', 'data-turbolinks-track': 'reload'/) + assert_file("app/views/layouts/application.html.erb", /javascript_pack_tag\s+'application', 'data-turbolinks-track': 'reload'/) assert_file("app/assets/stylesheets/application.css") - assert_file("app/assets/javascripts/application.js") + assert_file("app/javascript/packs/application.js") end def test_application_job_file_present @@ -215,7 +214,8 @@ class AppGeneratorTest < Rails::Generators::TestCase def test_new_application_load_defaults app_root = File.join(destination_root, "myfirstapp") - run_generator [app_root] + run_generator [app_root, "--no-skip-javascript"] + output = nil assert_file "#{app_root}/config/application.rb", /\s+config\.load_defaults #{Rails::VERSION::STRING.to_f}/ @@ -559,7 +559,6 @@ class AppGeneratorTest < Rails::Generators::TestCase run_generator assert_gem "sass-rails" - assert_gem "uglifier" end def test_action_cable_redis_gems @@ -601,24 +600,6 @@ class AppGeneratorTest < Rails::Generators::TestCase end end - def test_inclusion_of_javascript_runtime - run_generator - if defined?(JRUBY_VERSION) - assert_gem "therubyrhino" - elsif RUBY_PLATFORM =~ /mingw|mswin/ - assert_gem "duktape" - else - assert_file "Gemfile", /# gem 'mini_racer', platforms: :ruby/ - end - end - - def test_rails_ujs_is_the_default_ujs_library - run_generator - assert_file "app/assets/javascripts/application.js" do |contents| - assert_match %r{^//= require rails-ujs}, contents - end - end - def test_javascript_is_skipped_if_required run_generator [destination_root, "--skip-javascript"] @@ -628,22 +609,6 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_match(/stylesheet_link_tag\s+'application', media: 'all' %>/, contents) assert_no_match(/javascript_include_tag\s+'application' \%>/, contents) end - - assert_no_gem "coffee-rails" - assert_no_gem "uglifier" - - assert_file "config/environments/production.rb" do |content| - assert_no_match(/config\.assets\.js_compressor = :uglifier/, content) - end - end - - def test_coffeescript_is_skipped_if_required - run_generator [destination_root, "--skip-coffee"] - - assert_file "Gemfile" do |content| - assert_no_match(/coffee-rails/, content) - assert_match(/uglifier/, content) - end end def test_inclusion_of_jbuilder @@ -819,22 +784,22 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_no_gem "spring" end - def test_webpack_option + def test_skip_javascript_option command_check = -> command, *_ do @called ||= 0 if command == "webpacker:install" @called += 1 - assert_equal 1, @called, "webpacker:install expected to be called once, but was called #{@called} times." + assert_equal 0, @called, "webpacker:install expected not to be called once, but was called #{@called} times." end end - generator([destination_root], webpack: "webpack").stub(:rails_command, command_check) do + generator([destination_root], skip_javascript: true).stub(:rails_command, command_check) do generator.stub :bundle_command, nil do quietly { generator.invoke_all } end end - assert_gem "webpacker" + assert_no_gem "webpacker" end def test_webpack_option_with_js_framework @@ -856,22 +821,24 @@ class AppGeneratorTest < Rails::Generators::TestCase quietly { generator.invoke_all } end end + + assert_gem "webpacker" end def test_generator_if_skip_turbolinks_is_given - run_generator [destination_root, "--skip-turbolinks"] + run_generator [destination_root, "--skip-turbolinks", "--no-skip-javascript"] assert_no_gem "turbolinks" assert_file "app/views/layouts/application.html.erb" do |content| assert_no_match(/data-turbolinks-track/, content) end - assert_file "app/assets/javascripts/application.js" do |content| + assert_file "app/javascript/packs/application.js" do |content| assert_no_match(/turbolinks/, content) end end def test_bootsnap - run_generator + run_generator [destination_root, "--no-skip-bootsnap"] unless defined?(JRUBY_VERSION) assert_gem "bootsnap" @@ -972,7 +939,7 @@ class AppGeneratorTest < Rails::Generators::TestCase template end - sequence = ["git init", "install", "binstubs bundler", "exec spring binstub --all", "echo ran after_bundle"] + sequence = ["git init", "install", "binstubs bundler", "exec spring binstub --all", "webpacker:install", "echo ran after_bundle"] @sequence_step ||= 0 ensure_bundler_first = -> command, options = nil do assert_equal sequence[@sequence_step], command, "commands should be called in sequence #{sequence}" @@ -989,7 +956,7 @@ class AppGeneratorTest < Rails::Generators::TestCase end end - assert_equal 5, @sequence_step + assert_equal 6, @sequence_step end def test_gitignore diff --git a/railties/test/generators/assets_generator_test.rb b/railties/test/generators/assets_generator_test.rb index 3cec41dbf8..83d2429acf 100644 --- a/railties/test/generators/assets_generator_test.rb +++ b/railties/test/generators/assets_generator_test.rb @@ -9,13 +9,11 @@ class AssetsGeneratorTest < Rails::Generators::TestCase def test_assets run_generator - assert_file "app/assets/javascripts/posts.js" assert_file "app/assets/stylesheets/posts.css" end def test_skipping_assets - run_generator ["posts", "--no-stylesheets", "--no-javascripts"] - assert_no_file "app/assets/javascripts/posts.js" + run_generator ["posts", "--no-stylesheets"] assert_no_file "app/assets/stylesheets/posts.css" end end diff --git a/railties/test/generators/channel_generator_test.rb b/railties/test/generators/channel_generator_test.rb index e543cc11b8..265d7c9618 100644 --- a/railties/test/generators/channel_generator_test.rb +++ b/railties/test/generators/channel_generator_test.rb @@ -26,8 +26,8 @@ class ChannelGeneratorTest < Rails::Generators::TestCase assert_match(/class ChatChannel < ApplicationCable::Channel/, channel) end - assert_file "app/assets/javascripts/channels/chat.js" do |channel| - assert_match(/App\.chat = App\.cable\.subscriptions\.create\("ChatChannel/, channel) + assert_file "app/javascript/channels/chat_channel.js" do |channel| + assert_match(/import consumer from "\.\/consumer"\s+consumer\.subscriptions\.create\("ChatChannel/, channel) end end @@ -40,8 +40,8 @@ class ChannelGeneratorTest < Rails::Generators::TestCase assert_match(/def mute/, channel) end - assert_file "app/assets/javascripts/channels/chat.js" do |channel| - assert_match(/App\.chat = App\.cable\.subscriptions\.create\("ChatChannel/, channel) + assert_file "app/javascript/channels/chat_channel.js" do |channel| + assert_match(/import consumer from "\.\/consumer"\s+consumer\.subscriptions\.create\("ChatChannel/, channel) assert_match(/,\n\n speak/, channel) assert_match(/,\n\n mute: function\(\) \{\n return this\.perform\('mute'\);\n \}\n\}\);/, channel) end @@ -54,15 +54,17 @@ class ChannelGeneratorTest < Rails::Generators::TestCase assert_match(/class ChatChannel < ApplicationCable::Channel/, channel) end - assert_no_file "app/assets/javascripts/channels/chat.js" + assert_no_file "app/javascript/channels/chat_channel.js" end def test_cable_js_is_created_if_not_present_already run_generator ["chat"] - FileUtils.rm("#{destination_root}/app/assets/javascripts/cable.js") + FileUtils.rm("#{destination_root}/app/javascript/channels/index.js") + FileUtils.rm("#{destination_root}/app/javascript/channels/consumer.js") run_generator ["camp"] - assert_file "app/assets/javascripts/cable.js" + assert_file "app/javascript/channels/index.js" + assert_file "app/javascript/channels/consumer.js" end def test_channel_on_revoke @@ -74,7 +76,8 @@ class ChannelGeneratorTest < Rails::Generators::TestCase assert_file "app/channels/application_cable/channel.rb" assert_file "app/channels/application_cable/connection.rb" - assert_file "app/assets/javascripts/cable.js" + assert_file "app/javascript/channels/index.js" + assert_file "app/javascript/channels/consumer.js" end def test_channel_suffix_is_not_duplicated @@ -84,6 +87,6 @@ class ChannelGeneratorTest < Rails::Generators::TestCase assert_file "app/channels/chat_channel.rb" assert_no_file "app/assets/javascripts/channels/chat_channel.js" - assert_file "app/assets/javascripts/channels/chat.js" + assert_file "app/javascript/channels/chat_channel.js" end end diff --git a/railties/test/generators/controller_generator_test.rb b/railties/test/generators/controller_generator_test.rb index 021004c9b8..adef56255a 100644 --- a/railties/test/generators/controller_generator_test.rb +++ b/railties/test/generators/controller_generator_test.rb @@ -39,13 +39,11 @@ class ControllerGeneratorTest < Rails::Generators::TestCase def test_invokes_assets run_generator - assert_file "app/assets/javascripts/account.js" assert_file "app/assets/stylesheets/account.css" end def test_does_not_invoke_assets_if_required run_generator ["account", "--skip-assets"] - assert_no_file "app/assets/javascripts/account.js" assert_no_file "app/assets/stylesheets/account.css" end @@ -133,7 +131,6 @@ class ControllerGeneratorTest < Rails::Generators::TestCase assert_file "app/helpers/account_helper.rb" assert_no_file "app/assets/javascripts/account_controller.js" - assert_file "app/assets/javascripts/account.js" assert_no_file "app/assets/stylesheets/account_controller.css" assert_file "app/assets/stylesheets/account.css" diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index ad2a55f496..25d5dba1d8 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -42,6 +42,21 @@ module GeneratorsTestHelper end end + def with_secondary_database_configuration + original_configurations = ActiveRecord::Base.configurations + ActiveRecord::Base.configurations = { + test: { + secondary: { + database: "db/secondary.sqlite3", + migrations_paths: "db/secondary_migrate", + }, + }, + } + yield + ensure + ActiveRecord::Base.configurations = original_configurations + end + def copy_routes routes = File.expand_path("../../lib/rails/generators/rails/app/templates/config/routes.rb.tt", __dir__) destination = File.join(destination_root, "config") diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb index 5c57d607fc..5812cbdfc9 100644 --- a/railties/test/generators/migration_generator_test.rb +++ b/railties/test/generators/migration_generator_test.rb @@ -254,11 +254,13 @@ class MigrationGeneratorTest < Rails::Generators::TestCase end end - def test_migrations_paths_puts_migrations_in_that_folder - run_generator ["create_books", "--migrations_paths=db/test_migrate"] - assert_migration "db/test_migrate/create_books.rb" do |content| - assert_method :change, content do |change| - assert_match(/create_table :books/, change) + def test_database_puts_migrations_in_configured_folder + with_secondary_database_configuration do + run_generator ["create_books", "--database=secondary"] + assert_migration "db/secondary_migrate/create_books.rb" do |content| + assert_method :change, content do |change| + assert_match(/create_table :books/, change) + end end end end diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index 5a0c2f74c7..b06db6dd8a 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -392,11 +392,13 @@ class ModelGeneratorTest < Rails::Generators::TestCase end end - def test_migrations_paths_puts_migrations_in_that_folder - run_generator ["account", "--migrations_paths=db/test_migrate"] - assert_migration "db/test_migrate/create_accounts.rb" do |content| - assert_method :change, content do |change| - assert_match(/create_table :accounts/, change) + def test_database_puts_migrations_in_configured_folder + with_secondary_database_configuration do + run_generator ["account", "--database=secondary"] + assert_migration "db/secondary_migrate/create_accounts.rb" do |content| + assert_method :change, content do |change| + assert_match(/create_table :accounts/, change) + end end end end diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 468a9c9e89..66286fc554 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -140,10 +140,6 @@ class PluginGeneratorTest < Rails::Generators::TestCase run_generator assert_file "test/dummy/app/assets/stylesheets/application.css" - - assert_file "test/dummy/app/assets/javascripts/application.js" do |contents| - assert_no_match(/jquery/, contents) - end end def test_ensure_that_plugin_options_are_not_passed_to_app_generator @@ -210,28 +206,10 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_no_file "#{destination_root}/Gemfile.lock" end - def test_skipping_javascripts_without_mountable_option - run_generator - assert_no_file "app/assets/javascripts/bukkits/application.js" - end - - def test_javascripts_generation - run_generator [destination_root, "--mountable"] - assert_file "app/assets/javascripts/bukkits/application.js" do |content| - assert_match "//= require rails-ujs", content - assert_match "//= require activestorage", content - assert_match "//= require_tree .", content - end - assert_file "app/views/layouts/bukkits/application.html.erb" do |content| - assert_match "javascript_include_tag", content - end - end - - def test_skip_javascripts + def test_skip_javascript run_generator [destination_root, "--skip-javascript", "--mountable"] - assert_no_file "app/assets/javascripts/bukkits/application.js" assert_file "app/views/layouts/bukkits/application.html.erb" do |content| - assert_no_match "javascript_include_tag", content + assert_no_match "javascript_pack_tag", content end end @@ -264,7 +242,6 @@ class PluginGeneratorTest < Rails::Generators::TestCase def test_creating_engine_in_full_mode run_generator [destination_root, "--full"] - assert_file "app/assets/javascripts/bukkits" assert_file "app/assets/stylesheets/bukkits" assert_file "app/assets/images/bukkits" assert_file "app/models" @@ -280,7 +257,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase def test_creating_engine_with_hyphenated_name_in_full_mode run_generator [File.join(destination_root, "hyphenated-name"), "--full"] - assert_file "hyphenated-name/app/assets/javascripts/hyphenated/name" + assert_no_file "hyphenated-name/app/assets/javascripts/hyphenated/name" assert_file "hyphenated-name/app/assets/stylesheets/hyphenated/name" assert_file "hyphenated-name/app/assets/images/hyphenated/name" assert_file "hyphenated-name/app/models" @@ -297,7 +274,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase def test_creating_engine_with_hyphenated_and_underscored_name_in_full_mode run_generator [File.join(destination_root, "my_hyphenated-name"), "--full"] - assert_file "my_hyphenated-name/app/assets/javascripts/my_hyphenated/name" + assert_no_file "my_hyphenated-name/app/assets/javascripts/my_hyphenated/name" assert_file "my_hyphenated-name/app/assets/stylesheets/my_hyphenated/name" assert_file "my_hyphenated-name/app/assets/images/my_hyphenated/name" assert_file "my_hyphenated-name/app/models" @@ -318,7 +295,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase def test_create_mountable_application_with_mountable_option run_generator [destination_root, "--mountable"] - assert_file "app/assets/javascripts/bukkits" + assert_no_file "app/assets/javascripts/bukkits" assert_file "app/assets/stylesheets/bukkits" assert_file "app/assets/images/bukkits" assert_file "config/routes.rb", /Bukkits::Engine\.routes\.draw do/ @@ -334,7 +311,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_match "<%= csrf_meta_tags %>", contents assert_match "<%= csp_meta_tag %>", contents assert_match(/stylesheet_link_tag\s+['"]bukkits\/application['"]/, contents) - assert_match(/javascript_include_tag\s+['"]bukkits\/application['"]/, contents) + assert_no_match(/javascript_include_tag\s+['"]bukkits\/application['"]/, contents) assert_match "<%= yield %>", contents end assert_file "test/test_helper.rb" do |content| @@ -348,7 +325,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase def test_create_mountable_application_with_mountable_option_and_hypenated_name run_generator [File.join(destination_root, "hyphenated-name"), "--mountable"] - assert_file "hyphenated-name/app/assets/javascripts/hyphenated/name" + assert_no_file "hyphenated-name/app/assets/javascripts/hyphenated/name" assert_file "hyphenated-name/app/assets/stylesheets/hyphenated/name" assert_file "hyphenated-name/app/assets/images/hyphenated/name" assert_file "hyphenated-name/config/routes.rb", /Hyphenated::Name::Engine\.routes\.draw do/ @@ -364,13 +341,13 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "hyphenated-name/app/views/layouts/hyphenated/name/application.html.erb" do |contents| assert_match "<title>Hyphenated name</title>", contents assert_match(/stylesheet_link_tag\s+['"]hyphenated\/name\/application['"]/, contents) - assert_match(/javascript_include_tag\s+['"]hyphenated\/name\/application['"]/, contents) + assert_no_match(/javascript_include_tag\s+['"]hyphenated\/name\/application['"]/, contents) end end def test_create_mountable_application_with_mountable_option_and_hypenated_and_underscored_name run_generator [File.join(destination_root, "my_hyphenated-name"), "--mountable"] - assert_file "my_hyphenated-name/app/assets/javascripts/my_hyphenated/name" + assert_no_file "my_hyphenated-name/app/assets/javascripts/my_hyphenated/name" assert_file "my_hyphenated-name/app/assets/stylesheets/my_hyphenated/name" assert_file "my_hyphenated-name/app/assets/images/my_hyphenated/name" assert_file "my_hyphenated-name/config/routes.rb", /MyHyphenated::Name::Engine\.routes\.draw do/ @@ -386,13 +363,13 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "my_hyphenated-name/app/views/layouts/my_hyphenated/name/application.html.erb" do |contents| assert_match "<title>My hyphenated name</title>", contents assert_match(/stylesheet_link_tag\s+['"]my_hyphenated\/name\/application['"]/, contents) - assert_match(/javascript_include_tag\s+['"]my_hyphenated\/name\/application['"]/, contents) + assert_no_match(/javascript_include_tag\s+['"]my_hyphenated\/name\/application['"]/, contents) end end def test_create_mountable_application_with_mountable_option_and_multiple_hypenates_in_name run_generator [File.join(destination_root, "deep-hyphenated-name"), "--mountable"] - assert_file "deep-hyphenated-name/app/assets/javascripts/deep/hyphenated/name" + assert_no_file "deep-hyphenated-name/app/assets/javascripts/deep/hyphenated/name" assert_file "deep-hyphenated-name/app/assets/stylesheets/deep/hyphenated/name" assert_file "deep-hyphenated-name/app/assets/images/deep/hyphenated/name" assert_file "deep-hyphenated-name/config/routes.rb", /Deep::Hyphenated::Name::Engine\.routes\.draw do/ @@ -408,7 +385,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "deep-hyphenated-name/app/views/layouts/deep/hyphenated/name/application.html.erb" do |contents| assert_match "<title>Deep hyphenated name</title>", contents assert_match(/stylesheet_link_tag\s+['"]deep\/hyphenated\/name\/application['"]/, contents) - assert_match(/javascript_include_tag\s+['"]deep\/hyphenated\/name\/application['"]/, contents) + assert_no_match(/javascript_include_tag\s+['"]deep\/hyphenated\/name\/application['"]/, contents) end end diff --git a/railties/test/generators/resource_generator_test.rb b/railties/test/generators/resource_generator_test.rb index 7a470d0d91..b99b4baf6b 100644 --- a/railties/test/generators/resource_generator_test.rb +++ b/railties/test/generators/resource_generator_test.rb @@ -65,7 +65,7 @@ class ResourceGeneratorTest < Rails::Generators::TestCase end def test_plural_names_are_singularized - content = run_generator ["accounts".freeze] + content = run_generator ["accounts"] assert_file "app/models/account.rb", /class Account < ApplicationRecord/ assert_file "test/models/account_test.rb", /class AccountTest/ assert_match(/\[WARNING\] The model name 'accounts' was recognized as a plural, using the singular 'account' instead\. Override with --force-plural or setup custom inflection rules for this noun before running the generator\./, content) @@ -79,7 +79,7 @@ class ResourceGeneratorTest < Rails::Generators::TestCase end def test_mass_nouns_do_not_throw_warnings - content = run_generator ["sheep".freeze] + content = run_generator ["sheep"] assert_no_match(/\[WARNING\]/, content) end diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index dbcf49290e..21b5013484 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -93,7 +93,6 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase # Assets assert_file "app/assets/stylesheets/scaffold.css" - assert_file "app/assets/javascripts/product_lines.js" assert_file "app/assets/stylesheets/product_lines.css" end @@ -166,7 +165,6 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase # Assets assert_no_file "app/assets/stylesheets/scaffold.css" - assert_no_file "app/assets/javascripts/product_lines.js" assert_no_file "app/assets/stylesheets/product_lines.css" end @@ -222,7 +220,6 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase # Assets assert_file "app/assets/stylesheets/scaffold.css", /:visited/ - assert_no_file "app/assets/javascripts/product_lines.js" assert_no_file "app/assets/stylesheets/product_lines.css" end @@ -299,7 +296,6 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase # Assets assert_file "app/assets/stylesheets/scaffold.css", /:visited/ - assert_file "app/assets/javascripts/admin/roles.js" assert_file "app/assets/stylesheets/admin/roles.css" end @@ -335,7 +331,6 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase # Assets assert_file "app/assets/stylesheets/scaffold.css" - assert_no_file "app/assets/javascripts/admin/roles.js" assert_no_file "app/assets/stylesheets/admin/roles.css" end @@ -380,28 +375,24 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase def test_scaffold_generator_no_assets_with_switch_no_assets run_generator [ "posts", "--no-assets" ] assert_no_file "app/assets/stylesheets/scaffold.css" - assert_no_file "app/assets/javascripts/posts.js" assert_no_file "app/assets/stylesheets/posts.css" end def test_scaffold_generator_no_assets_with_switch_assets_false run_generator [ "posts", "--assets=false" ] assert_no_file "app/assets/stylesheets/scaffold.css" - assert_no_file "app/assets/javascripts/posts.js" assert_no_file "app/assets/stylesheets/posts.css" end def test_scaffold_generator_no_scaffold_stylesheet_with_switch_no_scaffold_stylesheet run_generator [ "posts", "--no-scaffold-stylesheet" ] assert_no_file "app/assets/stylesheets/scaffold.css" - assert_file "app/assets/javascripts/posts.js" assert_file "app/assets/stylesheets/posts.css" end def test_scaffold_generator_no_scaffold_stylesheet_with_switch_scaffold_stylesheet_false run_generator [ "posts", "--scaffold-stylesheet=false" ] assert_no_file "app/assets/stylesheets/scaffold.css" - assert_file "app/assets/javascripts/posts.js" assert_file "app/assets/stylesheets/posts.css" end @@ -429,17 +420,9 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase def test_scaffold_generator_no_stylesheets run_generator [ "posts", "--no-stylesheets" ] assert_no_file "app/assets/stylesheets/scaffold.css" - assert_file "app/assets/javascripts/posts.js" assert_no_file "app/assets/stylesheets/posts.css" end - def test_scaffold_generator_no_javascripts - run_generator [ "posts", "--no-javascripts" ] - assert_file "app/assets/stylesheets/scaffold.css" - assert_no_file "app/assets/javascripts/posts.js" - assert_file "app/assets/stylesheets/posts.css" - end - def test_scaffold_generator_outputs_error_message_on_missing_attribute_type run_generator ["post", "title", "body:text", "author"] @@ -476,10 +459,12 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase end end - def test_scaffold_generator_migrations_paths - run_generator ["posts", "--migrations-paths=db/kingston_migrate"] + def test_scaffold_generator_database + with_secondary_database_configuration do + run_generator ["posts", "--database=secondary"] - assert_migration "db/kingston_migrate/create_posts.rb" + assert_migration "db/secondary_migrate/create_posts.rb" + end end def test_scaffold_generator_password_digest @@ -628,7 +613,6 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert File.exist?("app/helpers/bukkits/users_helper.rb") - assert File.exist?("app/assets/javascripts/bukkits/users.js") assert File.exist?("app/assets/stylesheets/bukkits/users.css") end end @@ -658,7 +642,6 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_not File.exist?("app/helpers/bukkits/users_helper.rb") - assert_not File.exist?("app/assets/javascripts/bukkits/users.js") assert_not File.exist?("app/assets/stylesheets/bukkits/users.css") end end diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index 5a1257e5c1..521f775553 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -27,7 +27,7 @@ module SharedGeneratorTests end def test_skeleton_is_created - run_generator + run_generator [destination_root, "--no-skip-javascript"] default_files.each { |path| assert_file path } end @@ -196,10 +196,12 @@ module SharedGeneratorTests end def test_generator_for_active_storage - run_generator + run_generator [destination_root, "--no-skip-javascript"] - assert_file "#{application_path}/app/assets/javascripts/application.js" do |content| - assert_match(/^\/\/= require activestorage/, content) + unless generator_class.name == "Rails::Generators::PluginGenerator" + assert_file "#{application_path}/app/javascript/packs/application.js" do |content| + assert_match(/^import \* as ActiveStorage from "activestorage"\nActiveStorage.start\(\)/, content) + end end assert_file "#{application_path}/config/environments/development.rb" do |content| @@ -224,11 +226,11 @@ module SharedGeneratorTests end def test_generator_if_skip_active_storage_is_given - run_generator [destination_root, "--skip-active-storage"] + run_generator [destination_root, "--skip-active-storage", "--no-skip-javascript"] assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_storage\/engine["']/ - assert_file "#{application_path}/app/assets/javascripts/application.js" do |content| + assert_file "#{application_path}/app/javascript/packs/application.js" do |content| assert_no_match(/^\/\/= require activestorage/, content) end @@ -254,12 +256,12 @@ module SharedGeneratorTests end def test_generator_does_not_generate_active_storage_contents_if_skip_active_record_is_given - run_generator [destination_root, "--skip-active-record"] + run_generator [destination_root, "--skip-active-record", "--no-skip-javascript"] assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_storage\/engine["']/ - assert_file "#{application_path}/app/assets/javascripts/application.js" do |content| - assert_no_match(/^\/\/= require activestorage/, content) + assert_file "#{application_path}/app/javascript/packs/application.js" do |content| + assert_no_match(/^import * as ActiveStorage from "activestorage"\nActiveStorage.start()/, content) end assert_file "#{application_path}/config/environments/development.rb" do |content| @@ -320,8 +322,6 @@ module SharedGeneratorTests assert_file "Gemfile" do |content| assert_no_match(/sass-rails/, content) - assert_no_match(/uglifier/, content) - assert_no_match(/coffee-rails/, content) end assert_file "#{application_path}/config/environments/development.rb" do |content| @@ -330,7 +330,6 @@ module SharedGeneratorTests assert_file "#{application_path}/config/environments/production.rb" do |content| assert_no_match(/config\.assets\.digest/, content) - assert_no_match(/config\.assets\.js_compressor/, content) assert_no_match(/config\.assets\.css_compressor/, content) assert_no_match(/config\.assets\.compile/, content) end diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 2a8c6d8f97..e44f21380e 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -30,11 +30,11 @@ require "rails/secrets" module TestHelpers module Paths def app_template_path - File.join Dir.tmpdir, "app_template" + File.join RAILS_FRAMEWORK_ROOT, "tmp/templates/app_template" end def tmp_path(*args) - @tmp_path ||= File.realpath(Dir.mktmpdir) + @tmp_path ||= File.realpath(Dir.mktmpdir(nil, File.join(RAILS_FRAMEWORK_ROOT, "tmp"))) File.join(@tmp_path, *args) end @@ -469,17 +469,28 @@ Module.new do # Build a rails app FileUtils.rm_rf(app_template_path) - FileUtils.mkdir(app_template_path) + FileUtils.mkdir_p(app_template_path) + + Dir.chdir "#{RAILS_FRAMEWORK_ROOT}/actionview" do + `yarn build` + end `#{Gem.ruby} #{RAILS_FRAMEWORK_ROOT}/railties/exe/rails new #{app_template_path} --skip-gemfile --skip-listen --no-rc` File.open("#{app_template_path}/config/boot.rb", "w") do |f| f.puts "require 'rails/all'" end + Dir.chdir(app_template_path) { `yarn add https://github.com/rails/webpacker.git` } # Use the latest version. + + # Manually install `webpack` as bin symlinks are not created for subdependencies + # in workspaces. See https://github.com/yarnpkg/yarn/issues/4964 + Dir.chdir(app_template_path) { `yarn add webpack@4.17.1 --tilde` } + Dir.chdir(app_template_path) { `yarn add webpack-cli` } + # Fake 'Bundler.require' -- we run using the repo's Gemfile, not an # app-specific one: we don't want to require every gem that lists. contents = File.read("#{app_template_path}/config/application.rb") - contents.sub!(/^Bundler\.require.*/, "%w(turbolinks).each { |r| require r }") + contents.sub!(/^Bundler\.require.*/, "%w(turbolinks webpacker).each { |r| require r }") File.write("#{app_template_path}/config/application.rb", contents) require "rails" |