diff options
Diffstat (limited to 'railties/lib/rails')
58 files changed, 346 insertions, 260 deletions
diff --git a/railties/lib/rails/api/generator.rb b/railties/lib/rails/api/generator.rb index 3405560b74..126d4d0438 100644 --- a/railties/lib/rails/api/generator.rb +++ b/railties/lib/rails/api/generator.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "sdoc" +require "active_support/core_ext/array/extract" class RDoc::Generator::API < RDoc::Generator::SDoc # :nodoc: RDoc::RDoc.add_generator self @@ -11,7 +12,7 @@ class RDoc::Generator::API < RDoc::Generator::SDoc # :nodoc: # since they aren't nested under a definition of the `ActiveStorage` module. if visited.empty? classes = classes.reject { |klass| active_storage?(klass) } - core_exts, classes = classes.partition { |klass| core_extension?(klass) } + core_exts = classes.extract! { |klass| core_extension?(klass) } super.unshift([ "Core extensions", "", "", build_core_ext_subtree(core_exts, visited) ]) else diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 31d0d65a30..656786246d 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -232,7 +232,10 @@ module Rails if yaml.exist? require "erb" - (YAML.load(ERB.new(yaml.read).result) || {})[env] || {} + require "active_support/ordered_options" + + config = (YAML.load(ERB.new(yaml.read).result) || {})[env] || {} + ActiveSupport::InheritableOptions.new(config.deep_symbolize_keys) else raise "Could not load configuration. No such file - #{yaml}" end @@ -267,6 +270,7 @@ module Rails "action_dispatch.cookies_serializer" => config.action_dispatch.cookies_serializer, "action_dispatch.cookies_digest" => config.action_dispatch.cookies_digest, "action_dispatch.cookies_rotations" => config.action_dispatch.cookies_rotations, + "action_dispatch.use_cookies_with_metadata" => config.action_dispatch.use_cookies_with_metadata, "action_dispatch.content_security_policy" => config.content_security_policy, "action_dispatch.content_security_policy_report_only" => config.content_security_policy_report_only, "action_dispatch.content_security_policy_nonce_generator" => config.content_security_policy_nonce_generator @@ -434,8 +438,12 @@ module Rails # Decrypts the credentials hash as kept in +config/credentials.yml.enc+. This file is encrypted with # the Rails master key, which is either taken from <tt>ENV["RAILS_MASTER_KEY"]</tt> or from loading # +config/master.key+. + # If specific credentials file exists for current environment, it takes precedence, thus for +production+ + # environment look first for +config/credentials/production.yml.enc+ with master key taken + # from <tt>ENV["RAILS_MASTER_KEY"]</tt> or from loading +config/credentials/production.key+. + # Default behavior can be overwritten by setting +config.credentials.content_path+ and +config.credentials.key_path+. def credentials - @credentials ||= encrypted("config/credentials.yml.enc") + @credentials ||= encrypted(config.credentials.content_path, key_path: config.credentials.key_path) end # Shorthand to decrypt any encrypted configurations or files. diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 9c54cc1f37..eae902a938 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -17,7 +17,7 @@ module Rails :session_options, :time_zone, :reload_classes_only_on_change, :beginning_of_week, :filter_redirect, :x, :enable_dependency_loading, :read_encrypted_secrets, :log_level, :content_security_policy_report_only, - :content_security_policy_nonce_generator, :require_master_key + :content_security_policy_nonce_generator, :require_master_key, :credentials attr_reader :encoding, :api_only, :loaded_config_version @@ -60,6 +60,9 @@ module Rails @content_security_policy_nonce_generator = nil @require_master_key = false @loaded_config_version = nil + @credentials = ActiveSupport::OrderedOptions.new + @credentials.content_path = default_credentials_content_path + @credentials.key_path = default_credentials_key_path end def load_defaults(target_version) @@ -120,6 +123,10 @@ module Rails if respond_to?(:action_view) action_view.default_enforce_utf8 = false end + + if respond_to?(:action_dispatch) + action_dispatch.use_cookies_with_metadata = true + end else raise "Unknown version #{target_version.to_s.inspect}" end @@ -164,18 +171,6 @@ module Rails end end - # Loads the database YAML without evaluating ERB. People seem to - # write ERB that makes the database configuration depend on - # Rails configuration. But we want Rails configuration (specifically - # `rake` and `rails` tasks) to be generated based on information in - # the database yaml, so we need a method that loads the database - # yaml *without* the context of the Rails application. - def load_database_yaml # :nodoc: - path = paths["config/database"].existent.first - return {} unless path - YAML.load_file(path.to_s) - end - # Loads and returns the entire raw configuration of database from # values stored in <tt>config/database.yml</tt>. def database_configuration @@ -281,6 +276,27 @@ module Rails true end end + + private + def credentials_available_for_current_env? + File.exist?("#{root}/config/credentials/#{Rails.env}.yml.enc") + end + + def default_credentials_content_path + if credentials_available_for_current_env? + File.join(root, "config", "credentials", "#{Rails.env}.yml.enc") + else + File.join(root, "config", "credentials.yml.enc") + end + end + + def default_credentials_key_path + if credentials_available_for_current_env? + File.join(root, "config", "credentials", "#{Rails.env}.key") + else + File.join(root, "config", "master.key") + end + end end end end diff --git a/railties/lib/rails/backtrace_cleaner.rb b/railties/lib/rails/backtrace_cleaner.rb index 0e78959966..7c2eb1dc42 100644 --- a/railties/lib/rails/backtrace_cleaner.rb +++ b/railties/lib/rails/backtrace_cleaner.rb @@ -6,29 +6,17 @@ 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 - - add_gem_filters add_silencer { |line| !APP_DIRS_PATTERN.match?(line) } end - - private - def add_gem_filters - gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) } - return if gems_paths.empty? - - gems_regexp = %r{(#{gems_paths.join('|')})/gems/([^/]+)-([\w.]+)/(.*)} - gems_result = '\2 (\3) \4'.freeze - add_filter { |line| line.sub(gems_regexp, gems_result) } - end end end diff --git a/railties/lib/rails/command/spellchecker.rb b/railties/lib/rails/command/spellchecker.rb index 04485097fa..085d5b16df 100644 --- a/railties/lib/rails/command/spellchecker.rb +++ b/railties/lib/rails/command/spellchecker.rb @@ -24,8 +24,8 @@ module Rails n = s.length m = t.length - return m if (0 == n) - return n if (0 == m) + return m if 0 == n + return n if 0 == m d = (0..m).to_a x = nil diff --git a/railties/lib/rails/commands/credentials/USAGE b/railties/lib/rails/commands/credentials/USAGE index ea429f58d8..6b33d1ab74 100644 --- a/railties/lib/rails/commands/credentials/USAGE +++ b/railties/lib/rails/commands/credentials/USAGE @@ -38,3 +38,12 @@ the encrypted credentials. When the temporary file is next saved the contents are encrypted and written to `config/credentials.yml.enc` while the file itself is destroyed to prevent credentials from leaking. + +=== Environment Specific Credentials + +It is possible to have credentials for each environment. If the file for current environment exists it will take +precedence over `config/credentials.yml.enc`, thus for `production` environment first look for +`config/credentials/production.yml.enc` that can be decrypted using master key taken from `ENV["RAILS_MASTER_KEY"]` +or stored in `config/credentials/production.key`. +To edit given file use command `rails credentials:edit --environment production` +Default paths can be overwritten by setting `config.credentials.content_path` and `config.credentials.key_path`. diff --git a/railties/lib/rails/commands/credentials/credentials_command.rb b/railties/lib/rails/commands/credentials/credentials_command.rb index 65c5218fc8..4b30d208e0 100644 --- a/railties/lib/rails/commands/credentials/credentials_command.rb +++ b/railties/lib/rails/commands/credentials/credentials_command.rb @@ -8,6 +8,9 @@ module Rails class CredentialsCommand < Rails::Command::Base # :nodoc: include Helpers::Editor + class_option :environment, aliases: "-e", type: :string, + desc: "Uses credentials from config/credentials/:environment.yml.enc encrypted by config/credentials/:environment.key key" + no_commands do def help say "Usage:\n #{self.class.banner}" @@ -20,58 +23,74 @@ module Rails require_application_and_environment! ensure_editor_available(command: "bin/rails credentials:edit") || (return) - ensure_master_key_has_been_added if Rails.application.credentials.key.nil? - ensure_credentials_have_been_added + + encrypted = Rails.application.encrypted(content_path, key_path: key_path) + + ensure_encryption_key_has_been_added(key_path) if encrypted.key.nil? + ensure_encrypted_file_has_been_added(content_path, key_path) catch_editing_exceptions do - change_credentials_in_system_editor + change_encrypted_file_in_system_editor(content_path, key_path) end - say "New credentials encrypted and saved." + say "File encrypted and saved." + rescue ActiveSupport::MessageEncryptor::InvalidMessage + say "Couldn't decrypt #{content_path}. Perhaps you passed the wrong key?" end def show require_application_and_environment! - say Rails.application.credentials.read.presence || missing_credentials_message + encrypted = Rails.application.encrypted(content_path, key_path: key_path) + + say encrypted.read.presence || missing_encrypted_message(key: encrypted.key, key_path: key_path, file_path: content_path) end private - def ensure_master_key_has_been_added - master_key_generator.add_master_key_file - master_key_generator.ignore_master_key_file + def content_path + options[:environment] ? "config/credentials/#{options[:environment]}.yml.enc" : "config/credentials.yml.enc" + end + + def key_path + options[:environment] ? "config/credentials/#{options[:environment]}.key" : "config/master.key" + end + + + def ensure_encryption_key_has_been_added(key_path) + encryption_key_file_generator.add_key_file(key_path) + encryption_key_file_generator.ignore_key_file(key_path) end - def ensure_credentials_have_been_added - credentials_generator.add_credentials_file_silently + def ensure_encrypted_file_has_been_added(file_path, key_path) + encrypted_file_generator.add_encrypted_file_silently(file_path, key_path) end - def change_credentials_in_system_editor - Rails.application.credentials.change do |tmp_path| + def change_encrypted_file_in_system_editor(file_path, key_path) + Rails.application.encrypted(file_path, key_path: key_path).change do |tmp_path| system("#{ENV["EDITOR"]} #{tmp_path}") end end - def master_key_generator + def encryption_key_file_generator require "rails/generators" - require "rails/generators/rails/master_key/master_key_generator" + require "rails/generators/rails/encryption_key_file/encryption_key_file_generator" - Rails::Generators::MasterKeyGenerator.new + Rails::Generators::EncryptionKeyFileGenerator.new end - def credentials_generator + def encrypted_file_generator require "rails/generators" - require "rails/generators/rails/credentials/credentials_generator" + require "rails/generators/rails/encrypted_file/encrypted_file_generator" - Rails::Generators::CredentialsGenerator.new + Rails::Generators::EncryptedFileGenerator.new end - def missing_credentials_message - if Rails.application.credentials.key.nil? - "Missing master key to decrypt credentials. See `rails credentials:help`" + def missing_encrypted_message(key:, key_path:, file_path:) + if key.nil? + "Missing '#{key_path}' to decrypt credentials. See `rails credentials:help`" else - "No credentials have been added yet. Use `rails credentials:edit` to change that." + "File '#{file_path}' does not exist. Use `rails credentials:edit` to change that." end end end diff --git a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb index 806b7de6d6..0fac7d34a0 100644 --- a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb +++ b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb @@ -75,7 +75,7 @@ module Rails args += ["-P", "#{config['password']}"] if config["password"] if config["host"] - host_arg = "#{config['host']}".dup + host_arg = +"#{config['host']}" host_arg << ":#{config['port']}" if config["port"] args += ["-S", host_arg] end diff --git a/railties/lib/rails/commands/dev/dev_command.rb b/railties/lib/rails/commands/dev/dev_command.rb new file mode 100644 index 0000000000..a3f02f3172 --- /dev/null +++ b/railties/lib/rails/commands/dev/dev_command.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "rails/dev_caching" + +module Rails + module Command + class DevCommand < Base # :nodoc: + def help + say "rails dev:cache # Toggle development mode caching on/off." + end + + def cache + Rails::DevCaching.enable_by_file + end + end + end +end diff --git a/railties/lib/rails/commands/help/help_command.rb b/railties/lib/rails/commands/help/help_command.rb index 8e5b4d68d3..9df34e9b79 100644 --- a/railties/lib/rails/commands/help/help_command.rb +++ b/railties/lib/rails/commands/help/help_command.rb @@ -6,7 +6,7 @@ module Rails hide_command! def help(*) - puts self.class.desc + say self.class.desc Rails::Command.print_commands end diff --git a/railties/lib/rails/commands/initializers/initializers_command.rb b/railties/lib/rails/commands/initializers/initializers_command.rb new file mode 100644 index 0000000000..33596177af --- /dev/null +++ b/railties/lib/rails/commands/initializers/initializers_command.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Rails + module Command + class InitializersCommand < Base # :nodoc: + desc "initializers", "Print out all defined initializers in the order they are invoked by Rails." + def perform + require_application_and_environment! + + Rails.application.initializers.tsort_each do |initializer| + say "#{initializer.context_class}.#{initializer.name}" + end + end + end + end +end diff --git a/railties/lib/rails/commands/new/new_command.rb b/railties/lib/rails/commands/new/new_command.rb index d73d64d899..a4f2081510 100644 --- a/railties/lib/rails/commands/new/new_command.rb +++ b/railties/lib/rails/commands/new/new_command.rb @@ -10,8 +10,8 @@ module Rails end def perform(*) - puts "Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first.\n" - puts "Type 'rails' for help." + say "Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first.\n" + say "Type 'rails' for help." exit 1 end end diff --git a/railties/lib/rails/commands/plugin/plugin_command.rb b/railties/lib/rails/commands/plugin/plugin_command.rb index 2b192abf9b..96187aa952 100644 --- a/railties/lib/rails/commands/plugin/plugin_command.rb +++ b/railties/lib/rails/commands/plugin/plugin_command.rb @@ -26,7 +26,7 @@ module Rails if File.exist?(railsrc) extra_args = File.read(railsrc).split(/\n+/).flat_map(&:split) - puts "Using #{extra_args.join(" ")} from #{railsrc}" + say "Using #{extra_args.join(" ")} from #{railsrc}" plugin_args.insert(1, *extra_args) end end diff --git a/railties/lib/rails/commands/runner/runner_command.rb b/railties/lib/rails/commands/runner/runner_command.rb index 30fbf04982..cb693bcf34 100644 --- a/railties/lib/rails/commands/runner/runner_command.rb +++ b/railties/lib/rails/commands/runner/runner_command.rb @@ -10,7 +10,7 @@ module Rails no_commands do def help super - puts self.class.desc + say self.class.desc end end @@ -39,11 +39,11 @@ module Rails else begin eval(code_or_file, TOPLEVEL_BINDING, __FILE__, __LINE__) - rescue SyntaxError, NameError => error - $stderr.puts "Please specify a valid ruby command or the path of a script to run." - $stderr.puts "Run '#{self.class.executable} -h' for help." - $stderr.puts - $stderr.puts error + rescue SyntaxError, NameError => e + error "Please specify a valid ruby command or the path of a script to run." + error "Run '#{self.class.executable} -h' for help." + error "" + error e exit 1 end end 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/engine.rb b/railties/lib/rails/engine.rb index 6a13a84108..901934826b 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -403,6 +403,12 @@ module Rails define_method(:railtie_helpers_paths) { railtie.helpers_paths } end + unless mod.respond_to?(:railtie_include_helpers) + define_method(:railtie_include_helpers) { |klass, include_path_helpers| + railtie.routes.include_helpers(klass, include_path_helpers) + } + end + unless mod.respond_to?(:railtie_routes_url_helpers) define_method(:railtie_routes_url_helpers) { |include_path_helpers = true| railtie.routes.url_helpers(include_path_helpers) } end @@ -473,9 +479,13 @@ module Rails # files inside eager_load paths. def eager_load! config.eager_load_paths.each do |load_path| - matcher = /\A#{Regexp.escape(load_path.to_s)}\/(.*)\.rb\Z/ - Dir.glob("#{load_path}/**/*.rb").sort.each do |file| - require_dependency file.sub(matcher, '\1') + if File.file?(load_path) + require_dependency load_path + else + matcher = /\A#{Regexp.escape(load_path.to_s)}\/(.*)\.rb\Z/ + Dir.glob("#{load_path}/**/*.rb").sort.each do |file| + require_dependency file.sub(matcher, '\1') + end end end end diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 6bf0406b21..7595272c03 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -38,6 +38,7 @@ module Rails @paths ||= begin paths = Rails::Paths::Root.new(@root) + paths.add "config/routes.rb", eager_load: true paths.add "app", eager_load: true, glob: "{*,*/concerns}" paths.add "app/assets", glob: "*" paths.add "app/controllers", eager_load: true @@ -55,7 +56,6 @@ module Rails paths.add "config/environments", glob: "#{Rails.env}.rb" paths.add "config/initializers", glob: "**/*.rb" paths.add "config/locales", glob: "*.{rb,yml}" - paths.add "config/routes.rb" paths.add "db" paths.add "db/migrate" 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/actions.rb b/railties/lib/rails/generators/actions.rb index ae395708cb..78d2471890 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -7,7 +7,7 @@ module Rails module Actions def initialize(*) # :nodoc: super - @in_group = nil + @indentation = 0 @after_bundle_callbacks = [] end @@ -36,13 +36,11 @@ module Rails log :gemfile, message - options.each do |option, value| - parts << "#{option}: #{quote(value)}" - end + parts << quote(options) unless options.empty? in_root do str = "gem #{parts.join(", ")}" - str = " " + str if @in_group + str = indentation + str str = "\n" + str append_file "Gemfile", str, verbose: false end @@ -54,17 +52,29 @@ module Rails # gem "rspec-rails" # end def gem_group(*names, &block) - name = names.map(&:inspect).join(", ") - log :gemfile, "group #{name}" + options = names.extract_options! + str = names.map(&:inspect) + str << quote(options) unless options.empty? + str = str.join(", ") + log :gemfile, "group #{str}" in_root do - append_file "Gemfile", "\ngroup #{name} do", force: true + append_file "Gemfile", "\ngroup #{str} do", force: true + with_indentation(&block) + append_file "Gemfile", "\nend\n", force: true + end + end - @in_group = true - instance_eval(&block) - @in_group = false + def github(repo, options = {}, &block) + str = [quote(repo)] + str << quote(options) unless options.empty? + str = str.join(", ") + log :github, "github #{str}" - append_file "Gemfile", "\nend\n", force: true + in_root do + append_file "Gemfile", "\n#{indentation}github #{str} do", force: true + with_indentation(&block) + append_file "Gemfile", "\n#{indentation}end", force: true end end @@ -83,9 +93,7 @@ module Rails in_root do if block append_file "Gemfile", "\nsource #{quote(source)} do", force: true - @in_group = true - instance_eval(&block) - @in_group = false + with_indentation(&block) append_file "Gemfile", "\nend\n", force: true else prepend_file "Gemfile", "source #{quote(source)}\n", verbose: false @@ -315,6 +323,11 @@ module Rails # Surround string with single quotes if there is no quotes. # Otherwise fall back to double quotes def quote(value) # :doc: + if value.respond_to? :each_pair + return value.map do |k, v| + "#{k}: #{quote(v)}" + end.join(", ") + end return value.inspect unless value.is_a? String if value.include?("'") @@ -334,6 +347,19 @@ module Rails "#{value.strip.indent(amount)}\n" end end + + # Indent the +Gemfile+ to the depth of @indentation + def indentation # :doc: + " " * @indentation + end + + # Manage +Gemfile+ indentation for a DSL action block + def with_indentation(&block) # :doc: + @indentation += 1 + instance_eval(&block) + ensure + @indentation -= 1 + end end end end diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 985e9ab263..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, @@ -299,7 +296,7 @@ module Rails def gem_for_database # %w( mysql postgresql sqlite3 oracle frontbase ibm_db sqlserver jdbcmysql jdbcsqlite3 jdbcpostgresql ) case options[:database] - when "mysql" then ["mysql2", [">= 0.4.4", "< 0.6.0"]] + when "mysql" then ["mysql2", [">= 0.4.4"]] when "postgresql" then ["pg", [">= 0.18", "< 2.0"]] when "oracle" then ["activerecord-oracle_enhanced-adapter", nil] when "frontbase" then ["ruby-frontbase", nil] @@ -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,15 @@ 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 + + def generate_bundler_binstub + if bundle_install? + bundle_command("binstubs bundler") end end diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb index f7fd30a5fb..3f20f5a718 100644 --- a/railties/lib/rails/generators/generated_attribute.rb +++ b/railties/lib/rails/generators/generated_attribute.rb @@ -153,7 +153,7 @@ module Rails end def inject_options - "".dup.tap { |s| options_for_migration.each { |k, v| s << ", #{k}: #{v.inspect}" } } + (+"").tap { |s| options_for_migration.each { |k, v| s << ", #{k}: #{v.inspect}" } } end def inject_index_options 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/model_helpers.rb b/railties/lib/rails/generators/model_helpers.rb index 50078404b3..3676432d5c 100644 --- a/railties/lib/rails/generators/model_helpers.rb +++ b/railties/lib/rails/generators/model_helpers.rb @@ -7,6 +7,10 @@ module Rails module ModelHelpers # :nodoc: PLURAL_MODEL_NAME_WARN_MESSAGE = "[WARNING] The model name '%s' was recognized as a plural, using the singular '%s' instead. " \ "Override with --force-plural or setup custom inflection rules for this noun before running the generator." + IRREGULAR_MODEL_NAME_WARN_MESSAGE = <<~WARNING + [WARNING] Rails cannot recover singular form from its plural form '%s'. + Please setup custom inflection rules for this noun before running the generator in config/initializers/inflections.rb. + WARNING mattr_accessor :skip_warn def self.included(base) #:nodoc: @@ -19,11 +23,14 @@ module Rails singular = name.singularize unless ModelHelpers.skip_warn say PLURAL_MODEL_NAME_WARN_MESSAGE % [name, singular] - ModelHelpers.skip_warn = true end name.replace singular assign_names!(name) end + if name.singularize != name.pluralize.singularize && ! ModelHelpers.skip_warn + say IRREGULAR_MODEL_NAME_WARN_MESSAGE % [name.pluralize] + end + ModelHelpers.skip_warn = true end end end diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 83c5c9f297..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 @@ -469,7 +469,8 @@ module Rails end public_task :apply_rails_template, :run_bundle - public_task :run_webpack, :generate_spring_binstubs + public_task :generate_bundler_binstub, :generate_spring_binstubs + public_task :run_webpack def run_after_bundle_callbacks @after_bundle_callbacks.each(&:call) 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/bin/bundle.tt b/railties/lib/rails/generators/rails/app/templates/bin/bundle.tt deleted file mode 100644 index a84f0afe47..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/bin/bundle.tt +++ /dev/null @@ -1,2 +0,0 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -load Gem.bin_path('bundler', 'bundle') diff --git a/railties/lib/rails/generators/rails/app/templates/config/cable.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/cable.yml.tt index 8e53156c71..f69dc91b92 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/cable.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/cable.yml.tt @@ -2,7 +2,7 @@ development: adapter: async test: - adapter: async + adapter: test production: adapter: redis diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt index 97f9a92ff3..f39593372c 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt @@ -1,4 +1,4 @@ -# MySQL. Versions 5.1.10 and up are supported. +# MySQL. Versions 5.5.8 and up are supported. # # Install the MySQL driver: # gem install activerecord-jdbcmysql-adapter diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt index 1dc508b14f..5860563908 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt @@ -1,4 +1,4 @@ -# MySQL. Versions 5.1.10 and up are supported. +# MySQL. Versions 5.5.8 and up are supported. # # Install the MySQL driver # gem install mysql2 @@ -11,7 +11,6 @@ # default: &default adapter: mysql2 - encoding: utf8 pool: <%%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: 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 d646694477..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. @@ -69,7 +64,7 @@ Rails.application.configure do # Use a real queuing backend for Active Job (and separate queues per environment). # config.active_job.queue_adapter = :resque - # config.active_job.queue_name_prefix = "<%= app_name %>_#{Rails.env}" + # config.active_job.queue_name_prefix = "<%= app_name %>_production" <%- unless options.skip_action_mailer? -%> config.action_mailer.perform_caching = false diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt index 82f2a8aebe..223aa56187 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt @@ -21,6 +21,7 @@ Rails.application.configure do # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false + config.cache_store = :null_store # Raise exceptions instead of rendering exception templates. config.action_dispatch.show_exceptions = false diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt index 179b97de4a..54eb0cb1d2 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt @@ -8,3 +8,10 @@ # Don't force requests from old versions of IE to be UTF-8 encoded # Rails.application.config.action_view.default_enforce_utf8 = false + +# Embed purpose and expiry metadata inside signed and encrypted +# cookies for increased security. +# +# This option is not backwards compatible with earlier Rails versions. +# It's best enabled when your entire app is migrated and stable on 6.0. +# Rails.application.config.action_dispatch.use_cookies_with_metadata = true 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/rails/plugin/templates/%name%.gemspec.tt b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt index 9a8c4bf098..405642c850 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt @@ -4,21 +4,30 @@ $:.push File.expand_path("lib", __dir__) require "<%= namespaced_name %>/version" # Describe your gem and declare its dependencies: -Gem::Specification.new do |s| - s.name = "<%= name %>" - s.version = <%= camelized_modules %>::VERSION - s.authors = ["<%= author %>"] - s.email = ["<%= email %>"] - s.homepage = "TODO" - s.summary = "TODO: Summary of <%= camelized_modules %>." - s.description = "TODO: Description of <%= camelized_modules %>." - s.license = "MIT" +Gem::Specification.new do |spec| + spec.name = "<%= name %>" + spec.version = <%= camelized_modules %>::VERSION + spec.authors = ["<%= author %>"] + spec.email = ["<%= email %>"] + spec.homepage = "TODO" + spec.summary = "TODO: Summary of <%= camelized_modules %>." + spec.description = "TODO: Description of <%= camelized_modules %>." + spec.license = "MIT" - s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] + # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' + # to allow pushing to a single host or delete this section to allow pushing to any host. + if spec.respond_to?(:metadata) + spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" + else + raise "RubyGems 2.0 or newer is required to protect against " \ + "public gem pushes." + end - <%= '# ' if options.dev? || options.edge? -%>s.add_dependency "rails", "<%= Array(rails_version_specifier).join('", "') %>" + spec.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] + + <%= '# ' if options.dev? || options.edge? -%>spec.add_dependency "rails", "<%= Array(rails_version_specifier).join('", "') %>" <% unless options[:skip_active_record] -%> - s.add_development_dependency "<%= gem_for_database[0] %>" + spec.add_development_dependency "<%= gem_for_database[0] %>" <% end -%> end diff --git a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt index 755d19ef5d..4f7a8d3d6e 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt @@ -10,8 +10,7 @@ ActiveRecord::Migrator.migrations_paths << File.expand_path('../db/migrate', __d <% end -%> require "rails/test_help" -# Filter out Minitest backtrace while allowing backtrace from other libraries -# to be shown. +# Filter out the backtrace from minitest while preserving the one from other libraries. Minitest.backtrace_filter = Minitest::BacktraceFilter.new <% unless engine? -%> diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt b/railties/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt index f83f5a5c62..15bd7956b6 100644 --- a/railties/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +++ b/railties/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt @@ -16,7 +16,7 @@ class <%= class_name.pluralize %>Test < ApplicationSystemTestCase click_on "New <%= class_name.titleize %>" <%- attributes_hash.each do |attr, value| -%> - fill_in "<%= attr.humanize.titleize %>", with: <%= value %> + fill_in "<%= attr.humanize %>", with: <%= value %> <%- end -%> click_on "Create <%= human_name %>" @@ -29,7 +29,7 @@ class <%= class_name.pluralize %>Test < ApplicationSystemTestCase click_on "Edit", match: :first <%- attributes_hash.each do |attr, value| -%> - fill_in "<%= attr.humanize.titleize %>", with: <%= value %> + fill_in "<%= attr.humanize %>", with: <%= value %> <%- end -%> click_on "Update <%= human_name %>" 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/info.rb b/railties/lib/rails/info.rb index d5c9973c6b..3df36efc4c 100644 --- a/railties/lib/rails/info.rb +++ b/railties/lib/rails/info.rb @@ -41,7 +41,7 @@ module Rails alias inspect to_s def to_html - "<table>".dup.tap do |table| + (+"<table>").tap do |table| properties.each do |(name, value)| table << %(<tr><td class="name">#{CGI.escapeHTML(name.to_s)}</td>) formatted_value = if value.kind_of?(Array) diff --git a/railties/lib/rails/mailers_controller.rb b/railties/lib/rails/mailers_controller.rb index 0b0e802358..e2d36d7654 100644 --- a/railties/lib/rails/mailers_controller.rb +++ b/railties/lib/rails/mailers_controller.rb @@ -10,6 +10,8 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc: helper_method :part_query, :locale_query + content_security_policy(false) + def index @previews = ActionMailer::Preview.all @page_title = "Mailer Previews" diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index 2d66a4dc7d..d7170e6282 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -50,7 +50,7 @@ module Rails # If +options+ has a flag <tt>:tag</tt> the tag is shown as in the example above. # Otherwise the string contains just line and text. def to_s(options = {}) - s = "[#{line.to_s.rjust(options[:indent])}] ".dup + s = +"[#{line.to_s.rjust(options[:indent])}] " s << "[#{tag}] " if options[:tag] s << text end diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb index 56f2eba312..2f644a20c9 100644 --- a/railties/lib/rails/tasks.rb +++ b/railties/lib/rails/tasks.rb @@ -12,6 +12,7 @@ require "rake" middleware misc restart + routes tmp yarn ).tap { |arr| diff --git a/railties/lib/rails/tasks/annotations.rake b/railties/lib/rails/tasks/annotations.rake index 65af778a15..3a78de418a 100644 --- a/railties/lib/rails/tasks/annotations.rake +++ b/railties/lib/rails/tasks/annotations.rake @@ -2,20 +2,20 @@ require "rails/source_annotation_extractor" -task :notes do +task notes: :environment do Rails::SourceAnnotationExtractor::Annotation.notes_task_deprecation_warning Rails::Command.invoke :notes end namespace :notes do ["OPTIMIZE", "FIXME", "TODO"].each do |annotation| - task annotation.downcase.intern do + task annotation.downcase.intern => :environment do Rails::SourceAnnotationExtractor::Annotation.notes_task_deprecation_warning Rails::Command.invoke :notes, ["--annotations", annotation] end end - task :custom do + task custom: :environment do Rails::SourceAnnotationExtractor::Annotation.notes_task_deprecation_warning Rails::Command.invoke :notes, ["--annotations", ENV["ANNOTATION"]] end diff --git a/railties/lib/rails/tasks/dev.rake b/railties/lib/rails/tasks/dev.rake index 5aea6f7dc5..716fb6a331 100644 --- a/railties/lib/rails/tasks/dev.rake +++ b/railties/lib/rails/tasks/dev.rake @@ -1,10 +1,11 @@ # frozen_string_literal: true -require "rails/dev_caching" +require "rails/command" +require "active_support/deprecation" namespace :dev do - desc "Toggle development mode caching on/off" - task :cache do - Rails::DevCaching.enable_by_file + task cache: :environment do + ActiveSupport::Deprecation.warn("Using `bin/rake dev:cache` is deprecated and will be removed in Rails 6.1. Use `bin/rails dev:cache` instead.\n") + Rails::Command.invoke "dev:cache" end end diff --git a/railties/lib/rails/tasks/initializers.rake b/railties/lib/rails/tasks/initializers.rake index ae85cb0f86..f108517d1d 100644 --- a/railties/lib/rails/tasks/initializers.rake +++ b/railties/lib/rails/tasks/initializers.rake @@ -1,8 +1,9 @@ # frozen_string_literal: true -desc "Print out all defined initializers in the order they are invoked by Rails." +require "rails/command" +require "active_support/deprecation" + task initializers: :environment do - Rails.application.initializers.tsort_each do |initializer| - puts "#{initializer.context_class}.#{initializer.name}" - end + ActiveSupport::Deprecation.warn("Using `bin/rake initializers` is deprecated and will be removed in Rails 6.1. Use `bin/rails initializers` instead.\n") + Rails::Command.invoke "initializers" end diff --git a/railties/lib/rails/tasks/routes.rake b/railties/lib/rails/tasks/routes.rake new file mode 100644 index 0000000000..21ce900a8c --- /dev/null +++ b/railties/lib/rails/tasks/routes.rake @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require "rails/command" +require "active_support/deprecation" + +task routes: :environment do + ActiveSupport::Deprecation.warn("Using `bin/rake routes` is deprecated and will be removed in Rails 6.1. Use `bin/rails routes` instead.\n") + Rails::Command.invoke "routes" +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/lib/rails/tasks/yarn.rake b/railties/lib/rails/tasks/yarn.rake index cf45a392e8..4fb8586b69 100644 --- a/railties/lib/rails/tasks/yarn.rake +++ b/railties/lib/rails/tasks/yarn.rake @@ -9,7 +9,7 @@ namespace :yarn do rails_env = ENV["RAILS_ENV"] valid_node_envs.include?(rails_env) ? rails_env : "production" end - system({ "NODE_ENV" => node_env }, "./bin/yarn install --no-progress --frozen-lockfile") + system({ "NODE_ENV" => node_env }, "#{Rails.root}/bin/yarn install --no-progress --frozen-lockfile") end end diff --git a/railties/lib/rails/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb index 2fa7573bdf..d38952bb30 100644 --- a/railties/lib/rails/test_unit/runner.rb +++ b/railties/lib/rails/test_unit/runner.rb @@ -12,8 +12,8 @@ module Rails class << self def attach_before_load_options(opts) - opts.on("--warnings", "-w", "Run with Ruby warnings enabled") {} - opts.on("-e", "--environment ENV", "Run tests in the ENV environment") {} + opts.on("--warnings", "-w", "Run with Ruby warnings enabled") { } + opts.on("-e", "--environment ENV", "Run tests in the ENV environment") { } end def parse_options(argv) @@ -87,7 +87,7 @@ module Rails @filters = [ @named_filter, *derive_line_filters(patterns) ].compact end - # Minitest uses === to find matching filters. + # minitest uses === to find matching filters. def ===(method) @filters.any? { |filter| filter === method } end @@ -96,7 +96,7 @@ module Rails def derive_named_filter(filter) if filter.respond_to?(:named_filter) filter.named_filter - elsif filter =~ %r%/(.*)/% # Regexp filtering copied from Minitest. + elsif filter =~ %r%/(.*)/% # Regexp filtering copied from minitest. Regexp.new $1 elsif filter.is_a?(String) filter |