diff options
Diffstat (limited to 'railties/lib/rails')
20 files changed, 159 insertions, 81 deletions
diff --git a/railties/lib/rails/command/base.rb b/railties/lib/rails/command/base.rb index db20c71861..4f074df473 100644 --- a/railties/lib/rails/command/base.rb +++ b/railties/lib/rails/command/base.rb @@ -64,7 +64,7 @@ module Rails end def printing_commands - namespace.sub(/^rails:/, "") + namespaced_commands end def executable @@ -135,6 +135,12 @@ module Rails def command_root_namespace (namespace.split(":") - %w( rails )).first end + + def namespaced_commands + commands.keys.map do |key| + key == command_root_namespace ? key : "#{command_root_namespace}:#{key}" + end + end end def help diff --git a/railties/lib/rails/commands/destroy/destroy_command.rb b/railties/lib/rails/commands/destroy/destroy_command.rb index 5b552b2070..794673851d 100644 --- a/railties/lib/rails/commands/destroy/destroy_command.rb +++ b/railties/lib/rails/commands/destroy/destroy_command.rb @@ -3,8 +3,10 @@ require "rails/generators" module Rails module Command class DestroyCommand < Base # :nodoc: - def help - Rails::Generators.help self.class.command_name + no_commands do + def help + Rails::Generators.help self.class.command_name + end end def perform(*) @@ -12,9 +14,9 @@ module Rails return help unless generator require_application_and_environment! - Rails.application.load_generators + load_generators - Rails::Generators.invoke generator, args, behavior: :revoke, destination_root: Rails.root + Rails::Generators.invoke generator, args, behavior: :revoke, destination_root: Rails::Command.root end end end diff --git a/railties/lib/rails/commands/generate/generate_command.rb b/railties/lib/rails/commands/generate/generate_command.rb index aa8dab71b0..9dd7ad1012 100644 --- a/railties/lib/rails/commands/generate/generate_command.rb +++ b/railties/lib/rails/commands/generate/generate_command.rb @@ -3,8 +3,13 @@ require "rails/generators" module Rails module Command class GenerateCommand < Base # :nodoc: - def help - Rails::Generators.help self.class.command_name + no_commands do + def help + require_application_and_environment! + load_generators + + Rails::Generators.help self.class.command_name + end end def perform(*) diff --git a/railties/lib/rails/commands/new/new_command.rb b/railties/lib/rails/commands/new/new_command.rb index 74d1fa5021..207dd5d995 100644 --- a/railties/lib/rails/commands/new/new_command.rb +++ b/railties/lib/rails/commands/new/new_command.rb @@ -1,8 +1,10 @@ module Rails module Command class NewCommand < Base # :nodoc: - def help - Rails::Command.invoke :application, [ "--help" ] + no_commands do + def help + Rails::Command.invoke :application, [ "--help" ] + end end def perform(*) diff --git a/railties/lib/rails/commands/runner/runner_command.rb b/railties/lib/rails/commands/runner/runner_command.rb index 4989a7837d..056ad980b9 100644 --- a/railties/lib/rails/commands/runner/runner_command.rb +++ b/railties/lib/rails/commands/runner/runner_command.rb @@ -5,9 +5,11 @@ module Rails default: Rails::Command.environment.dup, desc: "The environment for the runner to operate under (test/development/production)" - def help - super - puts self.class.desc + no_commands do + def help + super + puts self.class.desc + end end def self.banner(*) diff --git a/railties/lib/rails/commands/secrets/USAGE b/railties/lib/rails/commands/secrets/USAGE index 4b7deb4e2a..96e322fe91 100644 --- a/railties/lib/rails/commands/secrets/USAGE +++ b/railties/lib/rails/commands/secrets/USAGE @@ -40,6 +40,14 @@ be encrypted. A `shared:` top level key is also supported such that any keys there is merged into the other environments. +Additionally, Rails won't read encrypted secrets out of the box even if you have +the key. Add this: + + config.read_encrypted_secrets = true + +to the environment you'd like to read encrypted secrets. `bin/rails secrets:setup` +inserts this into the production environment by default. + === Editing Secrets After `bin/rails secrets:setup`, run `bin/rails secrets:edit`. diff --git a/railties/lib/rails/commands/secrets/secrets_command.rb b/railties/lib/rails/commands/secrets/secrets_command.rb index 3ba8c0c85b..03a640bd65 100644 --- a/railties/lib/rails/commands/secrets/secrets_command.rb +++ b/railties/lib/rails/commands/secrets/secrets_command.rb @@ -4,10 +4,12 @@ require "rails/secrets" module Rails module Command class SecretsCommand < Rails::Command::Base # :nodoc: - def help - say "Usage:\n #{self.class.banner}" - say "" - say self.class.desc + no_commands do + def help + say "Usage:\n #{self.class.banner}" + say "" + say self.class.desc + end end def setup @@ -18,16 +20,27 @@ module Rails end def edit + if ENV["EDITOR"].to_s.empty? + say "No $EDITOR to open decrypted secrets in. Assign one like this:" + say "" + say %(EDITOR="mate --wait" bin/rails secrets:edit) + say "" + say "For editors that fork and exit immediately, it's important to pass a wait flag," + say "otherwise the secrets will be saved immediately with no chance to edit." + + return + end + require_application_and_environment! Rails::Secrets.read_for_editing do |tmp_path| - puts "Waiting for secrets file to be saved. Abort with Ctrl-C." + say "Waiting for secrets file to be saved. Abort with Ctrl-C." system("\$EDITOR #{tmp_path}") end - puts "New secrets encrypted and saved." + say "New secrets encrypted and saved." rescue Interrupt - puts "Aborted changing encrypted secrets: nothing saved." + say "Aborted changing encrypted secrets: nothing saved." rescue Rails::Secrets::MissingKeyError => error say error.message end diff --git a/railties/lib/rails/commands/server/server_command.rb b/railties/lib/rails/commands/server/server_command.rb index d58721f648..7e8c86fb49 100644 --- a/railties/lib/rails/commands/server/server_command.rb +++ b/railties/lib/rails/commands/server/server_command.rb @@ -99,8 +99,9 @@ module Rails class_option :port, aliases: "-p", type: :numeric, desc: "Runs Rails on the specified port.", banner: :port, default: 3000 - class_option :binding, aliases: "-b", type: :string, default: "localhost", - desc: "Binds Rails to the specified IP.", banner: :IP + class_option :binding, aliases: "-b", type: :string, + desc: "Binds Rails to the specified IP - defaults to 'localhost' in development and '0.0.0.0' in other environments'.", + banner: :IP class_option :config, aliases: "-c", type: :string, default: "config.ru", desc: "Uses a custom rackup configuration.", banner: :file class_option :daemon, aliases: "-d", type: :boolean, default: false, @@ -133,28 +134,64 @@ module Rails no_commands do def server_options { - server: @server, - log_stdout: @log_stdout, - Port: port, - Host: host, - DoNotReverseLookup: true, - config: options[:config], - environment: environment, - daemonize: options[:daemon], - pid: pid, - caching: options["dev-caching"], - restart_cmd: restart_command + user_supplied_options: user_supplied_options, + server: @server, + log_stdout: @log_stdout, + Port: port, + Host: host, + DoNotReverseLookup: true, + config: options[:config], + environment: environment, + daemonize: options[:daemon], + pid: pid, + caching: options["dev-caching"], + restart_cmd: restart_command } end end private + def user_supplied_options + @user_supplied_options ||= begin + # Convert incoming options array to a hash of flags + # ["-p", "3001", "-c", "foo"] # => {"-p" => true, "-c" => true} + user_flag = {} + @original_options.each_with_index { |command, i| user_flag[command] = true if i.even? } + + # Collect all options that the user has explicitly defined so we can + # differentiate them from defaults + user_supplied_options = [] + self.class.class_options.select do |key, option| + if option.aliases.any? { |name| user_flag[name] } || user_flag["--#{option.name}"] + name = option.name.to_sym + case name + when :port + name = :Port + when :binding + name = :Host + when :"dev-caching" + name = :caching + when :daemonize + name = :daemon + end + user_supplied_options << name + end + end + user_supplied_options << :Host if ENV["HOST"] + user_supplied_options << :Port if ENV["PORT"] + user_supplied_options.uniq + end + end + def port ENV.fetch("PORT", options[:port]).to_i end def host - ENV.fetch("HOST", options[:binding]) + unless (default_host = options[:binding]) + default_host = environment == "development" ? "localhost" : "0.0.0.0" + end + ENV.fetch("HOST", default_host) end def environment diff --git a/railties/lib/rails/commands/test/test_command.rb b/railties/lib/rails/commands/test/test_command.rb index 629fb5b425..65e16900ba 100644 --- a/railties/lib/rails/commands/test/test_command.rb +++ b/railties/lib/rails/commands/test/test_command.rb @@ -4,8 +4,10 @@ require "rails/test_unit/minitest_plugin" module Rails module Command class TestCommand < Base # :nodoc: - def help - perform # Hand over help printing to minitest. + no_commands do + def help + perform # Hand over help printing to minitest. + end end def perform(*) diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 3f1bf6a5bb..8ec805370b 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -63,7 +63,7 @@ module Rails stylesheet_engine: :css, scaffold_stylesheet: true, system_tests: nil, - test_framework: false, + test_framework: nil, template_engine: :erb } } diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 04f6341471..ebe8cfea60 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -280,7 +280,7 @@ module Rails case options[:database] when "mysql" then ["mysql2", [">= 0.3.18", "< 0.5"]] when "postgresql" then ["pg", ["~> 0.18"]] - when "oracle" then ["ruby-oci8", nil] + when "oracle" then ["activerecord-oracle_enhanced-adapter", nil] when "frontbase" then ["ruby-frontbase", nil] when "sqlserver" then ["activerecord-sqlserver-adapter", nil] when "jdbcmysql" then ["activerecord-jdbcmysql-adapter", nil] @@ -296,7 +296,6 @@ module Rails case options[:database] when "postgresql" then options[:database].replace "jdbcpostgresql" when "mysql" then options[:database].replace "jdbcmysql" - when "oracle" then options[:database].replace "jdbc" when "sqlite3" then options[:database].replace "jdbcsqlite3" end end @@ -322,7 +321,7 @@ module Rails return [] unless options[:webpack] comment = "Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker" - GemfileEntry.github "webpacker", "rails/webpacker", nil, comment + GemfileEntry.new "webpacker", nil, comment end def jbuilder_gemfile_entry diff --git a/railties/lib/rails/generators/erb.rb b/railties/lib/rails/generators/erb.rb index d5e326d6ee..97d9ab29d4 100644 --- a/railties/lib/rails/generators/erb.rb +++ b/railties/lib/rails/generators/erb.rb @@ -17,8 +17,8 @@ module Erb # :nodoc: :erb end - def filename_with_extensions(name, format = self.format) - [name, format, handler].compact.join(".") + def filename_with_extensions(name, file_format = format) + [name, file_format, handler].compact.join(".") 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 86326d98ed..442258c9d1 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -32,6 +32,14 @@ module Rails # This allows you to override entire operations, like the creation of the # Gemfile, README, or JavaScript files, without needing to know exactly # what those operations do so you can create another template action. + # + # class CustomAppBuilder < Rails::AppBuilder + # def test + # @generator.gem "rspec-rails", group: [:development, :test] + # run "bundle install" + # generate "rspec:install" + # end + # end class AppBuilder def rakefile template "Rakefile" diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml index d2499ea4fb..6da0601b24 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml @@ -1,4 +1,4 @@ -# Oracle/OCI 8i, 9, 10g +# Oracle/OCI 11g or higher recommended # # Requires Ruby/OCI8: # https://github.com/kubo/ruby-oci8 @@ -17,7 +17,7 @@ # cursor_sharing: similar # default: &default - adapter: oracle + adapter: oracle_enhanced pool: <%%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: <%= app_name %> password: @@ -45,7 +45,9 @@ test: # On Heroku and other platform providers, you may have a full connection URL # available as an environment variable. For example: # -# DATABASE_URL="oracle://myuser:mypass@localhost/somedatabase" +# DATABASE_URL="oracle-enhanced://myuser:mypass@localhost/somedatabase" +# +# Note that the adapter name uses a dash instead of an underscore. # # You can use this database configuration with: # diff --git a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index be211e016d..ca48919f9a 100644 --- a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -92,6 +92,7 @@ task default: :test opts[:api] = options.api? opts[:skip_listen] = true opts[:skip_git] = true + opts[:skip_turbolinks] = true invoke Rails::Generators::AppGenerator, [ File.expand_path(dummy_path, destination_root) ], opts @@ -432,7 +433,7 @@ end end def inside_application? - rails_app_path && app_path =~ /^#{rails_app_path}/ + rails_app_path && destination_root.start_with?(rails_app_path.to_s) end def relative_path diff --git a/railties/lib/rails/secrets.rb b/railties/lib/rails/secrets.rb index a083914109..2a95712cd9 100644 --- a/railties/lib/rails/secrets.rb +++ b/railties/lib/rails/secrets.rb @@ -1,4 +1,5 @@ require "yaml" +require "active_support/message_encryptor" module Rails # Greatly inspired by Ara T. Howard's magnificent sekrets gem. 😘 @@ -12,6 +13,7 @@ module Rails end end + @cipher = "aes-128-gcm" @read_encrypted_secrets = false @root = File # Wonky, but ensures `join` uses the current directory. @@ -30,20 +32,19 @@ module Rails end def generate_key - cipher = new_cipher - SecureRandom.hex(cipher.key_len)[0, cipher.key_len] + SecureRandom.hex(OpenSSL::Cipher.new(@cipher).key_len) end def key ENV["RAILS_MASTER_KEY"] || read_key_file || handle_missing_key end - def encrypt(text) - cipher(:encrypt, text) + def encrypt(data) + encryptor.encrypt_and_sign(data) end def decrypt(data) - cipher(:decrypt, data) + encryptor.decrypt_and_verify(data) end def read @@ -97,14 +98,8 @@ module Rails end end - def new_cipher - OpenSSL::Cipher.new("aes-256-cbc") - end - - def cipher(mode, data) - cipher = new_cipher.public_send(mode) - cipher.key = key - cipher.update(data) << cipher.final + def encryptor + @encryptor ||= ActiveSupport::MessageEncryptor.new([ key ].pack("H*"), cipher: @cipher) end end end diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 09931c108a..0f9bf98737 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -11,10 +11,6 @@ require "rails/generators/test_case" require "active_support/testing/autorun" -if defined?(Capbyara) - require "action_dispatch/system_test_case" -end - if defined?(ActiveRecord::Base) ActiveRecord::Migration.maintain_test_schema! @@ -48,12 +44,3 @@ class ActionDispatch::IntegrationTest super end end - -if defined? Capybara - class ActionDispatch::SystemTestCase - def before_setup # :nodoc: - @routes = Rails.application.routes - super - end - end -end diff --git a/railties/lib/rails/test_unit/minitest_plugin.rb b/railties/lib/rails/test_unit/minitest_plugin.rb index e44fe78bbd..8decdb0f4f 100644 --- a/railties/lib/rails/test_unit/minitest_plugin.rb +++ b/railties/lib/rails/test_unit/minitest_plugin.rb @@ -62,9 +62,9 @@ module Minitest options[:patterns] = opts.order! unless run_via.rake? end - def self.rake_run(patterns) # :nodoc: + def self.rake_run(patterns, exclude_patterns = []) # :nodoc: self.run_via = :rake unless run_via.set? - ::Rails::TestRequirer.require_files(patterns) + ::Rails::TestRequirer.require_files(patterns, exclude_patterns) autorun end @@ -88,7 +88,13 @@ module Minitest # If run via `ruby` we've been passed the files to run directly, or if run # via `rake` then they have already been eagerly required. unless run_via.ruby? || run_via.rake? - ::Rails::TestRequirer.require_files(options[:patterns]) + # If there are no given patterns, we can assume that the user + # simply runs the `bin/rails test` command without extra arguments. + if options[:patterns].empty? + ::Rails::TestRequirer.require_files(options[:patterns], ["test/system/**/*"]) + else + ::Rails::TestRequirer.require_files(options[:patterns]) + end end unless options[:full_backtrace] || ENV["BACKTRACE"] diff --git a/railties/lib/rails/test_unit/test_requirer.rb b/railties/lib/rails/test_unit/test_requirer.rb index fe35934abc..92e5fcf0bc 100644 --- a/railties/lib/rails/test_unit/test_requirer.rb +++ b/railties/lib/rails/test_unit/test_requirer.rb @@ -4,10 +4,13 @@ require "rake/file_list" module Rails class TestRequirer # :nodoc: class << self - def require_files(patterns) + def require_files(patterns, exclude_patterns = []) patterns = expand_patterns(patterns) - Rake::FileList[patterns.compact.presence || "test/**/*_test.rb"].to_a.each do |file| + file_list = Rake::FileList[patterns.compact.presence || "test/**/*_test.rb"] + file_list.exclude(exclude_patterns) + + file_list.to_a.each do |file| require File.expand_path(file) end end diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index 4dde3d3c97..ef19bd7626 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -4,15 +4,15 @@ require "rails/test_unit/minitest_plugin" task default: :test -desc "Runs all tests in test folder" +desc "Runs all tests in test folder except system ones" task :test do $: << "test" - pattern = if ENV.key?("TEST") - ENV["TEST"] + + if ENV.key?("TEST") + Minitest.rake_run([ENV["TEST"]]) else - "test" + Minitest.rake_run(["test"], ["test/system/**/*"]) end - Minitest.rake_run([pattern]) end namespace :test do |