aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG.md55
-rw-r--r--railties/Rakefile3
-rw-r--r--railties/lib/rails/application.rb6
-rw-r--r--railties/lib/rails/application/configuration.rb26
-rw-r--r--railties/lib/rails/backtrace_cleaner.rb8
-rw-r--r--railties/lib/rails/commands/credentials/USAGE9
-rw-r--r--railties/lib/rails/commands/credentials/credentials_command.rb63
-rw-r--r--railties/lib/rails/commands/dbconsole/dbconsole_command.rb2
-rw-r--r--railties/lib/rails/commands/server/server_command.rb2
-rw-r--r--railties/lib/rails/generators.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb58
-rw-r--r--railties/lib/rails/generators/generated_attribute.rb2
-rw-r--r--railties/lib/rails/generators/js/assets/assets_generator.rb15
-rw-r--r--railties/lib/rails/generators/js/assets/templates/javascript.js2
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb8
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt22
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js (renamed from railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.js.tt)11
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt21
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt8
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt7
-rw-r--r--railties/lib/rails/generators/rails/app/templates/package.json.tt8
-rw-r--r--railties/lib/rails/generators/rails/assets/USAGE5
-rw-r--r--railties/lib/rails/generators/rails/assets/assets_generator.rb8
-rw-r--r--railties/lib/rails/generators/rails/assets/templates/javascript.js2
-rw-r--r--railties/lib/rails/generators/rails/plugin/plugin_generator.rb2
-rw-r--r--railties/lib/rails/generators/testing/behaviour.rb3
-rw-r--r--railties/lib/rails/info.rb2
-rw-r--r--railties/lib/rails/railtie.rb2
-rw-r--r--railties/lib/rails/source_annotation_extractor.rb2
-rw-r--r--railties/lib/rails/tasks/statistics.rake1
-rw-r--r--railties/lib/rails/test_unit/runner.rb4
-rw-r--r--railties/test/abstract_unit.rb18
-rw-r--r--railties/test/application/assets_test.rb20
-rw-r--r--railties/test/application/bin_setup_test.rb18
-rw-r--r--railties/test/application/configuration_test.rb59
-rw-r--r--railties/test/application/middleware_test.rb15
-rw-r--r--railties/test/application/rake/dbs_test.rb18
-rw-r--r--railties/test/application/rake_test.rb3
-rw-r--r--railties/test/commands/credentials_test.rb26
-rw-r--r--railties/test/console_helpers.rb2
-rw-r--r--railties/test/credentials_test.rb49
-rw-r--r--railties/test/engine/commands_test.rb3
-rw-r--r--railties/test/generators/actions_test.rb2
-rw-r--r--railties/test/generators/api_app_generator_test.rb1
-rw-r--r--railties/test/generators/app_generator_test.rb75
-rw-r--r--railties/test/generators/assets_generator_test.rb4
-rw-r--r--railties/test/generators/channel_generator_test.rb27
-rw-r--r--railties/test/generators/controller_generator_test.rb5
-rw-r--r--railties/test/generators/generators_test_helper.rb15
-rw-r--r--railties/test/generators/migration_generator_test.rb12
-rw-r--r--railties/test/generators/model_generator_test.rb11
-rw-r--r--railties/test/generators/plugin_generator_test.rb49
-rw-r--r--railties/test/generators/resource_generator_test.rb4
-rw-r--r--railties/test/generators/scaffold_generator_test.rb27
-rw-r--r--railties/test/generators/shared_generator_tests.rb29
-rw-r--r--railties/test/isolation/abstract_unit.rb21
-rw-r--r--railties/test/rack_logger_test.rb2
60 files changed, 521 insertions, 376 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index b916fda1cb..925dac7b3c 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,58 @@
+* 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
+ per database in their own directories.
+
+ ```
+ bin/rails g model Room capacity:integer --migrations-paths=db/kingston_migrate
+ invoke active_record
+ create db/kingston_migrate/20180830151055_create_rooms.rb
+ ```
+
+ Because rails scaffolding uses the model generator, you can
+ also specify migrations paths with the scaffold generator.
+
+ *Gannon McGibbon*
+
+* Raise an error when "recyclable cache keys" are being used by a cache store
+ that does not explicitly support it. Custom cache keys that do support this feature
+ can bypass this error by implementing the `supports_cache_versioning?` method on their
+ class and returning a truthy value.
+
+ *Richard Schneeman*
+
+* Support environment specific credentials file.
+
+ For `production` environment look first for `config/credentials/production.yml.enc` file that can be decrypted by
+ `ENV["RAILS_MASTER_KEY"]` or `config/credentials/production.key` master key.
+ Edit given environment credentials file by command `rails credentials:edit --environment production`.
+ Default paths can be overwritten by setting `config.credentials.content_path` and `config.credentials.key_path`.
+
+ *Wojciech Wnętrzak*
+
* Make `ActiveSupport::Cache::NullStore` the default cache store in the test environment.
*Michael C. Nelson*
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/application.rb b/railties/lib/rails/application.rb
index 26ed195dcc..656786246d 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -438,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 f4cbd2b9d0..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)
@@ -273,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 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/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/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/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/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/jobs/application_job.rb.tt b/railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt
index a009ace51c..d394c3d106 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt
@@ -1,2 +1,7 @@
class ApplicationJob < ActiveJob::Base
+ # Automatically retry jobs that encountered a deadlock
+ # retry_on ActiveRecord::Deadlocked
+
+ # Most jobs are safe to ignore if the underlying records are no longer available
+ # discard_on ActiveJob::DeserializationError
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/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/railtie.rb b/railties/lib/rails/railtie.rb
index 88dd932370..a67b90e285 100644
--- a/railties/lib/rails/railtie.rb
+++ b/railties/lib/rails/railtie.rb
@@ -224,7 +224,7 @@ module Rails
end
def railtie_namespace #:nodoc:
- @railtie_namespace ||= self.class.parents.detect { |n| n.respond_to?(:railtie_namespace) }
+ @railtie_namespace ||= self.class.module_parents.detect { |n| n.respond_to?(:railtie_namespace) }
end
protected
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/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/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb
index 6332a9d422..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)
diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb
index b42f37d6b9..9c866263f0 100644
--- a/railties/test/abstract_unit.rb
+++ b/railties/test/abstract_unit.rb
@@ -21,12 +21,14 @@ end
class ActiveSupport::TestCase
include ActiveSupport::Testing::Stream
- # Skips the current run on Rubinius using Minitest::Assertions#skip
- private def rubinius_skip(message = "")
- skip message if RUBY_ENGINE == "rbx"
- end
- # Skips the current run on JRuby using Minitest::Assertions#skip
- private def jruby_skip(message = "")
- skip message if defined?(JRUBY_VERSION)
- end
+ private
+ # Skips the current run on Rubinius using Minitest::Assertions#skip
+ def rubinius_skip(message = "")
+ skip message if RUBY_ENGINE == "rbx"
+ end
+
+ # Skips the current run on JRuby using Minitest::Assertions#skip
+ def jruby_skip(message = "")
+ skip message if defined?(JRUBY_VERSION)
+ end
end
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/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb
index 54934dbe24..d02100d94c 100644
--- a/railties/test/application/bin_setup_test.rb
+++ b/railties/test/application/bin_setup_test.rb
@@ -43,18 +43,20 @@ module ApplicationTests
# Ignore line that's only output by Bundler < 1.14
output.sub!(/^Resolving dependencies\.\.\.\n/, "")
+ # Suppress Bundler platform warnings from output
+ output.gsub!(/^The dependency .* will be unused .*\.\n/, "")
- assert_equal(<<-OUTPUT, output)
-== Installing dependencies ==
-The Gemfile's dependencies are satisfied
+ assert_equal(<<~OUTPUT, output)
+ == Installing dependencies ==
+ The Gemfile's dependencies are satisfied
-== Preparing database ==
-Created database 'db/development.sqlite3'
-Created database 'db/test.sqlite3'
+ == Preparing database ==
+ Created database 'db/development.sqlite3'
+ Created database 'db/test.sqlite3'
-== Removing old logs and tempfiles ==
+ == Removing old logs and tempfiles ==
-== Restarting application server ==
+ == Restarting application server ==
OUTPUT
end
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 11cd6dd1e6..9b01d42b1e 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -124,6 +124,18 @@ module ApplicationTests
assert_equal "MyLogger", Rails.application.config.logger.class.name
end
+ test "raises an error if cache does not support recyclable cache keys" do
+ build_app(initializers: true)
+ add_to_env_config "production", "config.cache_store = Class.new {}.new"
+ add_to_env_config "production", "config.active_record.cache_versioning = true"
+
+ error = assert_raise(RuntimeError) do
+ app "production"
+ end
+
+ assert_match(/You're using a cache/, error.message)
+ end
+
test "a renders exception on pending migration" do
add_to_config <<-RUBY
config.active_record.migration_error = :page_load
@@ -298,6 +310,53 @@ module ApplicationTests
assert_equal %w(noop_email).to_set, PostsMailer.instance_variable_get(:@action_methods)
end
+ test "does not eager load attribute methods in development" do
+ app_file "app/models/post.rb", <<-RUBY
+ class Post < ActiveRecord::Base
+ end
+ RUBY
+
+ app_file "config/initializers/active_record.rb", <<-RUBY
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
+ ActiveRecord::Migration.verbose = false
+ ActiveRecord::Schema.define(version: 1) do
+ create_table :posts do |t|
+ t.string :title
+ end
+ end
+ RUBY
+
+ app "development"
+
+ assert_not_includes Post.instance_methods, :title
+ end
+
+ test "eager loads attribute methods in production" do
+ app_file "app/models/post.rb", <<-RUBY
+ class Post < ActiveRecord::Base
+ end
+ RUBY
+
+ app_file "config/initializers/active_record.rb", <<-RUBY
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
+ ActiveRecord::Migration.verbose = false
+ ActiveRecord::Schema.define(version: 1) do
+ create_table :posts do |t|
+ t.string :title
+ end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ config.eager_load = true
+ config.cache_classes = true
+ RUBY
+
+ app "production"
+
+ assert_includes Post.instance_methods, :title
+ end
+
test "initialize an eager loaded, cache classes app" do
add_to_config <<-RUBY
config.eager_load = true
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/dbs_test.rb b/railties/test/application/rake/dbs_test.rb
index b1038ba5d6..039987ac8c 100644
--- a/railties/test/application/rake/dbs_test.rb
+++ b/railties/test/application/rake/dbs_test.rb
@@ -26,12 +26,13 @@ module ApplicationTests
FileUtils.rm_rf("#{app_path}/config/database.yml")
end
- def db_create_and_drop(expected_database)
+ def db_create_and_drop(expected_database, environment_loaded: true)
Dir.chdir(app_path) do
output = rails("db:create")
assert_match(/Created database/, output)
assert File.exist?(expected_database)
- assert_equal expected_database, ActiveRecord::Base.connection_config[:database]
+ yield if block_given?
+ assert_equal expected_database, ActiveRecord::Base.connection_config[:database] if environment_loaded
output = rails("db:drop")
assert_match(/Dropped database/, output)
assert_not File.exist?(expected_database)
@@ -62,11 +63,16 @@ module ApplicationTests
end
RUBY
- app "development"
-
- assert_equal true, Rails.application.config.read_encrypted_secrets
+ app_file "lib/tasks/check_env.rake", <<-RUBY
+ Rake::Task["db:create"].enhance do
+ File.write("tmp/config_value", Rails.application.config.read_encrypted_secrets)
+ end
+ RUBY
- db_create_and_drop "db/development.sqlite3"
+ db_create_and_drop("db/development.sqlite3", environment_loaded: false) do
+ assert File.exist?("tmp/config_value")
+ assert_equal "true", File.read("tmp/config_value")
+ end
end
def with_database_existing
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/commands/credentials_test.rb b/railties/test/commands/credentials_test.rb
index 5b8b9e4eda..7842b0db61 100644
--- a/railties/test/commands/credentials_test.rb
+++ b/railties/test/commands/credentials_test.rb
@@ -55,6 +55,14 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
end
end
+ test "edit command modifies file specified by environment option" do
+ assert_match(/access_key_id: 123/, run_edit_command(environment: "production"))
+ Dir.chdir(app_path) do
+ assert File.exist?("config/credentials/production.key")
+ assert File.exist?("config/credentials/production.yml.enc")
+ end
+ end
+
test "show credentials" do
assert_match(/access_key_id: 123/, run_show_command)
end
@@ -70,17 +78,25 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
remove_file "config/master.key"
add_to_config "config.require_master_key = false"
- assert_match(/Missing master key to decrypt credentials/, run_show_command)
+ assert_match(/Missing 'config\/master\.key' to decrypt credentials/, run_show_command)
+ end
+
+ test "show command displays content specified by environment option" do
+ run_edit_command(environment: "production")
+
+ assert_match(/access_key_id: 123/, run_show_command(environment: "production"))
end
private
- def run_edit_command(editor: "cat")
+ def run_edit_command(editor: "cat", environment: nil, **options)
switch_env("EDITOR", editor) do
- rails "credentials:edit"
+ args = environment ? ["--environment", environment] : []
+ rails "credentials:edit", args, **options
end
end
- def run_show_command(**options)
- rails "credentials:show", **options
+ def run_show_command(environment: nil, **options)
+ args = environment ? ["--environment", environment] : []
+ rails "credentials:show", args, **options
end
end
diff --git a/railties/test/console_helpers.rb b/railties/test/console_helpers.rb
index 8350fce5ee..67f55fdc45 100644
--- a/railties/test/console_helpers.rb
+++ b/railties/test/console_helpers.rb
@@ -9,7 +9,7 @@ module ConsoleHelpers
def assert_output(expected, io, timeout = 10)
timeout = Time.now + timeout
- output = "".dup
+ output = +""
until output.include?(expected) || Time.now > timeout
if IO.select([io], [], [], 0.1)
output << io.read(1)
diff --git a/railties/test/credentials_test.rb b/railties/test/credentials_test.rb
new file mode 100644
index 0000000000..03370e0fc7
--- /dev/null
+++ b/railties/test/credentials_test.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+
+class Rails::CredentialsTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ setup :build_app
+ teardown :teardown_app
+
+ test "reads credentials from environment specific path" do
+ with_credentials do |content, key|
+ Dir.chdir(app_path) do
+ Dir.mkdir("config/credentials")
+ File.write("config/credentials/production.yml.enc", content)
+ File.write("config/credentials/production.key", key)
+ end
+
+ app("production")
+
+ assert_equal "revealed", Rails.application.credentials.mystery
+ end
+ end
+
+ test "reads credentials from customized path and key" do
+ with_credentials do |content, key|
+ Dir.chdir(app_path) do
+ Dir.mkdir("config/credentials")
+ File.write("config/credentials/staging.yml.enc", content)
+ File.write("config/credentials/staging.key", key)
+ end
+
+ add_to_env_config("production", "config.credentials.content_path = config.root.join('config/credentials/staging.yml.enc')")
+ add_to_env_config("production", "config.credentials.key_path = config.root.join('config/credentials/staging.key')")
+ app("production")
+
+ assert_equal "revealed", Rails.application.credentials.mystery
+ end
+ end
+
+ private
+ def with_credentials
+ key = "2117e775dc2024d4f49ddf3aeb585919"
+ # secret_key_base: secret
+ # mystery: revealed
+ content = "vgvKu4MBepIgZ5VHQMMPwnQNsLlWD9LKmJHu3UA/8yj6x+3fNhz3DwL9brX7UA==--qLdxHP6e34xeTAiI--nrcAsleXuo9NqiEuhntAhw=="
+ yield(content, key)
+ end
+end
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 14cdd8b5c9..cd6bdd11c0 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
@@ -216,12 +215,13 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_new_application_load_defaults
app_root = File.join(destination_root, "myfirstapp")
run_generator [app_root]
+
output = nil
assert_file "#{app_root}/config/application.rb", /\s+config\.load_defaults #{Rails::VERSION::STRING.to_f}/
Dir.chdir(app_root) do
- output = `./bin/rails r "puts Rails.application.config.assets.unknown_asset_fallback"`
+ output = `SKIP_REQUIRE_WEBPACKER=true ./bin/rails r "puts Rails.application.config.assets.unknown_asset_fallback"`
end
assert_equal "false\n", output
@@ -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,49 +600,15 @@ 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"]
- assert_no_file "app/assets/javascripts"
+ assert_no_file "app/javascript"
assert_file "app/views/layouts/application.html.erb" do |contents|
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"
@@ -964,7 +931,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_after_bundle_callback
path = "http://example.org/rails_template"
- template = %{ after_bundle { run 'echo ran after_bundle' } }.dup
+ template = +%{ after_bundle { run 'echo ran after_bundle' } }
template.instance_eval "def read; self; end" # Make the string respond to read
check_open = -> *args do
@@ -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..1cb8465539 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
+ def test_consumer_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
@@ -70,11 +72,12 @@ class ChannelGeneratorTest < Rails::Generators::TestCase
run_generator ["chat"], behavior: :revoke
assert_no_file "app/channels/chat_channel.rb"
- assert_no_file "app/assets/javascripts/channels/chat.js"
+ assert_no_file "app/javascript/channels/chat_channel.js"
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
@@ -83,7 +86,7 @@ class ChannelGeneratorTest < Rails::Generators::TestCase
assert_no_file "app/channels/chat_channel_channel.rb"
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_no_file "app/javascript/channels/chat_channel_channel.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..8786756c68 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
@@ -132,9 +130,6 @@ class ControllerGeneratorTest < Rails::Generators::TestCase
assert_no_file "app/helpers/account_controller_helper.rb"
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"
end
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 7febdfae96..b06db6dd8a 100644
--- a/railties/test/generators/model_generator_test.rb
+++ b/railties/test/generators/model_generator_test.rb
@@ -392,6 +392,17 @@ class ModelGeneratorTest < Rails::Generators::TestCase
end
end
+ 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
+
def test_required_belongs_to_adds_required_association
run_generator ["account", "supplier:references{required}"]
diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb
index 20acd23329..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
@@ -737,7 +714,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase
def test_after_bundle_callback
path = "http://example.org/rails_template"
- template = %{ after_bundle { run "echo ran after_bundle" } }.dup
+ template = +%{ after_bundle { run "echo ran after_bundle" } }
template.instance_eval "def read; self; end" # Make the string respond to read
check_open = -> *args do
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 e90834bc2b..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,6 +459,14 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_scaffold_generator_database
+ with_secondary_database_configuration do
+ run_generator ["posts", "--database=secondary"]
+
+ assert_migration "db/secondary_migrate/create_posts.rb"
+ end
+ end
+
def test_scaffold_generator_password_digest
run_generator ["user", "name", "password:digest"]
@@ -622,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
@@ -652,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 aa577e4234..b766fa1a71 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
@@ -83,7 +83,7 @@ module SharedGeneratorTests
def test_template_is_executed_when_supplied_an_https_path
path = "https://gist.github.com/josevalim/103208/raw/"
- template = %{ say "It works!" }.dup
+ template = +%{ say "It works!" }
template.instance_eval "def read; self; end" # Make the string respond to read
check_open = -> *args do
@@ -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|
@@ -303,8 +305,8 @@ module SharedGeneratorTests
run_generator [destination_root, "--skip-action-cable"]
assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']action_cable\/engine["']/
assert_no_file "#{application_path}/config/cable.yml"
- assert_no_file "#{application_path}/app/assets/javascripts/cable.js"
- assert_no_directory "#{application_path}/app/assets/javascripts/channels"
+ assert_no_file "#{application_path}/app/javascript/consumer.js"
+ assert_no_directory "#{application_path}/app/javascript/channels"
assert_no_directory "#{application_path}/app/channels"
assert_file "Gemfile" do |content|
assert_no_match(/redis/, 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 96d21b3ae2..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
@@ -71,7 +71,7 @@ module TestHelpers
end
def extract_body(response)
- "".dup.tap do |body|
+ (+"").tap do |body|
response[2].each { |chunk| body << chunk }
end
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"
diff --git a/railties/test/rack_logger_test.rb b/railties/test/rack_logger_test.rb
index 6e8f333e1d..ac37062e6d 100644
--- a/railties/test/rack_logger_test.rb
+++ b/railties/test/rack_logger_test.rb
@@ -56,7 +56,7 @@ module Rails
end
def test_notification
- logger = TestLogger.new {}
+ logger = TestLogger.new { }
assert_difference("subscriber.starts.length") do
assert_difference("subscriber.finishes.length") do